Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,22 @@ the linear at its root now, and each piece is the table's
| `"t^9/(a + b*t)^8".ToEntity().Integrate("t")` | `integral(...)` | powers of `a/b + t` and a logarithm, in 0.03 s |
| `"x^4/(a + b*sqrt(x))^8".ToEntity().Integrate("x")` | `integral(...)` | the same in `sqrt(x)`, in 0.5 s; a minute on the unreleased master |

### Two roots of linears over a linear off the real line are integrated

**Answers where there were none.** `1/(sqrt(x) sqrt(a + b x) (1 - i x))` was declined. The closed forms
for two roots of linears over a third, an arctangent and a logarithm, were chosen by the sign of a
quantity that, over a linear whose coefficients are not real, has none -- `-i a - b < 0` is NaN, the
complex numbers not being ordered -- and on the unreleased master the answer was a piecewise on that
sign which held at no point. Both forms use nothing about their root but `sqrt(q)^2 = q`, so either
is an antiderivative wherever the quantity is not zero, whatever its phase, and with the imaginary
unit in the quantity the one for a positive quantity is taken alone
([#718](https://github.com/asc-community/AngouriMath/issues/718)).

| Input | Was (2.5.0) | Now |
|---|---|---|
| `"1/(sqrt(x)*sqrt(a + b*x)*(1 - i*x))".ToEntity().Integrate("x")` | `integral(...)` | `2 arctan(sqrt(-i a - b) sqrt(x)/sqrt(a + b x))/sqrt(-i a - b)` |
| `"sqrt(x)*sqrt(a + b*x)/(1 + i*x)".ToEntity().Integrate("x")` | `integral(...)` | a root, a logarithm and an arctangent, piecewise in the sign of `b` |

### A polynomial over a power of a quadratic with a sum of symbols in it is reduced

**Answers where there were none.** The reduction of `N(x)/Q(x)^n` divides `N` by the quadratic a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10698,7 +10698,7 @@ is not var (algebraic, ofTheLogarithm, ofTheThirdKind))
var r = LowestOverTheSymbols(d / b);
answer = answer + BySign(r,
ofTheLogarithm * MathS.Ln((1 + MathS.Sqrt(r) * root) / (1 - MathS.Sqrt(r) * root)) / MathS.Sqrt(r),
2 * ofTheLogarithm * MathS.Arctan(MathS.Sqrt(-r) * root) / MathS.Sqrt(-r));
2 * ofTheLogarithm * MathS.Arctan(MathS.Sqrt(-r) * root) / MathS.Sqrt(-r), alsoOffTheRealLine: true);
}
if (ofTheThirdKind != Number.Integer.Zero)
{
Expand All @@ -10708,7 +10708,7 @@ is not var (algebraic, ofTheLogarithm, ofTheThirdKind))
var rho = LowestOverTheSymbols(-atThePole[1] / atThePole[0]);
answer = answer + BySign(rho,
-2 * ofTheThirdKind * MathS.Arctan(MathS.Sqrt(rho) * root) / MathS.Sqrt(rho),
-ofTheThirdKind * MathS.Ln((1 + MathS.Sqrt(-rho) * root) / (1 - MathS.Sqrt(-rho) * root)) / MathS.Sqrt(-rho));
-ofTheThirdKind * MathS.Ln((1 + MathS.Sqrt(-rho) * root) / (1 - MathS.Sqrt(-rho) * root)) / MathS.Sqrt(-rho), alsoOffTheRealLine: true);
}
return (constantBelow == Number.Integer.One ? answer : answer / constantBelow).InnerSimplified;
}
Expand Down Expand Up @@ -11316,10 +11316,21 @@ private sealed record ALinearBesideTheRoot(Entity Linear, Entity G, Entity H, in
// where it holds, for a quantity with symbols in it, as `1/(a - x^2)` is answered. A
// number times even powers of symbols has the number's sign wherever the symbols are
// real and not zero, which is the generic case: `-b^2` in `a^2 - b^2 x^2` is negative.
private static Entity BySign(Entity quantity, Entity wherePositive, Entity whereNegative)
=> SignOfANumberTimesEvenPowers(quantity) is { } sign
? (sign < 0 ? whereNegative : wherePositive)
: MathS.Piecewise((wherePositive, new Greaterf(quantity, Number.Integer.Zero)), (whereNegative, new Lessf(quantity, Number.Integer.Zero)));
// Off the real line neither sign holds, the complex numbers not being ordered, and the
// piecewise had no arm there: `1/(sqrt(x) sqrt(a + b x) (1 - i x))` was answered with
// nothing at any point. Where the caller's form for a positive quantity uses nothing about
// its root but `sqrt(z)^2 = z`, as an arctangent or a logarithm does and an arcsine does
// not, it is an antiderivative wherever the quantity is not zero, whatever its phase -- the
// sign only chooses the form that is real on the real line -- and the caller says so with
// alsoOffTheRealLine: a quantity with the imaginary unit in it then takes that form alone.
private static Entity BySign(Entity quantity, Entity wherePositive, Entity whereNegative, bool alsoOffTheRealLine = false)
{
if (SignOfANumberTimesEvenPowers(quantity) is { } sign)
return sign < 0 ? whereNegative : wherePositive;
if (alsoOffTheRealLine && HoldsTheImaginaryUnit(quantity.InnerSimplified))
return wherePositive;
return MathS.Piecewise((wherePositive, new Greaterf(quantity, Number.Integer.Zero)), (whereNegative, new Lessf(quantity, Number.Integer.Zero)));
}

// The same where the form for a positive first quantity is chosen by the sign of a second,
// as one piecewise rather than one inside another.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Copyright (c) 2019-2026 Angouri.
// AngouriMath is licensed under MIT.
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
// Website: https://am.angouri.org.
//

using System;
using AngouriMath.Extensions;
using Xunit;

namespace AngouriMath.Tests.Calculus
{
/// <summary>
/// The roots of two linears over a linear whose coefficients are not real, where the closed
/// forms chose between an arctangent and a logarithm by the sign of a quantity that has none,
/// and the answer held at no point.
/// <a href="https://github.com/asc-community/AngouriMath/issues/718">#718</a>
/// </summary>
/// <remarks>
/// Compared as complex numbers, the integrands being complex, and differentiated before the
/// symbols are pinned: a piecewise arm whose condition compares a number off the real line, pinned
/// first and then differentiated, made the whole derivative NaN.
/// </remarks>
[Trait("Area", "Calculus")]
public sealed class RootsOfLinearsOffTheRealLineIntegralTest
{
[Theory]
[InlineData("1/(sqrt(x)*sqrt(a + b*x)*(1 - i*x))")]
[InlineData("sqrt(x)/(sqrt(a + b*x)*(1 + i*x))")]
[InlineData("sqrt(x)*sqrt(a + b*x)/(1 + i*x)")]
public void IsIntegratedOverTheLinear(string integrand)
{
var integral = integrand.ToEntity().Integrate("x");
Assert.DoesNotContain("integral(", integral.Stringize());
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.6);
var derivative = Pinned(integral.Substitute("C", 0).Differentiate("x"));
var original = Pinned(integrand.ToEntity());
foreach (var at in new[] { 0.3, 0.7, 1.2, 2.0 })
{
var want = original.Substitute("x", at).EvalNumerical();
var got = derivative.Substitute("x", at).EvalNumerical();
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
}
}
}
}
Loading