diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 90c8c587b..bc6dc1b29 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -2353,6 +2353,19 @@ a sample of its families 1 to 7 are answered alone as they were. | `"x^2*Ei(a+b*x)^2".Integrate("x")` | `a ^ 2 * Ei * x ^ 3 / 3 + a * b * 2 * Ei * x ^ 4 / 4 + b ^ 2 * Ei * x ^ 5 / 5 + C`, with `Ei` a variable | an antiderivative in `Ei(a + b x)` and `Ei(2 (a + b x))` | | `"erf(a+b*x)^2".Integrate("x")` | `UnrecognizedFunctionParseException`: there is no function `erf` | an antiderivative in `erf` | +### A logarithm of `x` is matched to a logarithm of a multiple of `x` below the bar + +By parts on `li(b x)/x` takes the antiderivative of `1/x`, and with `ln(x)` the remainder was +`b ln(x)/ln(b x)`, which nothing read. `ln(b x)` is as much an antiderivative of `1/x`, and taken so, +the logarithm the derivative of `li(b x)` divides by cancels: `li(b x)/x` is `li(b x) ln(b x) - b x` +([#1501](https://github.com/asc-community/AngouriMath/issues/1501)). `li` had no reading in 2.5.0, +which its own entry records, and no integrand without it changes: Rubi's independent suites, its +family 3 at twenty a file and a sample of the others are answered alone as they were. + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"li(b*x)/x".Integrate("x")` | `li * b * x + C`, with `li` a variable | `li(b * x) * ln(b * x) - b * x + C` | + ### An exponential or a hyperbolic function over several linears is split into partial fractions over them `e^x/(x (x + 1))` was left unevaluated, where `e^x/x` and `e^x/(x + 1)` were each answered with diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs index c4354b9a5..0a8479415 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -1679,6 +1679,18 @@ private static bool IsASpecialFunctionOfALinear(Entity factor, Variable x) // divisor, where the division leaves a constant. static Entity WithTheConstantMatchedTo(Entity antiderivative, Entity derivativeOfV, Variable x) { + // A logarithm of x, against a logarithm of a multiple of x below the bar: ln(c x) is + // as much an antiderivative of 1/x as ln(x) is, and taken so, the logarithm the + // derivative divides by cancels. li(b x)/x is li(b x) ln(b x) - b x, where with ln(x) + // the remainder was ln(x)/ln(b x), which nothing read. + // https://github.com/asc-community/AngouriMath/issues/1501 + if (TheLogarithmOfTheVariable(antiderivative, x) is (var logarithmCoefficient, true) + && Sumf.LinearChildren(Functions.PartialFractions.Bare(derivativeOfV)) + .SelectMany(term => Mulf.LinearChildren(Functions.SingleQuotient.Of(term).Denominator)) + .FirstOrDefault(factor => factor is Logf(var logBase, var argument) && logBase == MathS.e + && TreeAnalyzer.TryGetPolyLinear(argument, x, out var multiple, out var offset) + && TreeAnalyzer.IsZero(offset) && !TreeAnalyzer.IsZero(multiple)) is { } logarithmBelow) + return logarithmCoefficient * logarithmBelow; if (!TreeAnalyzer.TryGetPolynomial(antiderivative, x, out _)) return antiderivative; var divisors = Sumf.LinearChildren(Functions.PartialFractions.Bare(derivativeOfV)) @@ -20367,6 +20379,25 @@ private static bool TheRemainderIsAskedTermByTerm(Entity v, Entity u, Variable x || u == special; } + /// + /// as a constant times ln(x), the coefficient and + /// , or where it is not one. + /// + private static (Entity Coefficient, bool IsOne) TheLogarithmOfTheVariable(Entity expr, Variable x) + { + static bool IsTheLogarithm(Entity factor, Variable x) => factor is Logf(var logBase, var argument) && logBase == MathS.e && argument == x; + if (IsTheLogarithm(expr, x)) + return (Number.Integer.One, true); + if (expr is Mulf(var left, var right)) + { + if (IsTheLogarithm(right, x) && !left.ContainsNode(x)) + return (left, true); + if (IsTheLogarithm(left, x) && !right.ContainsNode(x)) + return (right, true); + } + return (Number.Integer.Zero, false); + } + /// /// The factors of that are polynomials in of /// positive degree, against the rest: x sin(b x) is x and sin(b x). diff --git a/Sources/Tests/UnitTests/Calculus/SpecialFunctionsByPartsTest.cs b/Sources/Tests/UnitTests/Calculus/SpecialFunctionsByPartsTest.cs index c83e8806d..4139e5635 100644 --- a/Sources/Tests/UnitTests/Calculus/SpecialFunctionsByPartsTest.cs +++ b/Sources/Tests/UnitTests/Calculus/SpecialFunctionsByPartsTest.cs @@ -30,13 +30,17 @@ public sealed class SpecialFunctionsByPartsTest /// rule is asked the symbolic question. /// private static void DifferentiatesBack(string integrand, params (string Name, string Value)[] pins) + => DifferentiatesBackAt(Points, integrand, pins); + + /// at . + private static void DifferentiatesBackAt(double[] points, string integrand, params (string Name, string Value)[] pins) { var integral = integrand.ToEntity().Integrate("x"); Assert.DoesNotContain("integral(", integral.Stringize()); Entity Pinned(Entity e) => pins.Aggregate(e, (current, pin) => current.Substitute(pin.Name, pin.Value.ToEntity())); var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x"); var original = Pinned(integrand.ToEntity()); - foreach (var at in Points) + foreach (var at in points) { var got = derivative.Substitute("x", at).EvalNumerical(); var want = original.Substitute("x", at).EvalNumerical(); @@ -73,6 +77,16 @@ public void ASpecialFunctionAloneIsByPartsAgainstOne(string integrand) public void TheLogarithmicIntegralIsByParts(string integrand) => DifferentiatesBack(integrand, ("a", "3"), ("b", "13/10")); + /// + /// Over x, the antiderivative of 1/x is taken as ln(b x), the logarithm the + /// derivative of li(b x) divides by, and the remainder is b: + /// li(b x) ln(b x) - b x. At positive x, where li(b x) is real, and off + /// x = 1/b, where ln(b x) is 0. + /// + [Fact] + public void TheLogarithmicIntegralOverXIsOneRoundOfParts() + => DifferentiatesBackAt(new[] { 0.35, 1.45, 2.3 }, "li(b*x)/x", ("b", "13/10")); + /// /// Against a power of x, the special function is the factor differentiated: what is /// left is the power times e^(-u^2), e^u/u, sin(u)/u and the like.