Skip to content

Commit b699aa7

Browse files
Ask a hyperbolic quotient over a linear in its cosine as the cosine's, before the tangent (#2053)
Rubi's 6.2.5 sech(x)^3/(a + b cosh(x)) and 6.5.3 sech(x)^4/(a + b sech(x)) ran past the corpus's budget. SolveARationalFunctionOfTheHyperbolicTangent answered each under the tangent of the half argument, a cube of 1 + t^2 beside a symbolic quadratic, in about 118,000 characters. By Osborn's rule each is a rational function of a cosine alone over a sum linear in it, which partial fractions in the cosine answer: 1/(cos(s)^3 (a + b cos(s))) is 2,121 characters. A third mode of SolveAHyperbolicIntegrandAsATrigonometricOne asks that question beside #2042's, ahead of the tangent, only where s stands in cos(s) alone and the sums below the bar are linear in it, to the first power: over the square of one, written out, 6.7.1's (a + b cosh(x))/(b + a cosh(x))^2 took four times the memory in s. The answer in s goes back as the rule writes every one, and is checked by its derivative. Part of #233. Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 890a032 commit b699aa7

4 files changed

Lines changed: 97 additions & 1 deletion

File tree

‎BREAKING-CHANGES.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,22 @@ power, which by parts answers as before ([#233](https://github.com/asc-community
573573
| `"x*(a+b*atanh(c*x))^2/(d+c*d*x)^3".ToEntity().Integrate("x")` | `integral(...)` | 731 characters |
574574
| `"x*(a+b*acoth(c*x))^2/(d+c*d*x)^3".ToEntity().Integrate("x")` | `integral(...)` | 756 characters |
575575

576+
### A hyperbolic quotient over a linear in its cosine is asked as the cosine's
577+
578+
**Answers where there were none, and shorter than master's.** Rubi's 6.2.5 `sech(x)^3/(a + b cosh(x))` and 6.5.3
579+
`sech(x)^4/(a + b sech(x))` ran past the corpus's budget. Under the tangent of the half argument each is a cube of
580+
`1 + t^2` beside a symbolic quadratic, and was answered in about 118,000 characters. By Osborn's rule each is a rational
581+
function of a cosine alone, over a sum linear in it, and that question is now asked first. In the cosine,
582+
`1/(cos(s)^3 (a + b cos(s)))` is a partial fraction in it
583+
([#233](https://github.com/asc-community/AngouriMath/issues/233)).
584+
585+
| Input | Was (2.5.0) | Now |
586+
|---|---|---|
587+
| `"sech(x)^3/(a+b*cosh(x))".ToEntity().Integrate("x")` | `integral(...)` | 2,396 characters, where before this change master gave 118,366 |
588+
| `"sech(x)^4/(a+b*sech(x))".ToEntity().Integrate("x")` | `integral(...)` | 2,412 characters, where before this change master gave 118,032 |
589+
| `"cosh(x)^3/(a+b*cosh(x))".ToEntity().Integrate("x")` | `integral(...)` | 1,108 characters, where before this change master gave 2,858 |
590+
| `"cosh(x)^2/(a+b*sech(x))".ToEntity().Integrate("x")` | `integral(...)` | 802 characters, where before this change master gave 2,820 |
591+
576592
### An arctangent over a power of `d (1 + i c x)` is integrated under the tangent
577593

578594
**Answers where there were none.** `(a + b atan(c x))^2/(d + i c d x)^2` ran out of time, and so did seven more of

‎Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@ static bool APowerOfAQuotientOfLinearsVanishingAtPlusOrMinusOne(Entity inU, Vari
14301430
/// <c>s</c> took seconds to decline, five gigabytes for <c>1/(1 + sinh(x)^3)</c> against 0.2.
14311431
/// </remarks>
14321432
internal static Entity? SolveAHyperbolicIntegrandAsATrigonometricOne(Entity expr, Entity.Variable x, bool integrateByParts, bool rationalToo,
1433-
bool overAQuadraticInTheSine = false)
1433+
bool overAQuadraticInTheSine = false, bool overALinearInTheCosine = false)
14341434
{
14351435
// Only the question asked: a question in s is not cheap to decline, and below the top every
14361436
// sub-question a route gives up on would ask it.
@@ -1498,6 +1498,12 @@ static bool APowerOfAQuotientOfLinearsVanishingAtPlusOrMinusOne(Entity inU, Vari
14981498
&& AFactorAboveAQuadraticInS(inS, s))
14991499
return null;
15001500
var question = MathS.i / slopeOfL * inS;
1501+
// Or, asked as early, only a rational function of the cosine alone over a sum linear in it, or in
1502+
// the secant: under the tangent of the half argument Rubi's `sech(x)^3/(a + b cosh(x))` is a
1503+
// cube of `1 + t^2` beside a symbolic quadratic, answered in 118,366 characters, where in the
1504+
// cosine `1/(cos(s)^3 (a + b cos(s)))` is a partial fraction in it.
1505+
if (overALinearInTheCosine && !IsARationalFunctionOfTheCosineOverALinearInIt(inS, s))
1506+
return null;
15011507
// Or the one rule for a rational function of a sine or a cosine over a symbolic quadratic in
15021508
// it, asked ahead of the exponential substitution and cheap to decline.
15031509
if ((overAQuadraticInTheSine
@@ -1520,6 +1526,26 @@ static bool APowerOfAQuotientOfLinearsVanishingAtPlusOrMinusOne(Entity inU, Vari
15201526
}).Substitute(s, -MathS.i * linear).InnerSimplified;
15211527
return Functions.PartialFractions.DerivativeHoldsAtSampledPoints(answer, expr, x) ? answer : null;
15221528

1529+
// Whether inS holds s only in cos(s), and below the bar a sum linear in it, to the first power:
1530+
// over `b^2 + 2 a b cos(s) + a^2 cos(s)^2`, the square of one, the question in s took four times
1531+
// the memory the tangent did, Rubi's 6.7.1 `(a + b cosh(x))/(b + a cosh(x))^2`.
1532+
static bool IsARationalFunctionOfTheCosineOverALinearInIt(Entity inS, Variable s)
1533+
{
1534+
var cosine = MathS.Cos(s);
1535+
foreach (var node in inS.Nodes)
1536+
if (node.ContainsNode(s) && node != cosine && node != s
1537+
&& node is not (Sumf or Minusf or Mulf or Divf or Powf(_, Number.Integer)))
1538+
return false;
1539+
var (_, below) = Functions.SingleQuotient.Of(inS);
1540+
var y = Variable.CreateUnique(inS, "y_osb");
1541+
bool ASum(Entity node) => node is Sumf or Minusf && node.ContainsNode(cosine);
1542+
bool Linear(Entity sum) => TreeAnalyzer.TryGetPolynomial(sum.Replace(node => node == cosine ? y : node), y, out var read)
1543+
&& read.Keys.Max()!.Equals(EInteger.One);
1544+
var sums = Mulf.LinearChildren(below).Where(ASum).ToList();
1545+
return sums.Count > 0 && sums.All(Linear)
1546+
&& !Mulf.LinearChildren(below).Any(factor => factor is Powf(var @base, _) && ASum(@base));
1547+
}
1548+
15231549
// Whether inS, rational in cos(s) alone or sin(s) alone, has a denominator of degree three or
15241550
// more that t = tan(s/2) or t = tan(s) leaves with an irreducible factor of degree above two,
15251551
// which the rational rules write only as a sum over roots. The cosine, and the square of the

‎Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,9 @@ internal static bool ASumOverRootsWouldAnswer
12421242
// `sinh(x)^2/(a + b sinh(x) + c sinh(x)^2)` is a quartic with symbols, and its partial
12431243
// fractions ran past the budget, where the sine's rule answers the question in s at once.
12441244
if ((answer = IndefiniteIntegralSolver.SolveAHyperbolicIntegrandAsATrigonometricOne(expr, x, integrateByParts, rationalToo: true, overAQuadraticInTheSine: true)) is { }) return answer;
1245+
// And one of the cosine alone over a sum linear in it, which the tangent made a cube of
1246+
// `1 + t^2` beside a symbolic quadratic: `sech(x)^3/(a + b cosh(x))` in 118,366 characters.
1247+
if ((answer = IndefiniteIntegralSolver.SolveAHyperbolicIntegrandAsATrigonometricOne(expr, x, integrateByParts, rationalToo: true, overALinearInTheCosine: true)) is { }) return answer;
12451248
if ((answer = IndefiniteIntegralSolver.SolveARationalFunctionOfTheHyperbolicTangent(expr, x, integrateByParts)) is { }) return answer;
12461249
// A rational function of a sine or a cosine over a quadratic in it with a symbol
12471250
// among the coefficients, split over the quadratic's two roots: under the
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//
2+
// Copyright (c) 2019-2026 Angouri.
3+
// AngouriMath is licensed under MIT.
4+
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
5+
// Website: https://am.angouri.org.
6+
//
7+
8+
using System;
9+
using AngouriMath.Extensions;
10+
using Xunit;
11+
12+
namespace AngouriMath.Tests.Calculus
13+
{
14+
/// <summary>
15+
/// A rational function of the hyperbolic cosine alone over a sum linear in it, or in the secant,
16+
/// asked by Osborn's rule as one of the cosine before the tangent of the half argument: under that
17+
/// tangent Rubi's 6.2.5 <c>sech(x)^3/(a + b cosh(x))</c> and 6.5.3 <c>sech(x)^4/(a + b sech(x))</c>
18+
/// are a cube of <c>1 + t^2</c> beside a symbolic quadratic, and were answered in 118,366 and
19+
/// 118,032 characters, past the corpus's budget.
20+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
21+
/// </summary>
22+
[Trait("Area", "Calculus")]
23+
public sealed class AHyperbolicQuotientOverALinearInItsCosineIntegralTest
24+
{
25+
[Theory]
26+
// Rubi 6.2.5:89.
27+
[InlineData("sech(x)^3/(a + b*cosh(x))")]
28+
// Rubi 6.5.3:139.
29+
[InlineData("sech(x)^4/(a + b*sech(x))")]
30+
[InlineData("cosh(x)^2/(a + b*sech(x))")]
31+
public void IsAnsweredInTheCosine(string integrand)
32+
{
33+
var integral = integrand.ToEntity().Integrate("x");
34+
var text = integral.Stringize();
35+
Assert.DoesNotContain("integral(", text);
36+
Assert.True(text.Length < 5000, $"{integrand} came back in {text.Length} characters");
37+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7);
38+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
39+
var original = Pinned(integrand.ToEntity());
40+
foreach (var at in new[] { -2.2, -0.9, 0.3, 1.4, 2.1 })
41+
{
42+
var want = original.Substitute("x", at).EvalNumerical();
43+
var got = derivative.Substitute("x", at).EvalNumerical();
44+
Assert.False(got.IsNaN, $"d/dx of the antiderivative of {integrand} has no value at x = {at}, where the integrand is {want}");
45+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
46+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
47+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
48+
}
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)