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
17 changes: 17 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,23 @@ quotient of two such linears the sum is `(b - d t^2)^2 + (c t^2 - a)^2`. Rubi's
| `"(c + d*tan(x))^(3/2)/(a + b*tan(x))^3".ToEntity().Integrate("x")` | `integral(...)` | the same |
| `"1/((a + b*tan(x))^(3/2)*(c + d*tan(x))^(3/2))".ToEntity().Integrate("x")` | `integral(...)`; past a minute on the unreleased master | in the root of the quotient of the two, in a second |

### An odd power of the secant over a whole power of `a + i a tan` is integrated in the sum

**Answers where there were none.** `sec(x)^5/(a + i a tan(x))^2` was declined: the rule that integrates
a power of the secant beside a power of `a + i a tan` in `u = a + i a tan(z)` left whole powers on both
to the rules for the sine and the cosine, which answer `cos(x)^5/(a + i a tan(x))^3` and
`sec(x)^3/(a + i a tan(x))^4` and not `sec(x)^5/(a + i a tan(x))^2`. It takes an odd power `s` of the
secant over the sum's `n`-th where `s + 2 n = 1`, which in `u` is a whole power of `2 a - u` over the root of `u`. And it checks the antiderivative it finds in `u` on the
path, `u = a + i a t` for a real `t`, where it checked the answer in `x`: the expression in `x` carries a
factor constant on intervals and was large enough that the sampled evaluations could not decide, so
right answers were declined after seconds
([#718](https://github.com/asc-community/AngouriMath/issues/718)).

| Input | Was (2.5.0) | Now |
|---|---|---|
| `"sec(x)^5/(a + i*a*tan(x))^2".ToEntity().Integrate("x")` | `integral(...)` | 2,431 characters |
| `"sec(x)^7/(a + i*a*tan(x))^3".ToEntity().Integrate("x")` | `integral(...)` | 3,774 characters |

### A power of the secant beside a power of `a + i a tan` is integrated in the sum, whatever the powers

**Answers where there were none.** `sec(x)^3 sqrt(a + i a tan(x))` was declined, with the rest of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27079,10 +27079,14 @@ static Entity SumOfThePowers(Entity first, Entity second)
|| !TreeAnalyzer.TryGetPolyLinear(argument, x, out var slope, out _) || TreeAnalyzer.IsZero(slope))
return null;
secantPower = secantPower is Number ? secantPower : secantPower.InnerSimplified;
// Whole powers on both are a rational function of the sine and the cosine, which the
// rules for those answer in a fraction of a second, where in u they ran past five:
// `cos(x)^5/(a + i a tan(x))^3`.
if (sumPower is Number.Integer && secantPower is Number.Integer)
// Whole powers on both are left to the rules for the sine and the cosine, which answer
// `cos(x)^5/(a + i a tan(x))^3` and `sec(x)^3/(a + i a tan(x))^4` in a fraction of a second
// where in u they ran past five -- but for an odd power s of the secant over the sum's n-th
// with s + 2 n = 1. Then u^n (sec(z)^2)^((s - 2)/2) is a whole power of 2 A - u over the root
// of u, which is answered in a second, and `sec(x)^5/(a + i a tan(x))^2` was declined by
// every route but this.
if (sumPower is Number.Integer { EInteger: var whole } && secantPower is Number.Integer { EInteger: var secant }
&& !(secant + whole * 2).Equals(EInteger.One))
return null;
Entity constantTerm = Number.Integer.Zero;
foreach (var term in Sumf.LinearChildren(sum))
Expand All @@ -27102,14 +27106,19 @@ static Entity SumOfThePowers(Entity first, Entity second)
// The antiderivative in u was found for a real u, and its conditions say so -- a radicand
// at least zero -- where u = A + i A tan(z) is not real: kept, they hold nowhere on the
// path and the answer has no value at all. The formula is an antiderivative wherever it is
// analytic, so the conditions go, each piecewise taken arm by arm, and an answer is kept
// only where its derivative is the integrand at the sampled points.
// analytic, so the conditions go, each piecewise taken arm by arm, and a formula is kept
// only where its derivative in u is the integrand in u on the path, u = A + i A t for a
// real t, at the sampled points: checked in x, through the factor constant on intervals,
// the expression was large enough that the evaluations could not decide, and right
// answers were declined after seconds.
var onThePath = Variable.CreateUnique(inU + a, "t_path");
var path = a + MathS.i * a * onThePath;
var integrandOnThePath = inU.Substitute(u, path);
foreach (var arm in new[] { 0, -1 })
{
var formula = WithoutConditions(inUAnswer, arm);
var answer = expr * formula.Substitute(u, sum) / differentiatesBackTo;
if (Functions.PartialFractions.DerivativeHoldsAtSampledPoints(answer, expr, x))
return answer;
if (Functions.PartialFractions.HoldsAtSampledPoints(formula.Differentiate(u).Substitute(u, path), integrandOnThePath, onThePath))
return expr * formula.Substitute(u, sum) / differentiatesBackTo;
if (!inUAnswer.Nodes.Any(node => node is Piecewise))
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public sealed class SecantBesideAnImaginaryTangentSumIntegralTest
[InlineData("(k*cos(x))^(3/2)*sqrt(a + i*a*tan(x))")]
[InlineData("cos(x)^9*(a + i*a*tan(x))^(7/2)")]
[InlineData("(m*sec(x))^(2/3)*(a + i*a*tan(x))^(5/3)")]
[InlineData("sec(x)^5/(a + i*a*tan(x))^2")]
public void InTheSum(string integrand)
{
var integral = integrand.ToEntity().Integrate("x");
Expand Down
Loading