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
20 changes: 20 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,26 @@ its sign on its own, so an answer through two says `provided cos(y) >= 0`
| `"sqrt(a - a*sec(x))".ToEntity().Integrate("x")` | `integral(...)` | a logarithm in `tan(x/2)`, times `sgn(tan(x/2))` |
| `"sqrt(1 + csc(x))".ToEntity().Integrate("x")` | `integral(...)` | an arctangent in `tan(pi/4 - x/2)` |

### An even power of the secant or the cosecant under a root is written in the tangent

**Answers where there were none.** `sqrt(a + b csc(x)^2)`, `(a + b sec(x)^2)^(3/2)` and their kin,
Rubi's 4.5.7 and 4.6.7, were declined, while `sqrt(a + b tan(x)^2)` and `sqrt(a + b cot(x)^2)` were
answered through `u = tan(x)`. That substitution writes an even power of the secant or the
cosecant in the tangent, `sec^2 = 1 + tan^2` and `csc^2 = (1 + tan^2)/tan^2`, but went on to do so
only where the tangent, or a sine or a cosine under a root, was already in the integrand. An even
power of the secant or the cosecant under a root goes on now too. The cosecant's answers carry
`sgn(tan(x))`, from the root of `1/tan(x)^2`
([#718](https://github.com/asc-community/AngouriMath/issues/718)).

| Input | Was (2.5.0) | Now |
|---|---|---|
| `"sqrt(a + b*csc(x)^2)".ToEntity().Integrate("x")` | `integral(...)` | arctangents in `sqrt((a + b) tan(x)^2 + b)`, times `sgn(tan(x))` |
| `"(a + b*csc(c + d*x)^2)^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | the same in `tan(c + d x)` and an algebraic part, by the signs of `a` and `b` |
| `"sqrt(a + b*sec(x)^2)".ToEntity().Integrate("x")` | `integral(...)` | arctangents in `tan(x)/sqrt(a + b (1 + tan(x)^2))` |
| `"1/sqrt(a + b*sec(x)^2)".ToEntity().Integrate("x")` | `integral(...)` | an arctangent or a logarithm in the same, by the sign of `a` |
| `"sqrt(1 + csc(x)^2)".ToEntity().Integrate("x")` | `integral(...)` | logarithms and an arctangent in `sqrt(2 tan(x)^2 + 1)`, times `sgn(tan(x))` |
| `"1/sqrt(-1 + csc(x)^2)".ToEntity().Integrate("x")` | `integral(...)` | `sgn(tan(x)) ln(1 + tan(x)^2)/2` |

### A partial-fraction coefficient with symbols in it is in lowest terms, its rational content included

**Improvement, not silent.** The decomposition over written factors with symbols among their
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8464,9 +8464,13 @@ node is Powf(var product, Number.Rational fraction) && fraction is not Number.In
: node);

var tangent = MathS.Tan(x);
// Or a sine or a cosine under a root, for the writing by the sign below; a rational
// function of those is the half-angle substitution's.
if (!expr.ContainsNode(tangent) && !(HasARadicalOf(expr, x) && expr.Nodes.Any(node => node is Sinf or Cosf && node.ContainsNode(x))))
// Or a sine or a cosine under a root, for the writing by the sign below, or an even
// power of the secant or the cosecant under one, which the next step writes in the
// tangent: `sqrt(a + b csc(x)^2)` is `sqrt(a + b + b/tan(x)^2)`. A rational function
// of those is the half-angle substitution's.
if (!expr.ContainsNode(tangent) && !(HasARadicalOf(expr, x) && expr.Nodes.Any(node =>
node is Sinf or Cosf && node.ContainsNode(x)
|| node is Powf(Secantf or Cosecantf, Number.Integer { EInteger.IsEven: true }) && node.ContainsNode(x))))
return null;

// An even power of the secant, cosine, sine or cosecant of x is a rational function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,51 @@ private static void DifferentiatesBack(string integrand)
[InlineData("(sec(x)^2 - 3*sqrt(4*sec(x)^2 + 5*tan(x)^2)*tan(x))/(sin(x)^2*(4*sec(x)^2 + 5*tan(x)^2)^(3/2))")]
public void AnEvenPowerOfTheOthersIsWrittenInTheTangent(string integrand) => DifferentiatesBack(integrand);

/// <summary>
/// The same under a root with no tangent beside it, Rubi's 4.5.7 and 4.6.7:
/// <c>sqrt(a + b csc(x)^2)</c> is <c>sqrt(a + b (1 + u^2)/u^2)</c> under the tangent. On both
/// signs of the tangent, which the cosecant's answer reads, with the symbols pinned before
/// the derivative is taken: <c>sgn(tan(c + d x))</c> is flat only where <c>c</c> and
/// <c>d</c> are real.
/// </summary>
[Theory]
[InlineData("sqrt(a + b*csc(x)^2)")]
[InlineData("(a + b*csc(x)^2)^(3/2)")]
[InlineData("1/(a + b*csc(x)^2)^(3/2)")]
[InlineData("sqrt(a + b*sec(x)^2)")]
[InlineData("1/sqrt(a + b*sec(x)^2)")]
[InlineData("sqrt(a + b*csc(c + d*x)^2)")]
[InlineData("sqrt(1 + csc(x)^2)")]
[InlineData("1/sqrt(-1 + csc(x)^2)")]
public void AnEvenPowerOfTheSecantOrTheCosecantUnderARoot(string integrand)
{
var integral = integrand.ToEntity().Integrate("x");
Assert.DoesNotContain("integral(", integral.Stringize());
var pins = new (string, double)[] { ("a", 1.3), ("b", 0.7), ("c", 0.4), ("d", 1.1) };
var answer = integral.Substitute("C", 0);
var original = integrand.ToEntity();
foreach (var (name, value) in pins)
{
answer = answer.Substitute(name, value);
original = original.Substitute(name, value);
}
var derivative = answer.Differentiate("x");
var compared = 0;
foreach (var at in new[] { -2.6, -0.9, 0.4, 1.1, 1.9, 2.7 })
{
var got = derivative.Substitute("x", at).EvalNumerical();
var want = original.Substitute("x", at).EvalNumerical();
if (got.IsNaN || want.IsNaN)
continue;
compared++;
var difference = Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart);
var scale = Math.Max(1.0, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart));
Assert.True(difference / scale < 1e-9,
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
}
Assert.True(compared >= 4, $"only {compared} points could be compared for {integrand}");
}

/// <summary>
/// An odd power of the sine or the cosine is its sign times a function of the tangent,
/// <c>cos(x) = sgn(cos(x))/sqrt(1 + tan^2)</c> and <c>sin(x) = tan(x) cos(x)</c>, the sign a
Expand Down
Loading