diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 10acfc723..fcd59239a 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -400,7 +400,7 @@ 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 +### An odd power of a sine or a cosine of a logarithm is integrated, and a resonance on a sign holds on both sides **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 @@ -410,7 +410,10 @@ substitution asked it one level down. A logarithm's substitution now asks that i **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)). +no value at any point. Euler's identity is written in `j = -(1/n)/sqrt(-1/n^2)` in place of `i` now: `j^2` is `-1` +whichever sign `n` has, and `1/n + j sqrt(-1/n^2)` is zero by construction, so one answer holds on both sides. A +logarithm's substitution reaches the same integrand, so `x^m sin(a + ln(k x^n) sqrt(-(1 + m)^2/n^2))` and its powers are +answered too ([#1852](https://github.com/asc-community/AngouriMath/issues/1852)). | Input | Was (2.5.0) | Now | |---|---|---| @@ -419,7 +422,10 @@ no value at any point. It is declined now ([#1852](https://github.com/asc-commun | `"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(...)` | +| `"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)` | 110 characters, right for either sign of `n` | +| `"exp(x/n)*sin(a + x*sqrt((-1)/n^2))".ToEntity().Integrate("x")` | an answer with no value anywhere | 254 characters | +| `"x^m*sin(a + ln(k*x^n)*sqrt(-(1 + m)^2/n^2))".ToEntity().Integrate("x")` | `integral(...)` | 465 characters | +| `"x^2*sin(a + ln(k*x^n)*sqrt((-1)/n^2))^3".ToEntity().Integrate("x")` | `integral(...)` | 1,873 characters | ### An odd power of a quadratic's derivative over a power of the quadratic is integrated in the quadratic @@ -2170,8 +2176,8 @@ by `(m + 1)^2 + B^2`, which an imaginary `B` can make zero, and Rubi's 4.7.5 is that. `e^(i (a + b ln(u)))` is `e^(i a)` times a real power of `u` when `b` is imaginary, so each such function is a sum or quotient of powers of `u`, and is written so now when `b` is an imaginary number; the zero is a power `1/x`, whose integral is a logarithm. A symbolic `b`, -`sqrt(-1/n^2)`, is left alone, since whether the zero is there turns on the sign of `n` -([#718](https://github.com/asc-community/AngouriMath/issues/718)). +`sqrt(-1/n^2)`, whose zero turns on the sign of `n`, is answered by the exponential's rule +([#1852](https://github.com/asc-community/AngouriMath/issues/1852), [#718](https://github.com/asc-community/AngouriMath/issues/718)). | Input | Was (2.5.0) | Now | |---|---|---| diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs index 39383a7c2..8c828130a 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -8493,8 +8493,7 @@ private static (Entity Elementary, Entity Si, Entity Ci) APowerTimesASineOrACosi // `P(x) e^(a x)` is a polynomial times one exponential -- one of them, with // `a = -i b` or `a = i b`, a polynomial alone -- which are closed on their own. // `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 unit = (Entity)MathS.i; 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 } @@ -8503,10 +8502,18 @@ static bool Vanishes(Entity exponent) => exponent.Evaled is Number.Complex { IsZ 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. + // and `a - i b` for a negative one. Neither seen to, Euler's identity is written in + // `j = -a/b` instead of `i`: its square is `-1` wherever the scale is zero, whichever + // sign holds, and `a + j b` is zero by construction. if (!plusVanishes && !minusVanishes) - return null; + { + if (frequency.Evaled is Number.Complex { IsZero: true }) + return null; + unit = -rate / frequency; + (towardsPlus, towardsMinus, plusVanishes) = (Number.Integer.Zero, (2 * rate).InnerSimplified, true); + } + var plus = ((onTheCosine - unit * onTheSine) / 2).InnerSimplified; + var minus = ((onTheCosine + unit * onTheSine) / 2).InnerSimplified; Entity resonant = Number.Integer.Zero; foreach (var (coefficient, exponent, vanishes) in new[] { (plus, towardsPlus, plusVanishes), (minus, towardsMinus, minusVanishes) }) { diff --git a/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs index 76f4a83ce..dbc218fbf 100644 --- a/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs +++ b/Sources/Tests/UnitTests/Calculus/AnOddPowerOfATrigonometricOfALogarithmIntegralTest.cs @@ -46,15 +46,40 @@ Entity Pinned(Entity e) => e.Substitute("a", "1/4".ToEntity()).Substitute("b", " } /// - /// 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. + /// a + i b or a - i b is zero, which one by the sign of n: an answer + /// dividing by either had no value anywhere, and one written in j = -a/b in place of + /// i holds on both sides. /// #1852 /// [Theory] [InlineData("exp(x/n)*sin(x*sqrt((-1)/n^2))")] [InlineData("exp(x/n)*sin(a + x*sqrt((-1)/n^2))")] + [InlineData("exp(x/n)*cos(a + x*sqrt((-1/9)/n^2))^3")] [InlineData("sin(a + ln(k*x^n)*sqrt((-1)/n^2))")] - public void AResonanceOnASignIsDeclined(string integrand) => - Assert.Contains("integral(", integrand.ToEntity().Integrate("x").Stringize()); + [InlineData("x*sin(a + ln(k*x^n)*sqrt((-4)/n^2))")] + [InlineData("x^m*sin(a + ln(k*x^n)*sqrt(-(1 + m)^2/n^2))")] + [InlineData("x^m*cos(a + ln(k*x^n)*sqrt(-1/4*(1 + m)^2/n^2))^2")] + [InlineData("x^2*sin(a + ln(k*x^n)*sqrt((-1)/n^2))^3")] + [InlineData("x^m*sin(a + ln(k*x^2)*sqrt(-1/36*(1 + m)^2))^3")] + public void AResonanceOnASignHoldsOnBothSides(string integrand) + { + var integral = integrand.ToEntity().Integrate("x"); + Assert.DoesNotContain("integral(", integral.Stringize()); + foreach (var n in new[] { 3, -3 }) + { + Entity Pinned(Entity e) => e.Substitute("a", "1/4".ToEntity()).Substitute("k", 2) + .Substitute("n", n).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) + Math.Abs((double)want.ImaginaryPart)), + $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, n = {n}, where the integrand is {want}"); + } + } + } } }