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
Original file line number Diff line number Diff line change
Expand Up @@ -18314,6 +18314,75 @@ private static (Entity Binomial, Entity Offset, Entity Scale, Entity Exponent)?
return exponent is null ? null : (sum, offset, scale, exponent.InnerSimplified);
}

/// <summary>
/// A power that is not whole of a linear in one logarithm <c>L = ln(c x^n)</c>, beside a linear in it or in another
/// logarithm of a power of x, <c>(a + b L)^p (d + e M)</c> with <c>M = ln(f x^r)</c>. M is <c>(r/n) L + delta</c>,
/// where <c>delta = M - (r/n) L</c> is constant between the cuts, its derivative being <c>r/x - (r/n)(n/x) = 0</c>.
/// So <c>d + e M</c> is <c>alpha (a + b L) + beta</c>, with <c>alpha = e r/(n b)</c> and
/// <c>beta = d + e delta - alpha a</c>, and the integrand is <c>alpha (a + b L)^(p + 1) + beta (a + b L)^p</c> beside
/// what else is there: powers of the one logarithm, which the rules for those answer. delta is written back in the
/// answer. Rubi's 3.1.5. https://github.com/asc-community/AngouriMath/issues/2075
/// </summary>
internal static Entity? SolveAPowerOfALogarithmBesideALinearInALogarithm(Entity expr, Entity.Variable x, bool integrateByParts)
{
if (!Integration.AnsweringTheQuestionAskedOrOneBelow || expr is not (Mulf or Divf))
return null;
var (numerator, denominator) = expr is Divf(var above, var below) ? (above, below) : (expr, (Entity)Number.Integer.One);
Powf? power = null;
Entity? linear = null;
Entity beside = Number.Integer.One;
foreach (var factor in Mulf.LinearChildren(numerator))
{
if (power is null && factor is Powf(var @base, var exponent) candidate && exponent is not Number.Integer
&& !exponent.ContainsNode(x) && TheLinearInOneLogarithm(@base, x) is not null)
power = candidate;
else if (linear is null && factor.ContainsNode(x) && factor is Logf or Sumf or Minusf && TheLinearInOneLogarithm(factor, x) is not null)
linear = factor;
else
beside *= factor;
}
if (power is null || linear is null
|| TheLinearInOneLogarithm(power.Base, x) is not var (logarithm, degree, a, b)
|| TheLinearInOneLogarithm(linear, x) is not var (other, otherDegree, d, e))
return null;
var ratio = (otherDegree / degree).InnerSimplified;
Entity delta = other == logarithm ? Number.Integer.Zero : Variable.CreateUnique(expr, "delta_log");
var alpha = e * ratio / b;
var beta = d + e * delta - alpha * a;
beside /= denominator;
if (Integration.ComputeAsAQuestionOfItsOwn((beside * MathS.Pow(power.Base, power.Exponent + 1)).InnerSimplified, x, integrateByParts) is not { } raised
|| Integration.ComputeAsAQuestionOfItsOwn((beside * power).InnerSimplified, x, integrateByParts) is not { } asWritten)
return null;
var answer = alpha * raised + beta * asWritten;
if (delta is Variable constant)
answer = answer.Substitute(constant, other - ratio * logarithm);
return answer.Nodes.Any(node => node == MathS.NaN) ? null : answer;
}

/// <summary>
/// <paramref name="expr"/> as <c>a + b L</c>, linear in one logarithm <c>L = ln(c x^n)</c> and free of x otherwise,
/// with the logarithm, <c>n</c>, <c>a</c> and <c>b</c>; or <see langword="null"/>.
/// </summary>
private static (Entity Logarithm, Entity Degree, Entity Offset, Entity Slope)? TheLinearInOneLogarithm(Entity expr, Entity.Variable x)
{
Entity? logarithm = null;
foreach (var node in expr.Nodes)
if (node is Logf(var @base, var antilogarithm) && @base == MathS.e && antilogarithm.ContainsNode(x))
{
if (logarithm is not null && node != logarithm)
return null;
logarithm = node;
}
if (logarithm is not Logf(_, var argument) || TheMonomial(argument, x) is not var (_, degree) || TreeAnalyzer.IsZero(degree))
return null;
var l = Variable.CreateUnique(expr, "l_log");
var inL = expr.Replace(node => node == logarithm ? l : node);
if (inL.ContainsNode(x) || !TreeAnalyzer.TryGetPolyLinear(inL, l, out var slope, out var offset)
|| slope.ContainsNode(l) || offset.ContainsNode(l) || TreeAnalyzer.IsZero(slope))
return null;
return (logarithm, degree, offset, slope);
}

/// <summary>
/// Whether <paramref name="factor"/> is a power that is not whole of something holding a logarithm of something in
/// <paramref name="x"/>, or an exponential of something in <paramref name="x"/> that is not linear in it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,10 @@ internal static bool ASumOverRootsWouldAnswer
// And a product of powers that is the derivative of one with symbolic exponents, its
// constant read at a point where the quotient of the brackets does not simplify free of x.
if ((answer = IndefiniteIntegralSolver.SolveAsTheDerivativeOfAProductOfPowersReadAtAPoint(expr, x, integrateByParts)) is { }) return answer;
// A power of a logarithm beside a linear in another as two powers of the first, after the product of powers read
// as a derivative: p x^m ln(x)^n ((m + 1) ln(x) + n + 1) is p x^(m + 1) ln(x)^(n + 1) there, and a sum of gamma
// functions here. https://github.com/asc-community/AngouriMath/issues/2075
if ((answer = IndefiniteIntegralSolver.SolveAPowerOfALogarithmBesideALinearInALogarithm(expr, x, integrateByParts)) is { }) return answer;
// An arcoth of a linear as its artanh plus a constant, last of all, so that every arcoth
// answered as written keeps that answer: `acoth(x)^2/(1 - x^2)^2` is
// `(atanh(x) + K)^2/(1 - x^2)^2` with `K = acoth(x) - atanh(x)`, constant where it is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ public void APositiveRateIsTakenOutOfThePower()
[InlineData("(a - b*ln(c*(d + f/x^(1/3))^2))^n/x^2")]
public void APowerOfXBesideAFunctionOfABinomial(string integrand) => DifferentiatesBack(integrand);

/// <summary>
/// A power of a linear in one logarithm of a power of x beside a linear in it or in another, which is the first
/// times a ratio of degrees plus a constant between the cuts: two powers of the one logarithm. Rubi's 3.1.5.
/// </summary>
[Theory]
[InlineData("(f - b*ln(c*x^2))^n*(d + a*ln(f*x^3))")]
[InlineData("x^2*(f - b*ln(c*x))^n*(d + a*ln(f*x^3))")]
[InlineData("(f - b*ln(c*x))^n*(d + a*ln(c*x))/x^2")]
[InlineData("(d*x)^m*(f - b*ln(c*x^2))^n*ln(a*x)")]
public void APowerOfALogarithmBesideALinearInALogarithm(string integrand) => DifferentiatesBack(integrand);

/// <summary>
/// Not where the integral is elementary, an exponential integral or an error function: those keep the form
/// they had.
Expand Down
Loading