diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index e69635cad..85189f790 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -400,6 +400,27 @@ whose denominator in the tangent is a product of linears
| `"sec(c + d*x)^3/(a*cos(c + d*x) + b*sin(c + d*x))^4".ToEntity().Integrate("x")` | `integral(...)` | answered, in 9,322 characters |
| `"1/(a*sec(x) + b*tan(x))^4".ToEntity().Integrate("x")` | `integral(...)` | answered, in 6,548 characters |
+### An odd power of a sine or a cosine of a logarithm is integrated, and a resonance on a sign is declined
+
+**Answers where there were none.** `x^m sin(a + b ln(k x^n))^3` and the cosine's cube were declined, though the first
+and second powers were answered (Rubi's 4.7.5). Under `t = ln(k x^n)` each one is an exponential times a power of a
+sine, `e^((m + 1) t/n) sin(a + b t)^3`. The rule that closes that answers only the question asked, and the
+substitution asked it one level down. A logarithm's substitution now asks that integrand as the question
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+**No answer where there was a wrong one.** `e^(x/n) sin(x sqrt(-1/n^2))` is resonant: `1/n + i sqrt(-1/n^2)` is zero
+for a positive `n`, and `1/n - i sqrt(-1/n^2)` is zero for a negative one. The answer divided by one of them, and had
+no value at any point. It is declined now ([#1852](https://github.com/asc-community/AngouriMath/issues/1852)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"sin(ln(x))^3".ToEntity().Integrate("x")` | `integral(...)` | 130 characters |
+| `"sin(a + b*ln(x))^3".ToEntity().Integrate("x")` | `integral(...)` | 909 characters |
+| `"x^2*sin(a + b*ln(k*x^n))^3".ToEntity().Integrate("x")` | `integral(...)` | 1,605 characters |
+| `"x^m*cos(a + b*ln(k*x^n))^3".ToEntity().Integrate("x")` | `integral(...)` | 1,907 characters |
+| `"sin(a + b*ln(k*x^n))^4/x^2".ToEntity().Integrate("x")` | `integral(...)` | 2,083 characters |
+| `"exp(x/n)*sin(x*sqrt((-1)/n^2))".ToEntity().Integrate("x")` | an answer with no value anywhere, divided by `1/n^2 + (-1/n^2)` | `integral(...)` |
+
### An odd power of a quadratic's derivative over a power of the quadratic is integrated in the quadratic
**Shorter answers, and answers where there were none.** `(b + 2c x)^9/(a + b x + c x^2)^3` was answered through the
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 3fcac5325..5f5414950 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -8146,12 +8146,24 @@ private static (Entity Elementary, Entity Si, Entity Ci) APowerTimesASineOrACosi
// `e^(i arctan(a x))/sqrt(c + a^2 c x^2)` under `x = tan(u)/a` is `e^(i u) cos(u)`.
var plus = ((onTheCosine - MathS.i * onTheSine) / 2).InnerSimplified;
var minus = ((onTheCosine + MathS.i * onTheSine) / 2).InnerSimplified;
+ var towardsPlus = (rate + MathS.i * frequency).InnerSimplified;
+ var towardsMinus = (rate - MathS.i * frequency).InnerSimplified;
+ static bool Vanishes(Entity exponent) => exponent.Evaled is Number.Complex { IsZero: true }
+ || exponent.Vars.Any() && Functions.PartialFractions.Bare(exponent.Simplify()).Evaled is Number.Complex { IsZero: true };
+ var plusVanishes = Vanishes(towardsPlus);
+ var minusVanishes = Vanishes(towardsMinus);
+ // One of the two vanishes, since their product is the scale, and which one can rest on
+ // a sign: with `a = 1/n` and `b = sqrt(-1/n^2)`, `a + i b` is zero for a positive `n`
+ // and `a - i b` for a negative one. Neither seen to, the term over it divides by zero
+ // on one side of the sign, and the answer had no value anywhere.
+ if (!plusVanishes && !minusVanishes)
+ return null;
Entity resonant = Number.Integer.Zero;
- foreach (var (coefficient, exponent) in new[] { (plus, (rate + MathS.i * frequency).InnerSimplified), (minus, (rate - MathS.i * frequency).InnerSimplified) })
+ foreach (var (coefficient, exponent, vanishes) in new[] { (plus, towardsPlus, plusVanishes), (minus, towardsMinus, minusVanishes) })
{
if (coefficient.Evaled is Number.Complex { IsZero: true })
continue;
- var term = exponent.Evaled is Number.Complex { IsZero: true } ? polynomial : polynomial * MathS.Pow(MathS.e, exponent * x);
+ var term = vanishes ? polynomial : polynomial * MathS.Pow(MathS.e, exponent * x);
if (Integration.ComputeIndefiniteIntegral(term.InnerSimplified, x, integrateByParts: false) is not { } termIntegral || termIntegral.Nodes.Any(node => node == MathS.NaN))
return null;
resonant += coefficient * termIntegral;
@@ -9820,12 +9832,83 @@ node is Logf(var @base, var argument) && !@base.ContainsNode(x) && @base != Math
if (integrand is Providedf(var inner, _))
integrand = inner;
- if (Integration.ComputeIndefiniteIntegral(integrand, u, integrateByParts) is not { } result)
+ if (TheIntegrandInTheLogarithm(integrand, u, integrateByParts) is not { } result)
return null;
var back = result.Substitute(u, MathS.Ln(x));
return IsARadicalFunctionOfWholePowersOfTheExponential(inU, u) ? back.Provided(x > Number.Integer.Zero) : back;
}
+ ///
+ /// The integral of what a logarithm's substitution makes of the integrand, in the logarithm
+ /// ; an exponential times whole powers of sines and cosines asked at the top.
+ ///
+ ///
+ /// x^m sin(a + b ln(c x^n))^3 is e^((m + 1) t/n) sin(a + b t)^3 in t, which the
+ /// closed rule for an exponential times a trigonometric answers only when asked, and as the
+ /// substitution's integrand it is one level down: the cube was declined where the first and
+ /// second powers, which other rules answer, were not. The substitution is exact, so its integrand
+ /// is the question asked in another variable. Once: an integrand asked so does not lift its own
+ /// substitution again. Rubi's 4.7.5.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ private static Entity? TheIntegrandInTheLogarithm(Entity integrand, Entity.Variable t, bool integrateByParts)
+ {
+ if (!Integration.AnsweringTheQuestionAsked || !IsAnExponentialTimesPowersOfSinesAndCosines(integrand, t))
+ return Integration.ComputeIndefiniteIntegral(integrand, t, integrateByParts);
+ if (askingTheIntegrandInTheLogarithm)
+ {
+ var answer = Integration.ComputeIndefiniteIntegral(integrand, t, integrateByParts);
+ if (answer is null)
+ Integration.DeclinedForItsScope();
+ return answer;
+ }
+ askingTheIntegrandInTheLogarithm = true;
+ try
+ {
+ return Integration.ComputeAsAQuestionOfItsOwn(integrand, t, integrateByParts);
+ }
+ finally
+ {
+ askingTheIntegrandInTheLogarithm = false;
+ }
+ }
+
+ /// Whether is asking at the top already.
+ [System.ThreadStatic] private static bool askingTheIntegrandInTheLogarithm;
+
+ ///
+ /// Whether is a constant times an exponential of a linear in
+ /// times whole positive powers of sines and cosines of linears in it.
+ ///
+ private static bool IsAnExponentialTimesPowersOfSinesAndCosines(Entity expr, Entity.Variable t)
+ {
+ if (expr is Divf(var above, var below))
+ {
+ if (below.ContainsNode(t))
+ return false;
+ expr = above;
+ }
+ var exponential = false;
+ var trigonometric = false;
+ foreach (var factor in Mulf.LinearChildren(expr))
+ {
+ if (!factor.ContainsNode(t))
+ continue;
+ if (factor is Powf(var @base, var exponent) && !@base.ContainsNode(t))
+ {
+ if (!TreeAnalyzer.TryGetPolyLinear(exponent, t, out _, out _))
+ return false;
+ exponential = true;
+ continue;
+ }
+ var function = factor is Powf(var raised, Number.Integer power) && power.EInteger.Sign > 0 ? raised : factor;
+ if (function is not (Sinf or Cosf) || !TreeAnalyzer.TryGetPolyLinear(function.DirectChildren.First(), t, out _, out _))
+ return false;
+ trigonometric = true;
+ }
+ return exponential && trigonometric;
+ }
+
///
/// Whether holds only in exponentials
/// e^(k t + a) with a whole k, some of them under a power that is not
@@ -9910,7 +9993,7 @@ node is Powf(var @base, var exponent) && @base == MathS.e && exponent.ContainsNo
var integrand = Functions.SingleQuotient.Combine(inT * MathS.Pow(MathS.e, (mPlusOne / n).InnerSimplified * t)).InnerSimplified;
if (integrand is Providedf(var bare, _))
integrand = bare;
- if (Integration.ComputeIndefiniteIntegral(integrand, t, integrateByParts) is not { } inTIntegral)
+ if (TheIntegrandInTheLogarithm(integrand, t, integrateByParts) is not { } inTIntegral)
return null;
// Of ln(x) itself, K is 1, and written as x^(m + 1) x^(-(m + 1)) it is not seen to be.
var k = logarithms[0].Antilogarithm == x ? Number.Integer.One
diff --git a/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs
new file mode 100644
index 000000000..76f4a83ce
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs
@@ -0,0 +1,60 @@
+//
+// 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
+{
+ ///
+ /// A power of x times a whole power of a sine or a cosine of a + b ln(k x^n), which
+ /// in the logarithm is an exponential times a power of a sine or a cosine. Rubi's 4.7.5.
+ /// #718
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class AnOddPowerOfATrigonometricOfALogarithmIntegralTest
+ {
+ [Theory]
+ [InlineData("sin(ln(x))^3", 500)]
+ [InlineData("sin(a + b*ln(x))^3", 2000)]
+ [InlineData("x^2*sin(a + b*ln(k*x^n))^3", 3000)]
+ [InlineData("sin(a + b*ln(k*x^n))^3/x^3", 3000)]
+ [InlineData("x^m*cos(a + b*ln(k*x^n))^3", 3000)]
+ [InlineData("sin(a + b*ln(k*x^n))^4/x^2", 4000)]
+ public void DifferentiatesBack(string integrand, int atMostCharacters)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Assert.True(integral.Stringize().Length <= atMostCharacters, $"{integral.Stringize().Length} characters");
+ Entity Pinned(Entity e) => e.Substitute("a", "1/4".ToEntity()).Substitute("b", "3/2".ToEntity())
+ .Substitute("k", 2).Substitute("n", 3).Substitute("m", "5/2".ToEntity());
+ var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
+ var original = Pinned(integrand.ToEntity());
+ foreach (var at in new[] { "0.35", "0.6", "1.1", "1.4" })
+ {
+ var want = original.Substitute("x", at.ToEntity()).EvalNumerical();
+ var got = derivative.Substitute("x", at.ToEntity()).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)),
+ $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
+ }
+ }
+
+ ///
+ /// a + i b or a - i b is zero, which one by the sign of n, and an answer
+ /// dividing by either had no value anywhere.
+ /// #1852
+ ///
+ [Theory]
+ [InlineData("exp(x/n)*sin(x*sqrt((-1)/n^2))")]
+ [InlineData("exp(x/n)*sin(a + x*sqrt((-1)/n^2))")]
+ [InlineData("sin(a + ln(k*x^n)*sqrt((-1)/n^2))")]
+ public void AResonanceOnASignIsDeclined(string integrand) =>
+ Assert.Contains("integral(", integrand.ToEntity().Integrate("x").Stringize());
+ }
+}