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
28 changes: 28 additions & 0 deletions Sources/AngouriMath/Numerics/PreciseEvaluation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,34 @@ private PreciseComplexInterval EvaluateOtherThanArithmetic(Entity expr)
return BySlope(Evaluate(argument), Number.Shi, z => Divide(Half(Subtract(Exp(z), Exp(Negate(z)))), z), cutEnd: null);
case Chif(var argument):
return BySlope(Evaluate(argument), Number.Chi, z => Divide(Half(Add(Exp(z), Exp(Negate(z)))), z), cutEnd: EDecimal.Zero);
// The upper incomplete gamma function of a constant order, through its derivative in z,
// -z^(a - 1) e^(-z), jumping across the negative real axis but at a whole order a >= 1. The
// power is the principal one, as this evaluation's powers are. An order known only to its
// last place, as 1/3 is, is taken at both ends, and the value is the hull of the two: across
// an interval that narrow the function is linear in its order.
// https://github.com/asc-community/AngouriMath/issues/2075
case IncompleteGammaf(var parameter, var lowerLimit):
{
var order = Evaluate(parameter);
if (!order.IsFinite)
return undefined;
var z = Evaluate(lowerLimit);
var entire = order.IsReal && order.Re.Low.CompareTo(order.Re.High) == 0 && order.Re.Low.IsInteger() && order.Re.Low.Sign > 0;
PreciseComplexInterval AtTheOrder(EDecimal re, EDecimal im)
{
var a = Number.Complex.Create(re, im);
var aLessOne = new PreciseComplexInterval(PreciseInterval.Exactly(re.Subtract(EDecimal.One)), PreciseInterval.Exactly(im));
return BySlope(z, w => Number.IncompleteGamma(a, w), w => Negate(Multiply(Pow(w, aLessOne), Exp(Negate(w)))), cutEnd: entire ? null : EDecimal.Zero);
}
var low = AtTheOrder(order.Re.Low, order.Im.Low);
if (order.Re.Low.CompareTo(order.Re.High) == 0 && order.Im.Low.CompareTo(order.Im.High) == 0 || !low.IsFinite)
return low;
var high = AtTheOrder(order.Re.High, order.Im.High);
if (!high.IsFinite)
return undefined;
return new(new(EDecimal.Min(low.Re.Low, high.Re.Low), EDecimal.Max(low.Re.High, high.Re.High)),
new(EDecimal.Min(low.Im.Low, high.Im.Low), EDecimal.Max(low.Im.High, high.Im.High)));
}
// A sum over the roots of a polynomial, the form Rothstein鈥揟rager answers in: each
// root enclosed, the summand worked out on its rectangle, and the terms added.
// https://github.com/asc-community/AngouriMath/issues/1285
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ public void APositiveRateIsTakenOutOfThePower()
[InlineData("(a + b*x)^2*e^(-c*(d + f*x)^3)")]
public void APolynomialBesideAFunctionOfAShiftedLinear(string integrand) => DifferentiatesBack(integrand);

/// <summary>
/// A symbolic power of an inverse hyperbolic function, which its substitution writes as powers of <c>u</c> beside
/// exponentials of it, each a gamma function. The route had these answers and turned them away: its check at
/// sampled points could not evaluate a gamma function, and so had no point to compare at. Rubi's 7.1.4 and 7.2.4.
/// </summary>
[Theory]
[InlineData("x*asinh(c*x)^n/sqrt(1 + c^2*x^2)")]
[InlineData("(d + f*asinh(c*x))^n*sqrt(1 + c^2*x^2)")]
[InlineData("x*(d + f*acosh(f*x))^n/(sqrt(f*x - 1)*sqrt(f*x + 1))")]
public void ASymbolicPowerOfAnInverseHyperbolicFunction(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
10 changes: 9 additions & 1 deletion Sources/Tests/UnitTests/Core/IntervalEvaluationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ public void TheSizeOfALargeComplexValueIsFinite()
[InlineData("Shi(3/2) + Chi(-1) + Chi(1 + 2i)")]
[InlineData("e^(-2) * Ei(sqrt(3)) + Si(pi/4)^2")]
[InlineData("iverson(pi > 3) * sqrt(2) + iverson(e < 2)")]
[InlineData("gamma(5/2, 3/2) + gamma(-3, 7/10)")]
[InlineData("gamma(1/2 + i, 2 - i)")]
[InlineData("gamma(3/2, -2) + gamma(4, -1)")]
[InlineData("gamma(1/3, 2) + gamma(2/7 + i/3, 1/2 + i)")]
public void ThePreciseIntervalHoldsTheValue(string expression)
{
var expr = expression.ToEntity();
Expand Down Expand Up @@ -247,7 +251,9 @@ public void AnExactZeroFactorIsZero(string expression)
/// <c>x erf(x)</c> differentiates to <c>erf(x)</c> and more -- is checked, where reading
/// none of them left no point to compare at and the answer was turned away. On the real
/// line left of 0 the values are the ones on the cut: <c>Chi(-0.61)</c> is
/// <c>Chi(0.61) + i pi</c>, and <c>li(-0.61)</c> is complex.
/// <c>Chi(0.61) + i pi</c>, and <c>li(-0.61)</c> is complex. The incomplete gamma function was
/// not read, and every answer holding one was turned away by the routes that check theirs:
/// Rubi's <c>x arsinh(a x)^n/sqrt(1 + a^2 x^2)</c> among them.
/// </summary>
[Theory]
[InlineData("x * erf(x) + e^(-x^2)/sqrt(pi)", "erf(x)")]
Expand All @@ -257,6 +263,8 @@ public void AnExactZeroFactorIsZero(string expression)
[InlineData("x * Ei(x) - e^x", "Ei(x)")]
[InlineData("x * Chi(x) - sinh(x)", "Chi(x)")]
[InlineData("x * li(x) - Ei(2 * ln(x))", "li(x)")]
[InlineData("x * gamma(5/2, x) - gamma(7/2, x)", "gamma(5/2, x)")]
[InlineData("x * gamma(n, x) - gamma(n + 1, x)", "gamma(n, x)")]
public void ADerivativeKeepingASpecialFunctionIsChecked(string antiderivative, string integrand)
{
var x = MathS.Var("x");
Expand Down
Loading