Skip to content

Commit 6e16aae

Browse files
Read hyperbolic integrands through cosh^2 = (1 + i sinh)(1 - i sinh), a symbolic power's own variable, and a phase (#2018)
Five shapes of Rubi's 6.1.1 and 6.7.1, each through an identity the substitutions did not use: - (g + f x)^m cosh(c + d x)^k/(a + i a sinh(c + d x)) and its sinh^k rows: cosh^2 = (1 + i sinh)(1 - i sinh), so the numerator divides by the denominator, leaving a polynomial and a constant over it. - 1/(sech(x) ± i tanh(x))^4 is cosh(x)^4/(1 ± i sinh(x))^4, which the same identity cancels to (1 ∓ i sinh)^2/(1 ± i sinh)^2; cosh^(2m) over (1 ± i sinh)^(2m) and the other way up only. - A symbolic power of sinh, cosh, sech or csch beside an odd power of the other, under u = sinh, cosh, sech or csch; a power of csch stays a power of u, since it is not sinh^(-n) where the sine is negative. - (cosh(x) coth(x))^(3/2) and (csch(x) + sinh(x))^(3/2) are (cosh(x)^2/sinh(x))^(3/2), cosh^3 sinh^(-3/2) times a constant on each side of zero. - Half-odd powers of S = b cosh(x) + c sinh(x) ± sqrt(b^2 - c^2): with T = b sinh + c cosh, d/dx (T S^(n-1)) = n S^n - a (2n - 1) S^(n-1) steps the power to ±1/2. The whole powers are left to the exponential substitution, which writes 1/S^2, 1/S^3 and 1/S^4 in 182, 272 and 416 characters, where the recurrence gave 350, 539 and 728. Chain against master 4877ed2: pocket of 1,756 rows, 1,686 -> 1,723 solved, 0 wrong; samples unchanged or better; the 43 rows that moved, alone, 4 -> 42 solved. Re-measured on master f7f2a7a after the rebase: 14 of the 43 are new there (12 of (e + f x)^k cosh^m/(a + i a sinh) past 20 s -> 0.1-0.9 s, (csch(x) + sinh(x))^(3/2) and ^(5/2) declined -> answered), and the other 29 answer on both, most much cheaper here: sech(a + b x)^n tanh^3 9.12 -> 0.02 GB, 1/(sech(x) + i tanh(x))^4 10.5 -> 0.07 GB and 551 -> 241 characters. 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 732fd0b commit 6e16aae

8 files changed

Lines changed: 947 additions & 0 deletions

‎BREAKING-CHANGES.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,41 @@ power, and the integrand is answered in a fraction of a second
756756
| `"csch(c+d*x)*(a+b*sinh(c+d*x)^4)^2".ToEntity().Integrate("x")` | past fifteen minutes | 426 characters |
757757
| `"csch(c+d*x)*(a+b*sinh(c+d*x)^4)^3".ToEntity().Integrate("x")` | past fifteen minutes | 646 characters |
758758

759+
### Hyperbolic integrands are read through `cosh^2 = (1 + i sinh)(1 - i sinh)`, a symbolic power's own variable, and a phase
760+
761+
**Answers where there were none, and shorter ones.** Rows of these shapes in Rubi's 6.1.1 and 6.7.1 were declined or ran
762+
out of time. Each is answered now through an identity of the hyperbolic functions that the substitutions did not use
763+
([#233](https://github.com/asc-community/AngouriMath/issues/233)):
764+
- `(g + f x)^m cosh(c + d x)^k/(a + i a sinh(c + d x))` and its `sinh^k` rows. `cosh^2 = (1 + i sinh)(1 - i sinh)`, so
765+
the numerator divides by the denominator, leaving a polynomial and a constant over it.
766+
- `1/(sech(x) ± i tanh(x))^4`. It is `cosh(x)^4/(1 ± i sinh(x))^4`, which the same identity cancels to
767+
`(1 ∓ i sinh(x))^2/(1 ± i sinh(x))^2`. Only `cosh^(2m)` over `(1 ± i sinh)^(2m)` and the other way up: cancelling
768+
where a polynomial or another power of the binomial is left made other answers longer.
769+
- A symbolic power of `sinh`, `cosh`, `sech` or `csch` beside an odd power of the other function, with `tanh` and
770+
`coth` read as quotients. `cosh(a + b x)^3 sinh(a + b x)^n` is integrated under `u = sinh`, and
771+
`sech(a + b x)^n tanh(a + b x)^3` under `u = sech`. The power of `csch` stays a power of `u`, because it is not
772+
`sinh^(-n)` where the sine is negative.
773+
- `(cosh(x) coth(x))^(3/2)` and `(csch(x) + sinh(x))^(3/2)`. Both are `(cosh(x)^2/sinh(x))^(3/2)`, which is
774+
`cosh(x)^3 sinh(x)^(-3/2)` times a constant on each side of zero, odd in the cosine.
775+
- Half-odd powers of `S = b cosh(x) + c sinh(x) ± sqrt(b^2 - c^2)`. With `T = b sinh(x) + c cosh(x)` and `a` the
776+
constant term, `d/dx (T S^(n - 1)) = n S^n - a (2n - 1) S^(n - 1)` steps the power to `±1/2`. The whole powers stay
777+
the exponential substitution's, which writes them shorter.
778+
779+
2.5.0 declined or ran out of time on all of the inputs below. The unreleased master answered some of them, and
780+
those answers are now two to twelve times shorter: `(sech(x) + i tanh(x))^2` and `^4` were 437 and 2,916
781+
characters, and `1/(sech(x) + i tanh(x))^2` and `^4` were 372 and 551.
782+
783+
| Input | Was (2.5.0) | Now |
784+
|---|---|---|
785+
| `"(g+f*x)*cosh(c+d*x)^2/(a+i*a*sinh(c+d*x))".ToEntity().Integrate("x")` | `integral(...)` | 366 characters |
786+
| `"cosh(a+b*x)^3*sinh(a+b*x)^n".ToEntity().Integrate("x")` | `integral(...)` | 149 characters |
787+
| `"sech(a+b*x)^n*tanh(a+b*x)^3".ToEntity().Integrate("x")` | past two minutes | 183 characters |
788+
| `"coth(a+b*x)^3*csch(a+b*x)^n".ToEntity().Integrate("x")` | past a minute | 242 characters |
789+
| `"(cosh(x)*coth(x))^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | 247 characters |
790+
| `"1/sqrt(b*cosh(x)+c*sinh(x)+sqrt(b^2-c^2))".ToEntity().Integrate("x")` | `integral(...)` | 409 characters |
791+
| `"1/(sech(x)+i*tanh(x))^4".ToEntity().Integrate("x")` | `integral(...)` | 241 characters |
792+
| `"(sech(x)+i*tanh(x))^4".ToEntity().Integrate("x")` | `integral(...)`, after 54 seconds | 251 characters, where the unreleased master gave 2,916 |
793+
759794
### A power of a polynomial whose leading coefficient is zero spelled otherwise is not divided by it
760795

761796
**Answers where there were none.** `1/((a (1 + x^2))^2 - (a (1 - x^2))^2)^3` was left unevaluated. That is

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

Lines changed: 568 additions & 0 deletions
Large diffs are not rendered by default.

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,8 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
11341134
// And a power of `a + b cos(y) + c sin(y)` with `a^2 = b^2 + c^2`, the same square
11351135
// turned by a phase, in closed form: the substitution search spent the budget on it.
11361136
if ((answer = IndefiniteIntegralSolver.SolveAPowerOfACosineAndASinePlusTheirAmplitude(expr, x)) is { }) return answer;
1137+
// And `a + b cosh(y) + c sinh(y)` with `a^2 = b^2 - c^2`, the hyperbolic one.
1138+
if ((answer = IndefiniteIntegralSolver.SolveAPowerOfAHyperbolicCosineAndSinePlusTheirAmplitude(expr, x)) is { }) return answer;
11371139
// And symbolic powers of `a ± a sin(y)` beside a power of `g cos(y)`, by u = sin(y), where
11381140
// `(1 + u)(1 - u)` is the cosine's square: the half angle wants numeric powers, and the
11391141
// substitution search spent the budget on these. Numeric ones too beside a fractional
@@ -1158,6 +1160,20 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
11581160
if ((answer = IndefiniteIntegralSolver.SolveAHalfOddPowerOfOnePlusAnImaginaryHyperbolicSine(expr, x, integrateByParts)) is { }) return answer;
11591161
// And the cosecant's: a ± i a csch(y) is a (w ± i)^2/(w^2 - 1) in w = e^y.
11601162
if ((answer = IndefiniteIntegralSolver.SolveAPowerOfAnImaginaryHyperbolicCosecantSumInTheExponential(expr, x, integrateByParts)) is { }) return answer;
1163+
// And a polynomial in sinh(y) and cosh(y) over a ± i a sinh(y) beside a power of x,
1164+
// divided out, cosh(y)^2 being (1 + i sinh(y))(1 - i sinh(y)).
1165+
if ((answer = IndefiniteIntegralSolver.SolveByDividingOutOnePlusAnImaginaryHyperbolicSine(expr, x, integrateByParts)) is { }) return answer;
1166+
// A symbolic power of one hyperbolic function beside an odd power of the other, under
1167+
// u = the first: Bioche's substitution reads whole and rational powers. The first may be
1168+
// sech(y) or csch(y), and tanh(y) and coth(y) beside it are read as quotients.
1169+
if ((answer = IndefiniteIntegralSolver.SolveASymbolicPowerOfAHyperbolicFunctionBesideAnOddPowerOfTheOther(expr, x, integrateByParts)) is { }) return answer;
1170+
// And cosh(y)^2 taken out of a fractional power of a quotient, `cosh(x) coth(x)` being
1171+
// `cosh(x)^2/sinh(x)`: Bioche's substitution reads the radicands that are polynomials.
1172+
if ((answer = IndefiniteIntegralSolver.SolveByTakingTheHyperbolicCosineSquaredOutOfAPower(expr, x, integrateByParts)) is { }) return answer;
1173+
// And cosh(y)^(2m) over (1 ± i sinh(y))^(2m), or the other way up, cancelled through
1174+
// cosh(y)^2 = (1 + i sinh(y))(1 - i sinh(y)): `1/(sech(x) + i tanh(x))^4` is
1175+
// `(1 - i sinh(x))^2/(1 + i sinh(x))^2`, where the substitutions spent the budget.
1176+
if ((answer = IndefiniteIntegralSolver.SolveByCancellingOnePlusAnImaginaryHyperbolicSineAgainstTheCosineSquared(expr, x, integrateByParts)) is { }) return answer;
11611177
// A quotient of linears as a function's argument, written over its denominator: a
11621178
// constant plus a multiple of the reciprocal of a linear, which the rules read.
11631179
if ((answer = IndefiniteIntegralSolver.SolveByWritingAQuotientOfLinearsOverItsDenominator(expr, x, integrateByParts)) is { }) return answer;
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 half-odd power of <c>a + b cosh(y) + c sinh(y)</c> with <c>a^2 = b^2 - c^2</c>, a square of
16+
/// the half angle turned by a phase, in closed form through <c>T = b sinh(y) + c cosh(y)</c>.
17+
/// Rubi's 6.7.1.
18+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
19+
/// </summary>
20+
/// <remarks>
21+
/// Compared as complex numbers: with <c>b &lt; |c|</c> the constant is imaginary and so is the
22+
/// base everywhere. Away from the zero of the base where <c>a</c> is negative.
23+
/// </remarks>
24+
[Trait("Area", "Calculus")]
25+
public sealed class APowerOfAHyperbolicCosineAndSinePlusTheirAmplitudeIntegralTest
26+
{
27+
[Theory]
28+
[InlineData("(b*cosh(x) + c*sinh(x) + sqrt(b^2 - c^2))^(5/2)", 2.0, 1.0)]
29+
[InlineData("sqrt(b*cosh(x) + c*sinh(x) - sqrt(b^2 - c^2))", 2.0, 1.0)]
30+
[InlineData("1/sqrt(b*cosh(x) + c*sinh(x) + sqrt(b^2 - c^2))", 2.0, 1.0)]
31+
[InlineData("1/(b*cosh(x) + c*sinh(x) - sqrt(b^2 - c^2))^(5/2)", 2.0, -1.0)]
32+
[InlineData("1/(b*cosh(g + f*x) + c*sinh(g + f*x) + sqrt(b^2 - c^2))^(3/2)", 0.7, 1.1)]
33+
[InlineData("(b*cosh(g + f*x) + c*sinh(g + f*x) - sqrt(b^2 - c^2))^(3/2)", 0.7, 1.1)]
34+
[InlineData("1/sqrt(5*cosh(2*x + 1) + 3*sinh(2*x + 1) + 4)", 0.0, 0.0)]
35+
[InlineData("3*(2*cosh(x) - sinh(x) - sqrt(3))^(-3/2)", 0.0, 0.0)]
36+
public void IsWrittenThroughTheDerivativeOfItsBase(string integrand, double b, double c)
37+
=> DifferentiatesBack(integrand, b, c);
38+
39+
// A whole power is left to the exponential substitution, which writes `1/S^2`, `1/S^3` and
40+
// `1/S^4` shorter than the same recurrence stepped up to `T/(a S)`: answered all the same.
41+
[Theory]
42+
[InlineData("1/(b*cosh(x) + c*sinh(x) + sqrt(b^2 - c^2))^2", 2.0, 1.0)]
43+
[InlineData("1/(b*cosh(x) + c*sinh(x) + sqrt(b^2 - c^2))^3", 2.0, -1.0)]
44+
[InlineData("1/(b*cosh(x) + c*sinh(x) + sqrt(b^2 - c^2))^4", 0.7, 1.1)]
45+
[InlineData("1/(b*cosh(g + f*x) + c*sinh(g + f*x) - sqrt(b^2 - c^2))^3", 2.0, 1.0)]
46+
[InlineData("3*(2*cosh(x) - sinh(x) - sqrt(3))^(-2)", 0.0, 0.0)]
47+
[InlineData("1/(5*cosh(2*x + 1) + 3*sinh(2*x + 1) + 4)^3", 0.0, 0.0)]
48+
public void AWholePowerIsAnsweredToo(string integrand, double b, double c)
49+
=> DifferentiatesBack(integrand, b, c);
50+
51+
private static void DifferentiatesBack(string integrand, double b, double c)
52+
{
53+
var integral = integrand.ToEntity().Integrate("x");
54+
Assert.DoesNotContain("integral(", integral.Stringize());
55+
Entity Pinned(Entity e) => e.Substitute("b", b).Substitute("c", c).Substitute("g", 0.4).Substitute("f", 1.3);
56+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
57+
var original = Pinned(integrand.ToEntity());
58+
foreach (var at in new[] { -1.9, -1.1, -0.2, 0.4, 1.1, 1.9 })
59+
{
60+
var want = original.Substitute("x", at).EvalNumerical();
61+
var got = derivative.Substitute("x", at).EvalNumerical();
62+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
63+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
64+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
65+
}
66+
}
67+
68+
/// <summary>
69+
/// Real and continuous where the integrand is: across the point where <c>T</c> vanishes and
70+
/// the base does not, and on either side of the base's zero where <c>a</c> is negative.
71+
/// The difference of the answer against Simpson's rule.
72+
/// </summary>
73+
[Theory]
74+
[InlineData(1.0, -2.0, 1.0)]
75+
[InlineData(-1.0, 0.1, 2.0)]
76+
[InlineData(-1.0, -3.0, -1.0)]
77+
public void IsAContinuousAntiderivativeOnTheRealLine(double sign, double from, double to)
78+
{
79+
var root = sign > 0 ? "sqrt(3)" : "-sqrt(3)";
80+
var integral = $"1/sqrt(2*cosh(x) + sinh(x) + {root})".ToEntity().Integrate("x").Substitute("C", 0);
81+
Assert.DoesNotContain("integral(", integral.Stringize());
82+
double Integrand(double t) => 1 / Math.Sqrt(2 * Math.Cosh(t) + Math.Sinh(t) + sign * Math.Sqrt(3));
83+
const int steps = 400;
84+
var h = (to - from) / steps;
85+
var simpson = Integrand(from) + Integrand(to);
86+
for (var k = 1; k < steps; k++)
87+
simpson += (k % 2 == 1 ? 4 : 2) * Integrand(from + k * h);
88+
simpson *= h / 3;
89+
var difference = integral.Substitute("x", to).EvalNumerical() - integral.Substitute("x", from).EvalNumerical();
90+
Assert.True(Math.Abs((double)difference.ImaginaryPart) < 1e-9, $"F({to}) - F({from}) is {difference}");
91+
Assert.True(Math.Abs((double)difference.RealPart - simpson) < 1e-7, $"F({to}) - F({from}) is {difference}, Simpson's rule {simpson}");
92+
}
93+
}
94+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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 symbolic power of <c>sinh(y)</c> beside an odd power of <c>cosh(y)</c>, under
16+
/// <c>u = sinh(y)</c>, and the other way about under <c>u = cosh(y)</c>. Rubi's 6.7.1.
17+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
18+
/// </summary>
19+
/// <remarks>Compared as complex numbers: a symbolic power of a negative sine is complex.</remarks>
20+
[Trait("Area", "Calculus")]
21+
public sealed class ASymbolicPowerOfAHyperbolicFunctionBesideAnOddPowerOfTheOtherIntegralTest
22+
{
23+
[Theory]
24+
[InlineData("cosh(a + b*x)^3*sinh(a + b*x)^n")]
25+
[InlineData("cosh(a + b*x)^5*sinh(a + b*x)^n")]
26+
[InlineData("cosh(a + b*x)^m*sinh(a + b*x)^3")]
27+
[InlineData("cosh(a + b*x)^m*sinh(a + b*x)^5")]
28+
[InlineData("2*cosh(x)^3/sinh(x)^n")]
29+
public void IsAPolynomialTimesAPowerInTheOther(string integrand)
30+
{
31+
var integral = integrand.ToEntity().Integrate("x");
32+
Assert.DoesNotContain("integral(", integral.Stringize());
33+
Entity Pinned(Entity e) => e.Substitute("a", 0.4).Substitute("b", 1.3).Substitute("n", 0.37).Substitute("m", -1.6);
34+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
35+
var original = Pinned(integrand.ToEntity());
36+
foreach (var at in new[] { -1.9, -1.1, -0.7, 0.4, 1.1, 1.9 })
37+
{
38+
var want = original.Substitute("x", at).EvalNumerical();
39+
var got = derivative.Substitute("x", at).EvalNumerical();
40+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
41+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
42+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
43+
}
44+
}
45+
46+
/// <summary>
47+
/// The reciprocals to the symbolic power and the tangent and cotangent beside them, read as
48+
/// powers of the two: <c>sech(y)^n tanh(y)^3</c> under <c>u = sech(y)</c>, and
49+
/// <c>coth(y)^3 csch(y)^n</c> under <c>u = csch(y)</c>, whose power is complex where the sine
50+
/// is negative and not that of <c>sinh(y)^(-n)</c>. Rubi's 6.7.1. Both signs of the
51+
/// argument at each slope.
52+
/// </summary>
53+
[Theory]
54+
[InlineData("sech(a + b*x)^n*tanh(a + b*x)^3", 0.4, 1.3)]
55+
[InlineData("coth(a + b*x)^3*csch(a + b*x)^n", 0.4, 1.3)]
56+
[InlineData("coth(a + b*x)^3*csch(a + b*x)^n", 0.9, -0.8)]
57+
[InlineData("sech(a + b*x)^m*tanh(a + b*x)^5", -0.4, 1.3)]
58+
[InlineData("coth(a + b*x)^5*csch(a + b*x)^m", 0.9, -0.8)]
59+
[InlineData("cosh(a + b*x)^n*tanh(a + b*x)^3", 0.4, 1.3)]
60+
[InlineData("sinh(a + b*x)^m*coth(a + b*x)^3", -0.4, 1.3)]
61+
[InlineData("csch(a + b*x)^n*cosh(a + b*x)^3", 0.4, 1.3)]
62+
[InlineData("2*sech(x)^n*sinh(x)^3", 0.0, 1.0)]
63+
public void ReadsTheReciprocalsAndTheQuotients(string integrand, double a, double b)
64+
{
65+
var integral = integrand.ToEntity().Integrate("x");
66+
Assert.DoesNotContain("integral(", integral.Stringize());
67+
Entity Pinned(Entity e) => e.Substitute("a", a).Substitute("b", b).Substitute("n", 0.37).Substitute("m", -1.6);
68+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
69+
var original = Pinned(integrand.ToEntity());
70+
foreach (var at in new[] { -1.9, -1.1, -0.7, 0.4, 1.1, 1.9 })
71+
{
72+
var want = original.Substitute("x", at).EvalNumerical();
73+
var got = derivative.Substitute("x", at).EvalNumerical();
74+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
75+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
76+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
77+
}
78+
}
79+
}
80+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
/// <c>cosh(y)^(2m)</c> over <c>(1 ± i sinh(y))^(2m)</c>, or the other way up, cancelled through
16+
/// <c>cosh(y)^2 = (1 + i sinh(y))(1 - i sinh(y))</c>: <c>1/(sech(x) + i tanh(x))^4</c> is
17+
/// <c>(1 - i sinh(x))^2/(1 + i sinh(x))^2</c>. Rubi's 6.7.1.
18+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
19+
/// </summary>
20+
/// <remarks>Compared as complex numbers: the integrand is complex wherever it is defined.</remarks>
21+
[Trait("Area", "Calculus")]
22+
public sealed class CancellingOnePlusAnImaginaryHyperbolicSineAgainstTheCosineSquaredIntegralTest
23+
{
24+
[Theory]
25+
[InlineData("1/(sech(x) + i*tanh(x))^4")]
26+
[InlineData("1/(sech(x) - i*tanh(x))^4")]
27+
[InlineData("1/(sech(x) + i*tanh(x))^6")]
28+
[InlineData("1/(sech(a + b*x) - i*tanh(a + b*x))^4")]
29+
[InlineData("cosh(x)^4/(1 + i*sinh(x))^4")]
30+
[InlineData("3*cosh(a + b*x)^6/(a - i*a*sinh(a + b*x))^6")]
31+
[InlineData("(sech(x) + i*tanh(x))^6")]
32+
[InlineData("cosh(x)^2/(i + sinh(x))^2")]
33+
public void IsTheQuotientTheCancellationLeaves(string integrand)
34+
{
35+
var integral = integrand.ToEntity().Integrate("x");
36+
Assert.DoesNotContain("integral(", integral.Stringize());
37+
Entity Pinned(Entity e) => e.Substitute("a", -0.4).Substitute("b", 1.3);
38+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
39+
var original = Pinned(integrand.ToEntity());
40+
foreach (var at in new[] { -1.9, -1.1, -0.2, 0.4, 1.1, 1.9 })
41+
{
42+
var want = original.Substitute("x", at).EvalNumerical();
43+
var got = derivative.Substitute("x", at).EvalNumerical();
44+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
45+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
46+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
47+
}
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)