Skip to content

Commit 47e7362

Browse files
Integrate a rational function of x/sqrt(P) for an even quartic P, high powers of two linears, and nine more algebraic shapes (#2023)
Eleven shapes of Rubi's family 1, each answered where the rules declined or ran out of time: - a rational function beside a half-odd power of P = a + b x^2 + c x^4, where it is one of t = x/sqrt(P), since dt/dx = (a - c x^4)/P^(3/2); - (c x)^t, t not whole, as x^t beside (c x)^t x^(-t), constant wherever defined; - two roots whose radicands' quotient is a constant times an even power of x, as one root up to a factor whose square is constant; - a polynomial over high whole powers of two linears, under t = L1/L2; - an algebraic function of 1/x alone, under x = 1/u; - x^m (a + b x^n)^p, m and n whole and p <= -2, by the reduction to p = -1; - a power of a sum of powers of x beside a symbolic power of a binomial, multiplied out into binomial differentials; - a difference of radicands that is one power of x, written as one; - a rational function beside an odd root of a linear past the square, split first where a linear below meets the root at an irrational value; - an odd integrand beside a high power of a quadratic left to u = x^2, and a quartic in one shifted linear to u = d + k x. Chain against master f7f2a7a: pocket of 1,079 rows of family 1, 1,013 -> 1,038 solved, 0 wrong; samples unchanged but family 1's 40-a-file, 1,375 -> 1,379; the 25 rows that moved, alone, 0 -> 25 solved, each in 18-772 ms; no row's allocation grew past 1.3x. x^2/((1 - a x)^16 (1 + a x)^11), which master answers in 20 s and 8.5 GB as 16,292 characters (exactly right; the probe's double evaluation calls it wrong), is 1,380 in 0.12 s. 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 c32fdaa commit 47e7362

14 files changed

Lines changed: 1305 additions & 2 deletions

‎BREAKING-CHANGES.md‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,6 +3028,46 @@ without a common factor
30283028
| `"(c + d*tan(x))^(3/2)/(a + i*a*tan(x))^2".ToEntity().Integrate("x")` | `integral(...)`; 470,119 characters on the unreleased master | 77,377 characters |
30293029
| `"(c + d*tan(x))^(1/2)/(a + i*a*tan(x))^2".ToEntity().Integrate("x")` | `integral(...)`; 258,943 characters on the unreleased master | 71,266 characters |
30303030

3031+
### A rational function of `x/sqrt(P)` for an even quartic `P`, high powers of two linears, and nine more algebraic shapes are integrated
3032+
3033+
**Answers where there were none, and shorter ones.** Rubi's algebraic integrands of these shapes were declined or ran
3034+
out of time ([#233](https://github.com/asc-community/AngouriMath/issues/233)):
3035+
- A rational function beside a half-odd power of `P = a + b x^2 + c x^4`, where it is a rational function of
3036+
`t = x/sqrt(P)`: `dt/dx = (a - c x^4)/P^(3/2)`, so `(a - c x^4)/((a d + a e x^2 + c d x^4) sqrt(P))` is
3037+
`dt/(d + (a e - b d) t^2)`. Which integrands are is read in `y = x^2` modulo `y^2 - w y + a/c`, `w = y + a/(c y)`;
3038+
an elliptic integral does not pass.
3039+
- `(c x)^t`, `t` not whole, written `x^t` beside `(c x)^t x^(-t)`, whose derivative is zero wherever it is defined:
3040+
`(c x)^(-1 - 2 n - n p) (a + b x^n)^p`.
3041+
- Two square roots whose radicands have a constant times an even power of x for their quotient are one root, up to a
3042+
factor whose square is constant: `(g + h x) sqrt(a + b x + c x^2)/(a d + b d x + c d x^2)^(3/2)`.
3043+
- A polynomial over high whole powers of two linears, under `t = L1/L2`: `x^2/((1 - a x)^16 (1 + a x)^11)`.
3044+
- An algebraic function of `1/x` alone, under `x = 1/u`: `1/((a + b/x)^(5/2) (c + d/x)^2)`.
3045+
- `x^m (a + b x^n)^p` for whole `m` and `n` and `p ≤ -2`, by the reduction that raises `p` to `-1`:
3046+
`1/(x^2 (a + b x^3)^5)`.
3047+
- A power of a sum of powers of x beside a symbolic power of a binomial, multiplied out into binomial differentials:
3048+
`(a + b x^n)^3 (c + d x^n)^(-4 - 1/n)`.
3049+
- A difference of radicands that is one power of x, written as one: `x^4/(sqrt(a + b x) + sqrt(a + c x))^3`.
3050+
- A rational function beside an odd root of a linear past the square, split first where a linear below meets the root
3051+
at an irrational value: `1/(x^3 (1 - x^2)^(1/3) (3 + x^2))`.
3052+
- An odd integrand beside a high power of a quadratic is left to `u = x^2`, and a quartic in one shifted linear to
3053+
`u = d + k x`, where the partial fractions spent the budget or wrote pages.
3054+
3055+
Answers the unreleased master gave change length: `x^2/((1 - a x)^16 (1 + a x)^11)` was 16,292 characters there,
3056+
after twenty seconds, and is 1,380 in a tenth of a second; `1/((a + b/x)^(5/2) (c + d/x)^2)` was 16,675 and is 4,667.
3057+
One is longer: `1/(x (1 - x^2)^(1/3) (3 + x^2))`, 342 characters there and 495 now.
3058+
3059+
| Input | Was (2.5.0) | Now |
3060+
|---|---|---|
3061+
| `"(a - c*x^4)/((a*d + a*k*x^2 + c*d*x^4)*sqrt(a + b*x^2 + c*x^4))".ToEntity().Integrate("x")` | `integral(...)` | 1,949 characters |
3062+
| `"(g + h*x)*sqrt(a + b*x + c*x^2)/(a*d + b*d*x + c*d*x^2)^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | 4,376 characters |
3063+
| `"x^2/((1 - a*x)^16*(1 + a*x)^11)".ToEntity().Integrate("x")` | `integral(...)` | 1,380 characters |
3064+
| `"1/((a + b/x)^(5/2)*(c + d/x)^2)".ToEntity().Integrate("x")` | `integral(...)` | 4,667 characters |
3065+
| `"(c*x)^(-1 - 2*n - n*p)*(a + b*x^n)^p".ToEntity().Integrate("x")` | `integral(...)` | 255 characters |
3066+
| `"1/(x^2*(a + b*x^3)^5)".ToEntity().Integrate("x")` | `integral(...)` | 741 characters |
3067+
| `"(d + k*x)^4/(a + b*(d + k*x)^2 + c*(d + k*x)^4)".ToEntity().Integrate("x")` | no answer in twenty seconds | 452 characters |
3068+
| `"1/(x^5*(a + b*x^2)^10)".ToEntity().Integrate("x")` | `integral(...)` | 652 characters, where the unreleased master gave 67,828 |
3069+
| `"1/(x*(1 - x^2)^(1/3)*(3 + x^2))".ToEntity().Integrate("x")` | `integral(...)` | 503 characters, where the unreleased master gave 350 |
3070+
30313071
### A polynomial with symbols in it that is a binomial or an even quartic in a shifted variable is integrated in it
30323072

30333073
**Answers where there were none.** `1/(c^2 x^3 + 3 b c x^2 + 3 b^2 x + 3 a b)` was left unevaluated,

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

Lines changed: 667 additions & 2 deletions
Large diffs are not rendered by default.

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,9 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
726726
// A whole power of a linear in the inverse sine, cosine or hyperbolic cosine of
727727
// `c + d x^2` with `c^2 = 1`, by its recurrence, which closes: by parts it went round.
728728
if ((answer = IndefiniteIntegralSolver.SolveAPowerOfAnInverseFunctionOfAQuadraticByTheRecurrence(expr, x)) is { }) return answer;
729+
// An algebraic function of 1/x alone with a root in it, under x = 1/u, before the linears
730+
// are written once: `1/((a + b/x)^(5/2) (c + d/x)^2)` ran past the budget that way.
731+
if ((answer = IndefiniteIntegralSolver.SolveAnAlgebraicFunctionOfTheReciprocalOfX(expr, x, integrateByParts)) is { }) return answer;
729732
// A product of powers of quotients of linears with one linear in two of them, written
730733
// over each linear once with the constant that takes in front. First, since it answers
731734
// the question asked only, and the polynomial term below writes `1/u` as `u^(-1)` and
@@ -757,6 +760,9 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
757760
// A rational function with numbers for coefficients over a denominator past the twelfth
758761
// degree, by Hermite's reduction before anything searches: nothing below answered one.
759762
if ((answer = IndefiniteIntegralSolver.SolveAHighDegreeRationalFunctionByHermite(expr, x)) is { }) return answer;
763+
// And a polynomial over high whole powers of two linears with a symbol in them, under
764+
// t = L1/L2, where the partial fractions ran past the budget: `x^2/((1 - a x)^16 (1 + a x)^11)`.
765+
if ((answer = IndefiniteIntegralSolver.SolveAPolynomialOverHighWholePowersOfTwoLinears(expr, x)) is { }) return answer;
760766
// A whole power of the square of a polynomial written out, written over its root: the rules
761767
// for a power of a binomial read `(a + b x^2)^4` where `(a^2 + 2 a b x^2 + b^2 x^4)^2` ran
762768
// past the budget.
@@ -1022,6 +1028,11 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
10221028
// split, since Hearn's `e^(x^2)/x + 2x e^(x^2) ln(x) + ...` is a sum whose terms are
10231029
// not elementary apart; at the top only, and only for a tower no closed rule reads.
10241030
if ((answer = IndefiniteIntegralSolver.SolveByRischNormanAnsatz(expr, x)) is { }) return answer;
1031+
// A rational function with numbers beside an odd root of a linear past the square, split over
1032+
// the rationals first where a linear below meets the root at an irrational value:
1033+
// `1/(u^2 (1 - u)^(1/3) (3 + u))`, whose substitution is over the cube root of 4, and which the
1034+
// cancellation below spent five seconds declining.
1035+
if ((answer = IndefiniteIntegralSolver.SolveARationalFunctionBesideAnIrrationalOddRootOfALinearSplitFirst(expr, x, integrateByParts)) is { }) return answer;
10251036
// A quotient of polynomials in x and the functions of x in it, cancelled with those
10261037
// functions as indeterminates and its denominator factored the same way:
10271038
// `(x^2 + 2x sin(x) + sin(x)^2)/(x + sin(x))^2` is `1`, and nothing else reads it.
@@ -1553,6 +1564,20 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
15531564
// A half-odd power of a constant over a polynomial of either sign, written apart with
15541565
// its sign in front. After the substitutions, which answer some of these without it.
15551566
if ((answer = IndefiniteIntegralSolver.SolveByWritingAHalfOddPowerOfAReciprocalWithItsSign(expr, x, integrateByParts)) is { }) return answer;
1567+
// A power of x beside a whole power below -1 of a binomial with a symbol in it, by the
1568+
// reduction that raises the power to -1: `1/(x^2 (a + b x^3)^5)`, which the partial
1569+
// fractions declined past the first power.
1570+
if ((answer = IndefiniteIntegralSolver.SolveABinomialToAWholePowerBelowMinusOneByTheRecurrence(expr, x, integrateByParts)) is { }) return answer;
1571+
// A rational function beside a half-odd power of an even quartic P, as a rational
1572+
// function of x/sqrt(P) where it is one: Rubi's pseudo-elliptic
1573+
// `(a - c x^4)/((a d + a e x^2 + c d x^4) sqrt(a + b x^2 + c x^4))`. Late, since it fires
1574+
// on nothing a rule reading the root as written answers.
1575+
if ((answer = IndefiniteIntegralSolver.SolveByTheVariableOverTheRootOfAnEvenQuartic(expr, x, integrateByParts)) is { }) return answer;
1576+
// A factor `(c x)^t` as `x^t`, `(c x)^t x^(-t)` in front, constant on each interval.
1577+
if ((answer = IndefiniteIntegralSolver.SolveByWritingAPowerOfAMultipleOfXAsAPowerOfX(expr, x, integrateByParts)) is { }) return answer;
1578+
// Two square roots as one, up to a factor whose square is a constant, in front:
1579+
// `sqrt(b - a/x^2)/sqrt(a - b x^2)` is that factor over x.
1580+
if ((answer = IndefiniteIntegralSolver.SolveByWritingTwoRootsAsOneUpToAConstantFactor(expr, x, integrateByParts)) is { }) return answer;
15561581
// The sign of a real-valued factor is constant between its zeros, and goes in
15571582
// front of the antiderivative of the rest. After every rule that reads the sign
15581583
// where it stands: `cos(x) sgn(sin(x))` is `|sin(x)|` by the substitution, and
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 power of x beside a whole power below -1 of a binomial with a symbol in it, by the reduction
16+
/// that raises the power to -1, and the root of a perfect square that leaves one: Rubi's 1.2.3.2.
17+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
18+
/// </summary>
19+
[Trait("Area", "Calculus")]
20+
public sealed class ABinomialToAWholePowerBelowMinusOneIntegralTest
21+
{
22+
[Theory]
23+
[InlineData("1/(x^2*(a + b*x^3)^5)")]
24+
[InlineData("1/(x^3*(a + b*x^3)^5)")]
25+
[InlineData("1/(x^2*(a^2 + 2*a*b*x^3 + b^2*x^6)^(5/2))")]
26+
[InlineData("1/(x^3*(a^2 + 2*a*b*x^3 + b^2*x^6)^(5/2))")]
27+
public void RaisedToTheFirstPower(string integrand)
28+
{
29+
var integral = integrand.ToEntity().Integrate("x");
30+
var text = integral.Stringize();
31+
Assert.DoesNotContain("integral(", text);
32+
Assert.True(text.Length < 5000, $"{text.Length} characters of answer for {integrand}");
33+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7).Substitute("c", 0.4);
34+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
35+
var original = Pinned(integrand.ToEntity());
36+
var compared = 0;
37+
foreach (var at in new[] { -1.2, -0.7, 0.3, 0.8, 1.3, 2.9 })
38+
{
39+
var want = original.Substitute("x", at).EvalNumerical();
40+
var got = derivative.Substitute("x", at).EvalNumerical();
41+
if (want.IsNaN)
42+
continue;
43+
compared++;
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+
Assert.True(compared >= 5, $"only {compared} points could be compared for {integrand}");
49+
}
50+
}
51+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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 factor <c>(c x)^t</c> written as <c>x^t</c>, with <c>(c x)^t x^(-t)</c> in front, whose
16+
/// derivative is zero: Rubi's 1.1.3.2 and 1.2.3.2 with a symbol for the multiple of x.
17+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
18+
/// </summary>
19+
[Trait("Area", "Calculus")]
20+
public sealed class APowerOfAMultipleOfXAsAPowerOfXIntegralTest
21+
{
22+
[Theory]
23+
[InlineData("(c*x)^(-1 - 2*n - n*p)*(a + b*x^n)^p")]
24+
[InlineData("(c*x)^(-1 - 3*n - n*p)*(a + b*x^n)^p")]
25+
[InlineData("(c*x)^(-1 - 4*n - n*p)*(a + b*x^n)^p")]
26+
[InlineData("(d*x)^(-1 - 2*n*(1 + p))*(a^2 + 2*a*b*x^n + b^2*x^(2*n))^p")]
27+
public void WrittenAsAPowerOfX(string integrand)
28+
{
29+
var integral = integrand.ToEntity().Integrate("x");
30+
var text = integral.Stringize();
31+
Assert.DoesNotContain("integral(", text);
32+
Assert.True(text.Length < 5000, $"{text.Length} characters of answer for {integrand}");
33+
// n past the wrap, so that x^n at a negative x is not confined to a half-plane.
34+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7).Substitute("c", -0.4).Substitute("d", 0.3)
35+
.Substitute("n", 2.3).Substitute("p", 0.6);
36+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
37+
var original = Pinned(integrand.ToEntity());
38+
var compared = 0;
39+
foreach (var at in new[] { -1.2, -0.7, 0.3, 0.8, 1.3, 2.9 })
40+
{
41+
var want = original.Substitute("x", at).EvalNumerical();
42+
var got = derivative.Substitute("x", at).EvalNumerical();
43+
if (want.IsNaN)
44+
continue;
45+
compared++;
46+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
47+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
48+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
49+
}
50+
Assert.True(compared >= 5, $"only {compared} points could be compared for {integrand}");
51+
}
52+
}
53+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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 whole power of a binomial in <c>x^n</c> beside a power of another with a symbol in its
16+
/// exponent, written out with the power kept beside each term: each term is a binomial
17+
/// differential in Chebyshev's third case. Rubi's 1.1.3.3.
18+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
19+
/// </summary>
20+
[Trait("Area", "Calculus")]
21+
public sealed class AProductOfSumsBesideASymbolicPowerIntegralTest
22+
{
23+
[Theory]
24+
[InlineData("(a + b*x^n)^3*(c + d*x^n)^(-4 - 1/n)")]
25+
[InlineData("(a + b*x^n)^2*(c + d*x^n)^(-4 - 1/n)")]
26+
public void WrittenOutBesideThePower(string integrand)
27+
{
28+
var integral = integrand.ToEntity().Integrate("x");
29+
var text = integral.Stringize();
30+
Assert.DoesNotContain("integral(", text);
31+
Assert.True(text.Length < 10000, $"{text.Length} characters of answer for {integrand}");
32+
// n past the wrap, so that x^n at a negative x is not confined to a half-plane.
33+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7).Substitute("c", 0.4).Substitute("d", 0.3)
34+
.Substitute("n", 2.3);
35+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
36+
var original = Pinned(integrand.ToEntity());
37+
var compared = 0;
38+
foreach (var at in new[] { -1.2, -0.7, 0.3, 0.8, 1.3, 2.9 })
39+
{
40+
var want = original.Substitute("x", at).EvalNumerical();
41+
var got = derivative.Substitute("x", at).EvalNumerical();
42+
if (want.IsNaN)
43+
continue;
44+
compared++;
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+
Assert.True(compared >= 5, $"only {compared} points could be compared for {integrand}");
50+
}
51+
}
52+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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 power of a linear over a trinomial in its square, written in the linear rather than split
16+
/// over the quartic's quadratics first: Rubi's 1.2.3.2, which ran past the budget split.
17+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
18+
/// </summary>
19+
[Trait("Area", "Calculus")]
20+
public sealed class AQuarticInOneShiftedLinearIntegralTest
21+
{
22+
[Theory]
23+
[InlineData("(d + k*x)^4/(a + b*(d + k*x)^2 + c*(d + k*x)^4)")]
24+
[InlineData("(d + k*x)^2/(a + b*(d + k*x)^2 + c*(d + k*x)^4)")]
25+
public void WrittenInTheShiftedLinear(string integrand)
26+
{
27+
var integral = integrand.ToEntity().Integrate("x");
28+
var text = integral.Stringize();
29+
Assert.DoesNotContain("integral(", text);
30+
Assert.True(text.Length < 5000, $"{text.Length} characters of answer for {integrand}");
31+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7).Substitute("c", 0.4).Substitute("d", 0.9).Substitute("k", 1.1);
32+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
33+
var original = Pinned(integrand.ToEntity());
34+
var compared = 0;
35+
foreach (var at in new[] { -1.2, -0.7, 0.3, 0.8, 1.3, 2.9 })
36+
{
37+
var want = original.Substitute("x", at).EvalNumerical();
38+
var got = derivative.Substitute("x", at).EvalNumerical();
39+
if (want.IsNaN)
40+
continue;
41+
compared++;
42+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
43+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
44+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
45+
}
46+
Assert.True(compared >= 5, $"only {compared} points could be compared for {integrand}");
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)