This commit is contained in:
@@ -6,6 +6,60 @@ namespace Just.PreciseMath.Tests;
|
||||
|
||||
public class DoubleDoubleBoundaryTests
|
||||
{
|
||||
[Fact]
|
||||
public void BoundarySubtractionPreservesComponentsOfTheOriginalExpression()
|
||||
{
|
||||
DoubleDouble[] magnitudes =
|
||||
[
|
||||
new(0.0), new(double.Epsilon), new(1.0),
|
||||
new(Math.BitDecrement(Math.ScaleB(1.0, 1021))),
|
||||
new(Math.ScaleB(1.0, 1021)),
|
||||
DoubleDouble.FromComponents(Math.ScaleB(1.0, 1021), double.Epsilon),
|
||||
DoubleDouble.FromComponents(Math.ScaleB(1.0, 1021), Math.ScaleB(1.0, 967)),
|
||||
new(double.MaxValue),
|
||||
DoubleDouble.FromComponents(double.MaxValue, Math.ScaleB(1.0, 969)),
|
||||
DoubleDouble.FromComponents(double.MaxValue, -Math.ScaleB(1.0, 969))
|
||||
];
|
||||
foreach (DoubleDouble leftMagnitude in magnitudes)
|
||||
{
|
||||
foreach (DoubleDouble rightMagnitude in magnitudes)
|
||||
{
|
||||
// Use the original exponent-domain rule, not the production predicate.
|
||||
if (Math.ILogB(leftMagnitude.High) <= 1020 && Math.ILogB(rightMagnitude.High) <= 1020)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (double leftSign in new[] { -1.0, 1.0 })
|
||||
{
|
||||
foreach (double rightSign in new[] { -1.0, 1.0 })
|
||||
{
|
||||
DoubleDouble left = leftSign < 0.0 ? -leftMagnitude : leftMagnitude;
|
||||
DoubleDouble right = rightSign < 0.0 ? -rightMagnitude : rightMagnitude;
|
||||
DoubleDouble actual = left - right;
|
||||
// Bitwise characterization of the expression being extracted,
|
||||
// supplemented below by the independent exact-rational oracle.
|
||||
DoubleDouble original = PreciseMathHelper.AddBoundary(left, -right);
|
||||
string context = Describe(left, right, "-");
|
||||
BitConverter.DoubleToInt64Bits(actual.High).ShouldBe(BitConverter.DoubleToInt64Bits(original.High), context);
|
||||
BitConverter.DoubleToInt64Bits(actual.Low).ShouldBe(BitConverter.DoubleToInt64Bits(original.Low), context);
|
||||
Rational expected = Exact(left) - Exact(right);
|
||||
if (BelowOverflowMidpoint(expected))
|
||||
{
|
||||
AssertAccurate(actual, expected, context);
|
||||
AssertNormalized(actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
actual.High.ShouldBe(expected.CompareTo(Exact(0.0)) < 0
|
||||
? double.NegativeInfinity : double.PositiveInfinity, context);
|
||||
BitConverter.DoubleToInt64Bits(actual.Low).ShouldBe(0L, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1.0, "+")]
|
||||
[InlineData(-1.0, "+")]
|
||||
|
||||
Reference in New Issue
Block a user