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: 22 additions & 6 deletions Sources/AngouriMath/Numerics/IntervalEvaluation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,16 @@ internal static class IntervalEvaluation

[AngouriMath.Core.ConstantField] private static readonly ComplexInterval Undefined = new(new(double.NaN, double.NaN), new(double.NaN, double.NaN));

/// <remarks>
/// The arithmetic is what nests deep -- a sum of a few hundred terms is a few hundred
/// frames -- so it is kept apart from the other arms, whose temporaries and closures would
/// otherwise widen every one of those frames: with them in one method, 228 nested sums
/// overflowed a 1 MB stack.
/// </remarks>
private static ComplexInterval Evaluate(Entity expr)
{
switch (expr)
{
case Number.Complex number:
return FromNumber(number);
case Variable variable when variable == MathS.pi:
return ComplexInterval.Real(Interval.Around(Math.PI));
case Variable variable when variable == MathS.e:
return ComplexInterval.Real(Interval.Around(Math.E));
case Sumf(var left, var right):
return Evaluate(left) + Evaluate(right);
case Minusf(var left, var right):
Expand All @@ -345,6 +345,22 @@ private static ComplexInterval Evaluate(Entity expr)
// In the range of an int, so that the reciprocal's negation cannot overflow.
case Powf(var @base, Number.Integer power) when power.EInteger.CanFitInInt32():
return Evaluate(@base).Pow(power.EInteger.ToInt32Checked());
default:
return EvaluateOtherThanArithmetic(expr);
}
}

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private static ComplexInterval EvaluateOtherThanArithmetic(Entity expr)
{
switch (expr)
{
case Number.Complex number:
return FromNumber(number);
case Variable variable when variable == MathS.pi:
return ComplexInterval.Real(Interval.Around(Math.PI));
case Variable variable when variable == MathS.e:
return ComplexInterval.Real(Interval.Around(Math.E));
case Powf(var @base, var exponent):
if (@base == MathS.e)
return Evaluate(exponent).Exp();
Expand Down
35 changes: 25 additions & 10 deletions Sources/AngouriMath/Numerics/PreciseEvaluation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,32 @@ private PreciseComplexInterval Evaluate(Entity expr)
return value;
}

/// <remarks>
/// The arithmetic is what nests deep, so it is kept apart from the other arms, whose
/// temporaries would otherwise widen every frame of the recursion, as in
/// <see cref="IntervalEvaluation"/>.
/// </remarks>
private PreciseComplexInterval EvaluateNode(Entity expr)
{
switch (expr)
{
case Sumf(var left, var right):
return Evaluate(left) is { IsFinite: true } lSumf ? Add(lSumf, Evaluate(right)) : undefined;
case Minusf(var left, var right):
return Evaluate(left) is { IsFinite: true } lMinusf ? Subtract(lMinusf, Evaluate(right)) : undefined;
case Mulf(var left, var right):
return Multiply(Evaluate(left), Evaluate(right));
case Divf(var left, var right):
return Evaluate(left) is { IsFinite: true } lDivf ? Divide(lDivf, Evaluate(right)) : undefined;
case Powf(var @base, Number.Integer power) when power.EInteger.CanFitInInt32():
return Pow(Evaluate(@base), power.EInteger.ToInt32Checked());
default:
return EvaluateOtherThanArithmetic(expr);
}
}

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private PreciseComplexInterval EvaluateOtherThanArithmetic(Entity expr)
{
switch (expr)
{
Expand All @@ -430,16 +455,6 @@ private PreciseComplexInterval EvaluateNode(Entity expr)
return Real(Pi());
case Variable variable when variable == MathS.e:
return Real(E());
case Sumf(var left, var right):
return Evaluate(left) is { IsFinite: true } lSumf ? Add(lSumf, Evaluate(right)) : undefined;
case Minusf(var left, var right):
return Evaluate(left) is { IsFinite: true } lMinusf ? Subtract(lMinusf, Evaluate(right)) : undefined;
case Mulf(var left, var right):
return Multiply(Evaluate(left), Evaluate(right));
case Divf(var left, var right):
return Evaluate(left) is { IsFinite: true } lDivf ? Divide(lDivf, Evaluate(right)) : undefined;
case Powf(var @base, Number.Integer power) when power.EInteger.CanFitInInt32():
return Pow(Evaluate(@base), power.EInteger.ToInt32Checked());
case Powf(var @base, var exponent):
return @base == MathS.e ? Exp(Evaluate(exponent)) : Pow(Evaluate(@base), Evaluate(exponent));
case Sinf(var argument):
Expand Down
Loading