Skip to content

Commit 78680f0

Browse files
An imaginary sum of a cosine and a sine beside powers of the secant, over the cosine (#1846)
* An imaginary sum of a cosine and a sine beside powers of the secant, over the cosine Part of #718. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura * Measure the entry's six rows on 2.5.0, master 180301c and the branch Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 180301c commit 78680f0

4 files changed

Lines changed: 118 additions & 0 deletions

File tree

‎BREAKING-CHANGES.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,25 @@ two more of Rubi's 4.5.2.3. The two sums multiply to `-a c tan^2`, so in `u = a
381381
| `"sec(e + f*x)*(a + a*sec(e + f*x))^m*(c - c*sec(e + f*x))^(5/2)".ToEntity().Integrate("x")` | `integral(...)` | 469 characters |
382382
| `"sec(e + f*x)*(a + a*sec(e + f*x))^m*sqrt(c - c*sec(e + f*x))".ToEntity().Integrate("x")` | `integral(...)` | 268 characters |
383383

384+
### `a cos + i a sin` beside powers of the secant is written over the cosine
385+
386+
**Answers where there were none, and shorter ones.** `sec(c + d x)^5/(a cos(c + d x) + i a sin(c + d x))^2` was declined,
387+
and so were `sec^4` over the cube, and `sec^6` over the sum and over its cube, Rubi's 4.7.2. `A cos(y) ± i A sin(y)` below
388+
the bar, with nothing but cosines and secants of `y` beside it, is written `A cos(y) (1 ± i tan(y))` now, where the
389+
exponential it also is gave nothing the rules read: a power of the secant over a power of `1 ± i tan(y)` is what the
390+
rules for `a + i a tan` take. 2.5.0 declined all six below; where the unreleased master answered, `sec^4` over the sum
391+
and `sec^2` over its cube, the answers are a quarter and three-fifths the size
392+
([#718](https://github.com/asc-community/AngouriMath/issues/718)).
393+
394+
| Input | Was (2.5.0) | Now |
395+
|---|---|---|
396+
| `"sec(c + d*x)^6/(a*cos(c + d*x) + i*a*sin(c + d*x))".ToEntity().Integrate("x")` | `integral(...)` | 419 characters |
397+
| `"sec(c + d*x)^5/(a*cos(c + d*x) + i*a*sin(c + d*x))^2".ToEntity().Integrate("x")` | `integral(...)` | 668 characters |
398+
| `"sec(c + d*x)^4/(a*cos(c + d*x) + i*a*sin(c + d*x))^3".ToEntity().Integrate("x")` | `integral(...)` | 639 characters |
399+
| `"sec(c + d*x)^6/(a*cos(c + d*x) + i*a*sin(c + d*x))^3".ToEntity().Integrate("x")` | `integral(...)` | 771 characters |
400+
| `"sec(c + d*x)^4/(a*cos(c + d*x) + i*a*sin(c + d*x))".ToEntity().Integrate("x")` | `integral(...)` | 209 characters, where the unreleased master gave 780 |
401+
| `"sec(c + d*x)^2/(a*cos(c + d*x) + i*a*sin(c + d*x))^3".ToEntity().Integrate("x")` | `integral(...)` | 488 characters, where the unreleased master gave 810 |
402+
384403
### An even rational function with symbols in it is not searched for a substitution
385404

386405
**Answers where there were none.** `(d + e x^2 + f x^4)/(x^4 (a + b x^2 + c x^4)^2)` ran past a minute: the

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28604,6 +28604,62 @@ node is Powf(Mulf(var left, var right), Number.Integer power)
2860428604
return Integration.ComputeAsTheSameQuestion((above / rewritten).InnerSimplified, x, integrateByParts);
2860528605
}
2860628606

28607+
/// <summary>
28608+
/// <c>A cos(y) + i A sin(y)</c> below the bar, with nothing but cosines of <c>y</c> and their
28609+
/// reciprocals beside it, written as <c>A cos(y) (1 + i tan(y))</c>, and <c>A cos(y) - i A sin(y)</c>
28610+
/// as <c>A cos(y) (1 - i tan(y))</c>: a power of the secant over a power of <c>1 ± i tan(y)</c>,
28611+
/// which the rules for that sum answer.
28612+
/// </summary>
28613+
/// <remarks>
28614+
/// Where the exponential <see cref="SolveByWritingAnImaginarySumOfACosineAndASineAsAnExponential"/>
28615+
/// writes declines: an odd power of the secant beside it, `sec(y)^5/(a cos(y) + i a sin(y))^2`,
28616+
/// is a half-odd power of `1 + tan(y)^2` in the tangent, and that is `(1 - i t)^(5/2) (1 + i t)^(1/2)`
28617+
/// over the sum, which the rules for `a + i a tan` take. Rubi's 4.7.2.
28618+
/// https://github.com/asc-community/AngouriMath/issues/718
28619+
/// </remarks>
28620+
internal static Entity? SolveByWritingAnImaginarySumOfACosineAndASineOverTheCosine(Entity expr, Entity.Variable x, bool integrateByParts)
28621+
{
28622+
var (above, below) = Functions.SingleQuotient.Of(Functions.SingleQuotient.Combine(expr));
28623+
if (!below.ContainsNode(x))
28624+
return null;
28625+
Entity? argumentOfThePair = null;
28626+
var rewritten = below.Replace(node =>
28627+
{
28628+
if (node is not (Sumf or Minusf) || !node.ContainsNode(x)
28629+
|| !TryReadACosineAndASine(node, x, out var cosineCoefficient, out var sineCoefficient, out var argument)
28630+
|| argumentOfThePair is { } && argumentOfThePair != argument)
28631+
return node;
28632+
var ratio = Functions.PartialFractions.Bare((sineCoefficient / cosineCoefficient).InnerSimplified);
28633+
if (ratio.Evaled is not Number.Complex)
28634+
ratio = Functions.PartialFractions.Bare(ratio.Simplify());
28635+
var plus = ratio.Evaled == MathS.i.Evaled;
28636+
if (!plus && ratio.Evaled != (-MathS.i).Evaled)
28637+
return node;
28638+
argumentOfThePair = argument;
28639+
return cosineCoefficient * MathS.Cos(argument) * (1 + (plus ? MathS.i : -MathS.i) * MathS.Tan(argument));
28640+
});
28641+
if (rewritten == below || argumentOfThePair is not { } y)
28642+
return null;
28643+
// Nothing beside the pair but cosines and secants of its argument: a sine elsewhere is the
28644+
// exponential's.
28645+
bool OnlyCosines(Entity side, bool andTheTangent) => side.Nodes.All(node => node switch
28646+
{
28647+
Tanf(var a) => andTheTangent && a == y,
28648+
Sinf or Tanf or Cotanf or Cosecantf => false,
28649+
Cosf(var a) => a == y,
28650+
Secantf(var a) => a == y,
28651+
_ => true,
28652+
});
28653+
if (!OnlyCosines(above, andTheTangent: false) || !OnlyCosines(rewritten, andTheTangent: true))
28654+
return null;
28655+
// A whole power of the product split, so that the power of the sum stands on its own.
28656+
rewritten = rewritten.Replace(node =>
28657+
node is Powf(Mulf(var left, var right), Number.Integer power) && (left.Nodes.Any(n => n is Tanf) || right.Nodes.Any(n => n is Tanf))
28658+
? MathS.Pow(left, power) * MathS.Pow(right, power)
28659+
: node);
28660+
return Integration.ComputeAsTheSameQuestion((above / rewritten).InnerSimplified, x, integrateByParts);
28661+
}
28662+
2860728663
/// <summary>
2860828664
/// Bioche's first two rules for the hyperbolic functions: a rational function of
2860928665
/// <c>sinh(y)</c> and <c>cosh(y)</c> that is odd in the hyperbolic sine is a rational

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ private static Entity Normalized(Entity expr, Entity.Variable x) =>
692692
if ((answer = IndefiniteIntegralSolver.SolveByWritingAnImaginaryTangentAsAnExponential(expr, x, integrateByParts)) is { }) return answer;
693693
// And `A cos(z) + i A sin(z)`, which is `A e^(i z)`, where no rotation is real.
694694
if ((answer = IndefiniteIntegralSolver.SolveByWritingAnImaginarySumOfACosineAndASineAsAnExponential(expr, x, integrateByParts)) is { }) return answer;
695+
if ((answer = IndefiniteIntegralSolver.SolveByWritingAnImaginarySumOfACosineAndASineOverTheCosine(expr, x, integrateByParts)) is { }) return answer;
695696
// Exponentials of quadratics, with sines, cosines and sums of them multiplied out:
696697
// each term is the Gaussian's, where the search would take the product by parts.
697698
if ((answer = IndefiniteIntegralSolver.SolveAProductOfExponentialsOfQuadratics(expr, x)) is { }) return answer;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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>a cos(y) + i a sin(y)</c> beside powers of the secant is written <c>a cos(y) (1 + i tan(y))</c>,
16+
/// which the rules for <c>a + i a tan</c> take. Rubi's 4.7.2.
17+
/// <a href="https://github.com/asc-community/AngouriMath/issues/718">#718</a>
18+
/// </summary>
19+
[Trait("Area", "Calculus")]
20+
public sealed class AnImaginaryCosineAndSineSumOverTheCosineIntegralTest
21+
{
22+
[Theory]
23+
[InlineData("sec(x)^5/(a*cos(x) + i*a*sin(x))^2")]
24+
[InlineData("sec(x)^6/(a*cos(x) - i*a*sin(x))")]
25+
public void DifferentiatesBack(string integrand)
26+
{
27+
var integral = integrand.ToEntity().Integrate("x");
28+
Assert.DoesNotContain("integral(", integral.Stringize());
29+
Entity Pinned(Entity e) => e.Substitute("a", 3);
30+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
31+
var original = Pinned(integrand.ToEntity());
32+
foreach (var at in new[] { -1.1, -0.4, 0.3, 1.2 })
33+
{
34+
var want = original.Substitute("x", at).EvalNumerical();
35+
var got = derivative.Substitute("x", at).EvalNumerical();
36+
var scale = Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart));
37+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart) < 1e-9 * scale,
38+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
39+
}
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)