added root functions
.NET Test / .NET tests (push) Successful in 1m31s

This commit is contained in:
2026-09-16 20:24:08 +04:00
parent 24d2aef892
commit 7084fae174
11 changed files with 1912 additions and 94 deletions
@@ -0,0 +1,120 @@
using System.Numerics;
using Shouldly;
using Xunit;
namespace Just.PreciseMath.Tests;
public class DoubleDoubleCbrtTests
{
[Fact]
public void ExactCubesAndSpecialValues()
{
foreach (double value in new[] { 0.0, -0.0, double.NaN, double.PositiveInfinity, double.NegativeInfinity })
{
DoubleDouble result = DoubleDouble.Cbrt(new DoubleDouble(value));
AssertBits(new DoubleDouble(Math.Cbrt(value)), result);
}
foreach (double root in new[] { -3.0, -2.0, -1.0, 0.5, 1.0, 2.0, 3.0 })
{
AssertBits(new DoubleDouble(root), DoubleDouble.Cbrt(new DoubleDouble(root * root * root)));
}
for (int exponent = -1074; exponent <= 1023; exponent += 3)
{
DoubleDouble input = new(Math.ScaleB(1.0, exponent));
AssertBits(new DoubleDouble(Math.ScaleB(1.0, exponent / 3)), DoubleDouble.Cbrt(input));
}
}
[Fact]
public void CubesMeetExactBoundAcrossEveryInputExponent()
{
Random random = new(271828);
for (int exponent = -1074; exponent <= 1023; ++exponent)
{
double high = Math.ScaleB(1.0 + random.NextDouble(), exponent);
double dense = Math.ScaleB(random.NextDouble(), exponent - 53);
foreach (double low in new[] { 0.0, dense, -dense, double.Epsilon, -double.Epsilon })
{
DoubleDouble input = DoubleDouble.FromComponents(high, low);
if (input.High > 0.0 && DoubleDouble.IsFinite(input))
{
AssertBound(input, DoubleDouble.Cbrt(input));
AssertBound(-input, DoubleDouble.Cbrt(-input));
AssertBits(DoubleDouble.Cbrt(input), DDMath.Cbrt(input));
}
}
}
foreach (double low in new[] { 0.0, Math.BitDecrement(Math.ScaleB(1.0, 970)), -Math.ScaleB(1.0, 970) })
{
DoubleDouble input = DoubleDouble.FromComponents(double.MaxValue, low);
AssertBound(input, DoubleDouble.Cbrt(input));
}
}
[Fact]
public void SparseNearOneCorrectionsSurvive()
{
// cbrt(1+d) = 1+d/3+O(d^2); for these d, the quadratic is
// below half an ulp of the rounded binary64 correction d/3.
foreach (int exponent in new[] { -100, -500, -1000, -1072 })
{
foreach (double sign in new[] { -1.0, 1.0 })
{
double low = Math.ScaleB(sign, exponent);
DoubleDouble result = DoubleDouble.Cbrt(DoubleDouble.FromComponents(1.0, low));
result.High.ShouldBe(1.0);
result.Low.ShouldBe(low / 3.0);
}
}
}
[Fact]
public void ScalingDoesNotEraseARepresentableSparseCorrection()
{
// cbrt(2^900 + d) = 2^300 + d/(3*2^600) + O(d²/2^1500).
// Scaling d=2^-174 by 2^-900 leaves epsilon, whose division by 3
// underflows, although the final correction 2^-774/3 is representable.
foreach (double sign in new[] { -1.0, 1.0 })
{
DoubleDouble input = DoubleDouble.FromComponents(Math.ScaleB(1.0, 900), Math.ScaleB(sign, -174));
DoubleDouble result = DoubleDouble.Cbrt(input);
AssertBits(DoubleDouble.FromComponents(Math.ScaleB(1.0, 300), Math.ScaleB(sign / 3.0, -774)), result);
AssertBits(-result, DoubleDouble.Cbrt(-input));
}
}
private static void AssertBound(DoubleDouble input, DoubleDouble actual)
{
DoubleDouble.IsFinite(actual).ShouldBeTrue();
DoubleDouble.IsCanonical(actual).ShouldBeTrue();
Math.Sign(actual.High).ShouldBe(Math.Sign(input.High));
// Exact dyadic oracle, independent of the implementation's arithmetic:
// x*(1-t)^3 <= |y|^3 <= x*(1+t)^3, t=2^-100, x=|input|.
BigInteger x = BigInteger.Abs(Units(input.High) + Units(input.Low)) << 2148;
BigInteger y = BigInteger.Abs(Units(actual.High) + Units(actual.Low));
BigInteger scale = BigInteger.One << 100;
BigInteger cube = BigInteger.Pow(y, 3) << 300;
(cube >= x * BigInteger.Pow(scale - 1, 3)
&& cube <= x * BigInteger.Pow(scale + 1, 3)).ShouldBeTrue(
$"Cbrt bound failed for ({input.High:R}, {input.Low:R}): ({actual.High:R}, {actual.Low:R})");
}
private static BigInteger Units(double value)
{
long bits = BitConverter.DoubleToInt64Bits(value);
int exponent = (int)((bits >> 52) & 0x7ff);
BigInteger significand = bits & 0xfffffffffffffL;
if (exponent != 0)
{
significand += BigInteger.One << 52;
significand <<= exponent - 1;
}
return bits < 0 ? -significand : significand;
}
private static void AssertBits(DoubleDouble expected, DoubleDouble actual)
{
BitConverter.DoubleToInt64Bits(actual.High).ShouldBe(BitConverter.DoubleToInt64Bits(expected.High));
BitConverter.DoubleToInt64Bits(actual.Low).ShouldBe(BitConverter.DoubleToInt64Bits(expected.Low));
}
}
@@ -0,0 +1,349 @@
using System.Numerics;
using Shouldly;
using Xunit;
namespace Just.PreciseMath.Tests;
public class DoubleDoubleHypotTests
{
[Fact]
public void SpecialValuesAndZeroOperandsFollowTheContract()
{
double[] values = [0.0, -0.0, 1.0, -1.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN];
foreach (double x in values)
{
foreach (double y in values)
{
if (!double.IsFinite(x) || !double.IsFinite(y) || x == 0.0 || y == 0.0)
{
AssertBits(new DoubleDouble(double.Hypot(x, y)), DoubleDouble.Hypot(new DoubleDouble(x), new DoubleDouble(y)));
}
}
}
DoubleDouble sparse = DoubleDouble.FromComponents(double.MaxValue, double.Epsilon);
AssertBits(sparse, DoubleDouble.Hypot(-sparse, DoubleDouble.NegativeZero));
AssertBits(sparse, DoubleDouble.Hypot(DoubleDouble.Zero, -sparse));
AssertBits(DoubleDouble.PositiveInfinity, DoubleDouble.Hypot(new DoubleDouble(double.MaxValue), new DoubleDouble(double.MaxValue)));
}
[Fact]
public void ScaledPythagoreanTriplesAreExact()
{
for (int exponent = -1074; exponent <= 1021; ++exponent)
{
DoubleDouble x = new(Math.ScaleB(3.0, exponent));
DoubleDouble y = new(Math.ScaleB(4.0, exponent));
DoubleDouble expected = new(Math.ScaleB(5.0, exponent));
AssertBits(expected, DoubleDouble.Hypot(x, y));
AssertBits(expected, DoubleDouble.Hypot(-y, -x));
}
}
[Fact]
public void FiniteResultsMeetExactSquaredBoundAcrossTheRange()
{
Random random = new(123456);
for (int exponent = -1074; exponent <= 1023; ++exponent)
{
double high = Math.ScaleB(1.0 + (random.NextDouble() * 0.1), exponent);
foreach (int gap in new[] { 0, 1, 26, 54, 55, 500, 1100 })
{
double second = Math.ScaleB(1.0, exponent - gap);
foreach (double sign in new[] { -1.0, 1.0 })
{
DoubleDouble x = DoubleDouble.FromComponents(high, Math.ScaleB(sign, exponent - 54));
DoubleDouble y = DoubleDouble.FromComponents(second, Math.ScaleB(-sign, exponent - gap - 54));
DoubleDouble result = DoubleDouble.Hypot(x, y);
AssertBound(x, y, result);
AssertBits(result, DoubleDouble.Hypot(-y, x));
AssertBits(result, DDMath.Hypot(x, y));
}
}
}
DoubleDouble maximum = new(double.MaxValue);
AssertBound(maximum, new DoubleDouble(Math.ScaleB(1.0, 995)), DoubleDouble.Hypot(maximum, new DoubleDouble(Math.ScaleB(1.0, 995))));
}
[Fact]
public void WidelySeparatedOperandsRetainRepresentableCorrections()
{
// sqrt(a^2+b^2) = a+b^2/(2a)+O(b^4/a^3). These exact dyadics
// put the omitted term below half an ulp of the expected low.
foreach ((int large, int small) in new[] { (0, -100), (1000, 450), (-500, -600) })
{
DoubleDouble result = DoubleDouble.Hypot(new DoubleDouble(Math.ScaleB(1.0, large)), new DoubleDouble(Math.ScaleB(1.0, small)));
AssertBits(DoubleDouble.FromComponents(Math.ScaleB(1.0, large), Math.ScaleB(1.0, (2 * small) - large - 1)), result);
}
}
[Fact]
public void OverflowClassificationUsesTheExactInputSquares()
{
DoubleDouble x = DoubleDouble.FromComponents(double.MaxValue, Math.BitDecrement(Math.ScaleB(1.0, 970)));
double boundaryY = Math.ScaleB(1.0, 971);
// T=2^1024-2^970 is the binary64 overflow midpoint. For the lower y,
// T²-x²-y² = 3*2^1888-5*2^1834 > 0, though the scaled root can round
// up to T before rescaling. The adjacent boundaryY is above the threshold.
foreach (double y in new[] { Math.BitDecrement(boundaryY), boundaryY, Math.BitIncrement(boundaryY) })
{
AssertOverflowBoundary(x, new DoubleDouble(y));
}
}
[Fact]
public void ExactOverflowMidpointAndAdjacentLowsAreClassified()
{
// 55²+48²=73² and 73 divides 2^54-1, so these scaled integer legs
// have hypotenuse exactly T=(2^54-1)*2^970. Split integer components
// before scaling; no DD arithmetic supplies the expected threshold.
const long factor = ((1L << 54) - 1) / 73;
const long first = 55 * factor;
const long second = 48 * factor;
DoubleDouble x = DoubleDouble.FromComponents(Math.ScaleB((double)first, 970), Math.ScaleB(first - (long)(double)first, 970));
DoubleDouble y = DoubleDouble.FromComponents(Math.ScaleB((double)second, 970), Math.ScaleB(second - (long)(double)second, 970));
BigInteger threshold = Units(double.MaxValue) + Units(Math.ScaleB(1.0, 970));
BigInteger a = Units(x.High) + Units(x.Low);
BigInteger b = Units(y.High) + Units(y.Low);
((a * a) + (b * b)).ShouldBe(threshold * threshold);
foreach (double low in new[] { Math.BitDecrement(x.Low), x.Low, Math.BitIncrement(x.Low) })
{
AssertOverflowBoundary(DoubleDouble.FromComponents(x.High, low), y);
}
}
[Fact]
public void ThreeDimensionalSpecialValuesAndZeroReductionFollowTheContract()
{
double[] values = [0.0, -0.0, 1.0, -1.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN];
foreach (double x in values)
{
foreach (double y in values)
{
foreach (double z in values)
{
DoubleDouble result = DoubleDouble.Hypot(new DoubleDouble(x), new DoubleDouble(y), new DoubleDouble(z));
if (double.IsInfinity(x) || double.IsInfinity(y) || double.IsInfinity(z))
{
AssertBits(DoubleDouble.PositiveInfinity, result);
}
else if (double.IsNaN(x) || double.IsNaN(y) || double.IsNaN(z))
{
AssertBits(DoubleDouble.NaN, result);
}
else if (x == 0.0 && y == 0.0 && z == 0.0)
{
AssertBits(DoubleDouble.Zero, result);
}
else
{
AssertBound(new DoubleDouble(x), new DoubleDouble(y), new DoubleDouble(z), result);
}
AssertBits(result, DDMath.Hypot(new DoubleDouble(x), new DoubleDouble(y), new DoubleDouble(z)));
}
}
}
DoubleDouble[] finite = [new(double.Epsilon), new(double.MaxValue), new(2.0),
DoubleDouble.FromComponents(1.0, double.Epsilon)];
foreach (DoubleDouble x in finite)
{
foreach (DoubleDouble y in finite)
{
DoubleDouble expected = DoubleDouble.Hypot(x, y);
AssertBits(expected, DoubleDouble.Hypot(x, y, DoubleDouble.NegativeZero));
AssertBits(expected, DoubleDouble.Hypot(x, DoubleDouble.Zero, y));
AssertBits(expected, DoubleDouble.Hypot(DoubleDouble.NegativeZero, x, y));
}
}
}
[Fact]
public void ThreeDimensionalExactBinaryNormsCoverTheExponentRange()
{
// 1²+2²+2²=3²; all scaled inputs and outputs here are exact dyadics.
for (int exponent = -1074; exponent <= 1021; ++exponent)
{
DoubleDouble x = new(Math.ScaleB(1.0, exponent));
DoubleDouble y = new(Math.ScaleB(2.0, exponent));
DoubleDouble expected = new(Math.ScaleB(3.0, exponent));
AssertBits(expected, DoubleDouble.Hypot(x, y, y));
AssertBits(expected, DoubleDouble.Hypot(-y, x, -y));
}
AssertBits(new DoubleDouble(7.0), DoubleDouble.Hypot(new DoubleDouble(2.0), new DoubleDouble(3.0), new DoubleDouble(6.0)));
AssertBits(new DoubleDouble(13.0), DoubleDouble.Hypot(new DoubleDouble(3.0), new DoubleDouble(4.0), new DoubleDouble(12.0)));
}
[Fact]
public void ThreeDimensionalFiniteResultsMeetExactSquaredBound()
{
Random random = new(314265);
for (int exponent = -1074; exponent <= 1023; ++exponent)
{
double high = Math.ScaleB(1.0 + (random.NextDouble() * 0.1), exponent);
foreach (int gap in new[] { 0, 1, 26, 54, 55, 500, 1100 })
{
foreach (double sign in new[] { -1.0, 1.0 })
{
DoubleDouble x = DoubleDouble.FromComponents(high, Math.ScaleB(sign, exponent - 54));
DoubleDouble y = DoubleDouble.FromComponents(Math.ScaleB(1.0, exponent - gap), Math.ScaleB(-sign, exponent - gap - 54));
DoubleDouble z = DoubleDouble.FromComponents(Math.ScaleB(0.75, exponent - gap), Math.ScaleB(sign, exponent - gap - 55));
DoubleDouble result = DoubleDouble.Hypot(x, y, z);
AssertBound(x, y, z, result);
AssertBits(result, DoubleDouble.Hypot(-z, x, -y));
AssertBits(result, DoubleDouble.Hypot(y, -z, x));
AssertBits(result, DDMath.Hypot(x, y, z));
}
}
}
}
[Fact]
public void ThreeDimensionalSparseCorrectionsAreCombinedBeforeFinalRounding()
{
// sqrt(a²+2b²) = a+b²/a+O(b^4/a^3). The omitted term is below
// half an ulp of the expected low in these exact dyadic cases.
foreach ((int large, int small) in new[] { (0, -100), (1000, 450), (-500, -600), (0, -537), (-500, -787) })
{
DoubleDouble x = new(Math.ScaleB(1.0, large));
DoubleDouble y = new(Math.ScaleB(1.0, small));
DoubleDouble expected = DoubleDouble.FromComponents(x.High, Math.ScaleB(1.0, (2 * small) - large));
AssertThreeDimensionalPermutations(x, y, y, expected);
}
DoubleDouble sparse = DoubleDouble.FromComponents(Math.ScaleB(1.0, 1000), double.Epsilon);
AssertThreeDimensionalPermutations(sparse, DoubleDouble.One, DoubleDouble.One,
DoubleDouble.FromComponents(sparse.High, Math.ScaleB(1.0, -1000)));
}
[Fact]
public void ThreeDimensionalOverflowUsesAllExactInputSquares()
{
// The third coordinate changes a finite two-coordinate norm to overflow.
DoubleDouble value = new(Math.ScaleB(1.25, 1023));
DoubleDouble.IsFinite(DoubleDouble.Hypot(value, value)).ShouldBeTrue();
AssertThreeDimensionalOverflowBoundary(value, value, value);
AssertThreeDimensionalOverflowBoundary(new DoubleDouble(double.MaxValue), value, DoubleDouble.One);
DoubleDouble x = DoubleDouble.FromComponents(double.MaxValue, Math.BitDecrement(Math.ScaleB(1.0, 970)));
double boundaryY = Math.ScaleB(1.0, 971);
foreach (double y in new[] { Math.BitDecrement(boundaryY), boundaryY, Math.BitIncrement(boundaryY) })
{
AssertThreeDimensionalOverflowBoundary(x, new DoubleDouble(y), DoubleDouble.One);
}
// 1²+2²+2²=3², and 3 divides 2^54-1. These exact scaled integers
// give norm T=(2^54-1)*2^970. Even an epsilon low on the first
// coordinate decides which side of the exact overflow midpoint we are on.
const long factor = ((1L << 54) - 1) / 3;
DoubleDouble first = new(Math.ScaleB((double)factor, 970));
DoubleDouble second = new(Math.ScaleB((double)(2 * factor), 970));
BigInteger a = Units(first.High);
BigInteger b = Units(second.High);
BigInteger threshold = Units(double.MaxValue) + Units(Math.ScaleB(1.0, 970));
((a * a) + (2 * b * b)).ShouldBe(threshold * threshold);
foreach (double low in new[] { -double.Epsilon, 0.0, double.Epsilon })
{
AssertThreeDimensionalOverflowBoundary(DoubleDouble.FromComponents(first.High, low), second, second);
}
}
private static void AssertThreeDimensionalOverflowBoundary(DoubleDouble x, DoubleDouble y, DoubleDouble z)
{
BigInteger a = Units(x.High) + Units(x.Low);
BigInteger b = Units(y.High) + Units(y.Low);
BigInteger c = Units(z.High) + Units(z.Low);
BigInteger threshold = Units(double.MaxValue) + Units(Math.ScaleB(1.0, 970));
bool overflow = ((a * a) + (b * b) + (c * c)) >= threshold * threshold;
DoubleDouble result = DoubleDouble.Hypot(x, y, z);
DoubleDouble.IsPositiveInfinity(result).ShouldBe(overflow);
if (!overflow)
{
AssertBound(x, y, z, result);
}
AssertThreeDimensionalPermutations(x, y, z, result);
}
private static void AssertThreeDimensionalPermutations(DoubleDouble x, DoubleDouble y, DoubleDouble z, DoubleDouble expected)
{
foreach (DoubleDouble a in new[] { x, -x })
{
foreach (DoubleDouble b in new[] { y, -y })
{
foreach (DoubleDouble c in new[] { z, -z })
{
AssertBits(expected, DoubleDouble.Hypot(a, b, c));
AssertBits(expected, DoubleDouble.Hypot(a, c, b));
AssertBits(expected, DoubleDouble.Hypot(b, a, c));
AssertBits(expected, DoubleDouble.Hypot(b, c, a));
AssertBits(expected, DoubleDouble.Hypot(c, a, b));
AssertBits(expected, DoubleDouble.Hypot(c, b, a));
AssertBits(expected, DDMath.Hypot(a, b, c));
}
}
}
}
private static void AssertOverflowBoundary(DoubleDouble x, DoubleDouble y)
{
BigInteger a = Units(x.High) + Units(x.Low);
BigInteger b = Units(y.High) + Units(y.Low);
BigInteger threshold = Units(double.MaxValue) + Units(Math.ScaleB(1.0, 970));
bool overflow = ((a * a) + (b * b)) >= threshold * threshold;
foreach (DoubleDouble first in new[] { x, -x })
{
foreach (DoubleDouble second in new[] { y, -y })
{
DoubleDouble result = DoubleDouble.Hypot(first, second);
DoubleDouble.IsPositiveInfinity(result).ShouldBe(overflow);
if (!overflow)
{
AssertBound(first, second, result);
}
AssertBits(result, DoubleDouble.Hypot(second, first));
AssertBits(result, DDMath.Hypot(first, second));
}
}
}
private static void AssertBound(DoubleDouble x, DoubleDouble y, DoubleDouble actual)
{
AssertBound(x, y, DoubleDouble.Zero, actual);
}
private static void AssertBound(DoubleDouble x, DoubleDouble y, DoubleDouble z, DoubleDouble actual)
{
DoubleDouble.IsFinite(actual).ShouldBeTrue();
DoubleDouble.IsCanonical(actual).ShouldBeTrue();
double.IsNegative(actual.High).ShouldBeFalse();
// Exact integer units of 2^-1074. The squared inequalities are equivalent
// to |actual/sqrt(x*x+y*y+z*z)-1| <= 2^-100, allowing one subnormal unit.
BigInteger a = Units(x.High) + Units(x.Low);
BigInteger b = Units(y.High) + Units(y.Low);
BigInteger c = Units(z.High) + Units(z.Low);
BigInteger r = Units(actual.High) + Units(actual.Low);
BigInteger sum = (a * a) + (b * b) + (c * c);
BigInteger scale = BigInteger.One << 100;
BigInteger lower = BigInteger.Max(BigInteger.Zero, r - 1) * scale;
BigInteger upper = (r + 1) * scale;
((lower * lower <= sum * (scale + 1) * (scale + 1))
&& (upper * upper >= sum * (scale - 1) * (scale - 1))).ShouldBeTrue(
$"Hypot bound failed for ({x.High:R}, {x.Low:R}), ({y.High:R}, {y.Low:R}), ({z.High:R}, {z.Low:R}): ({actual.High:R}, {actual.Low:R})");
}
private static BigInteger Units(double value)
{
long bits = BitConverter.DoubleToInt64Bits(value);
int exponent = (int)((bits >> 52) & 0x7ff);
BigInteger significand = bits & 0xfffffffffffffL;
if (exponent != 0)
{
significand += BigInteger.One << 52;
significand <<= exponent - 1;
}
return bits < 0 ? -significand : significand;
}
private static void AssertBits(DoubleDouble expected, DoubleDouble actual)
{
BitConverter.DoubleToInt64Bits(actual.High).ShouldBe(BitConverter.DoubleToInt64Bits(expected.High));
BitConverter.DoubleToInt64Bits(actual.Low).ShouldBe(BitConverter.DoubleToInt64Bits(expected.Low));
}
}
@@ -0,0 +1,27 @@
using Shouldly;
using Xunit;
namespace Just.PreciseMath.Tests;
public class DoubleDoubleRootFunctionsTests
{
[Fact]
public void ExistingRootsAreAvailableOnTheTypeAndMatchFacadeBits()
{
DoubleDouble[] values = [DoubleDouble.Zero, DoubleDouble.NegativeZero,
DoubleDouble.NaN, DoubleDouble.PositiveInfinity, DoubleDouble.NegativeInfinity,
new(-1.0), new(double.Epsilon), new(2.0), new(double.MaxValue),
DoubleDouble.FromComponents(1.0, Math.ScaleB(1.0, -1000))];
foreach (DoubleDouble value in values)
{
AssertBits(DDMath.Sqrt(value), DoubleDouble.Sqrt(value));
AssertBits(DDMath.InvSqrt(value), DoubleDouble.InvSqrt(value));
}
}
private static void AssertBits(DoubleDouble expected, DoubleDouble actual)
{
BitConverter.DoubleToInt64Bits(actual.High).ShouldBe(BitConverter.DoubleToInt64Bits(expected.High));
BitConverter.DoubleToInt64Bits(actual.Low).ShouldBe(BitConverter.DoubleToInt64Bits(expected.Low));
}
}
@@ -0,0 +1,243 @@
using System.Globalization;
using System.Numerics;
using Just.PreciseMath.Tests.ReferenceData;
using Shouldly;
using Xunit;
namespace Just.PreciseMath.Tests;
public class DoubleDoubleRootNTests
{
public static IEnumerable<TheoryDataRow<double, double, int, string>> ReferenceCases => RootNReferenceData.Cases();
[Theory]
[MemberData(nameof(ReferenceCases))]
public void LargeDegreesMeetIndependentHighPrecisionReferences(double high, double low, int degree, string reference)
{
DoubleDouble input = DoubleDouble.FromComponents(high, low);
(Units(input.High) + Units(input.Low)).ShouldBe(Units(high) + Units(low));
DoubleDouble actual = DoubleDouble.RootN(input, degree);
DoubleDouble.IsFinite(actual).ShouldBeTrue();
DoubleDouble.IsCanonical(actual).ShouldBeTrue();
Math.Sign(actual.High).ShouldBe(Math.Sign(high));
string[] parts = reference.Split('e');
int point = parts[0].IndexOf('.', StringComparison.Ordinal);
int decimals = point < 0 ? 0 : parts[0].Length - point - 1;
BigInteger numerator = BigInteger.Parse(parts[0].Replace(".", "", StringComparison.Ordinal), CultureInfo.InvariantCulture);
int exponent = int.Parse(parts[1], CultureInfo.InvariantCulture) - decimals;
BigInteger denominator = BigInteger.One;
if (exponent >= 0)
{
numerator *= BigInteger.Pow(10, exponent);
}
else
{
denominator = BigInteger.Pow(10, -exponent);
}
BigInteger actualUnits = Units(actual.High) + Units(actual.Low);
BigInteger error = BigInteger.Abs((actualUnits * denominator) - (numerator << 1074));
// 2^-100 relative plus the separately bounded 2^-350 relative reference
// rounding allowance. For |degree|>=2 every nonzero root is normal.
BigInteger magnitude = BigInteger.Abs(numerator);
BigInteger bound = (magnitude << 1324) + (magnitude << 1074);
((error << 350) <= bound).ShouldBeTrue(
$"RootN reference failed for ({high:R}, {low:R}), {degree}: ({actual.High:R}, {actual.Low:R})");
}
[Fact]
public void SpecialValuesMatchRuntimeRootNSemantics()
{
double[] values = [0.0, -0.0, 1.0, -1.0, double.PositiveInfinity, double.NegativeInfinity, double.NaN];
int[] degrees = [int.MinValue, int.MinValue + 1, -1000, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 1000, int.MaxValue];
foreach (double value in values)
{
foreach (int degree in degrees)
{
AssertBits(new DoubleDouble(double.RootN(value, degree)), DoubleDouble.RootN(new DoubleDouble(value), degree));
}
}
foreach (int degree in new[] { int.MinValue, -4, -2, 0, 2, 4, int.MaxValue - 1 })
{
DoubleDouble.IsNaN(DoubleDouble.RootN(new DoubleDouble(-2.0), degree)).ShouldBeTrue();
}
}
[Fact]
public void IdentitiesAndExistingKernelsKeepTheirComponentBits()
{
DoubleDouble[] values = [new(double.Epsilon), new(double.MaxValue), new(2.0),
DoubleDouble.FromComponents(1.0, double.Epsilon), DoubleDouble.FromComponents(1.0, -Math.ScaleB(1.0, -54))];
foreach (DoubleDouble value in values)
{
AssertBits(value, DoubleDouble.RootN(value, 1));
AssertBits(-value, DoubleDouble.RootN(-value, 1));
AssertBits(DDMath.Reciprocal(value), DoubleDouble.RootN(value, -1));
AssertBits(DoubleDouble.Sqrt(value), DoubleDouble.RootN(value, 2));
AssertBits(DoubleDouble.InvSqrt(value), DoubleDouble.RootN(value, -2));
AssertBits(DoubleDouble.Cbrt(value), DoubleDouble.RootN(value, 3));
AssertBits(1.0 / DoubleDouble.Cbrt(value), DoubleDouble.RootN(value, -3));
}
}
[Fact]
public void SmallDegreesMeetIndependentExactPowerInequalities()
{
Random random = new(8675309);
for (int exponent = -1074; exponent <= 1023; ++exponent)
{
double high = Math.ScaleB(1.0 + random.NextDouble(), exponent);
foreach (int degree in new[] { -5, -4, -3, -2, 2, 3, 4, 5 })
{
DoubleDouble input = DoubleDouble.FromComponents(high, Math.ScaleB((degree < 0 ? -1.0 : 1.0), exponent - 54));
AssertBound(input, DoubleDouble.RootN(input, degree), degree);
if ((degree & 1) != 0)
{
AssertBits(-DoubleDouble.RootN(input, degree), DoubleDouble.RootN(-input, degree));
}
}
}
foreach (double high in new[] { double.Epsilon, 1e-308, 0.5, 1.0, 2.0, 81.0, 1e308, double.MaxValue })
{
foreach (int degree in new[] { -31, -17, -7, -6, 6, 7, 17, 31 })
{
DoubleDouble input = new(high);
AssertBound(input, DoubleDouble.RootN(input, degree), degree);
}
}
}
[Fact]
public void ExactPowerOfTwoRootsAndSparseCorrectionsSurvive()
{
foreach (int degree in new[] { -31, -7, -5, -4, 4, 5, 7, 31 })
{
for (int exponent = -1074; exponent <= 1023; ++exponent)
{
if (exponent % degree == 0)
{
AssertBits(new DoubleDouble(Math.ScaleB(1.0, exponent / degree)),
DoubleDouble.RootN(new DoubleDouble(Math.ScaleB(1.0, exponent)), degree));
}
}
}
foreach (int degree in new[] { int.MinValue, int.MinValue + 1, -7, -4, 4, 7, int.MaxValue })
{
foreach (int exponent in new[] { -100, -500, -1000, -1070 })
{
foreach (double sign in new[] { -1.0, 1.0 })
{
double low = Math.ScaleB(sign, exponent);
// (1+d)^(1/n) = 1+d/n+O(d²); the quadratic term is
// below half an ulp of this rounded correction.
AssertBits(DoubleDouble.FromComponents(1.0, low / degree),
DoubleDouble.RootN(DoubleDouble.FromComponents(1.0, low), degree));
}
}
}
foreach (double sign in new[] { -1.0, 1.0 })
{
DoubleDouble input = DoubleDouble.FromComponents(Math.ScaleB(1.0, 900), Math.ScaleB(sign, -174));
// d*r/(n*high), with exact r=2^225 and n=4, is sign*2^-851.
AssertBits(DoubleDouble.FromComponents(Math.ScaleB(1.0, 225), Math.ScaleB(sign, -851)), DoubleDouble.RootN(input, 4));
}
}
[Fact]
public void NegativeDegreeRetainsSparseCorrectionAfterLargeRescaling()
{
// (2^-900+d)^(-1/4) = 2^225 - d*2^225/(4*2^-900) + O(d²).
// For d=±2^-1074, the correction is exactly ∓2^49 at binary64
// residual precision; the quadratic contribution is below half an ulp.
foreach (double sign in new[] { -1.0, 1.0 })
{
DoubleDouble input = DoubleDouble.FromComponents(Math.ScaleB(1.0, -900), sign * double.Epsilon);
AssertBits(DoubleDouble.FromComponents(Math.ScaleB(1.0, 225), Math.ScaleB(-sign, 49)), DoubleDouble.RootN(input, -4));
}
}
[Fact]
public void GenericContractAndFacadeDispatchToTypeMembers()
{
DoubleDouble[] values = [DoubleDouble.Zero, DoubleDouble.NegativeZero, DoubleDouble.NaN,
DoubleDouble.PositiveInfinity, DoubleDouble.NegativeInfinity, new(-2.0), new(double.Epsilon),
new(double.MaxValue), DoubleDouble.FromComponents(1.0, Math.ScaleB(1.0, -54))];
foreach (DoubleDouble value in values)
{
AssertBits(DoubleDouble.Sqrt(value), GenericSqrt(value));
AssertBits(DoubleDouble.Cbrt(value), GenericCbrt(value));
AssertBits(DoubleDouble.Hypot(value, DoubleDouble.One), GenericHypot(value, DoubleDouble.One));
foreach (int degree in new[] { int.MinValue, -7, -3, -2, -1, 0, 1, 2, 3, 4, 7, int.MaxValue })
{
DoubleDouble result = DoubleDouble.RootN(value, degree);
AssertBits(result, GenericRootN(value, degree));
AssertBits(result, DDMath.RootN(value, degree));
}
}
}
private static T GenericSqrt<T>(T value) where T : IRootFunctions<T>
{
return T.Sqrt(value);
}
private static T GenericCbrt<T>(T value) where T : IRootFunctions<T>
{
return T.Cbrt(value);
}
private static T GenericHypot<T>(T x, T y) where T : IRootFunctions<T>
{
return T.Hypot(x, y);
}
private static T GenericRootN<T>(T value, int n) where T : IRootFunctions<T>
{
return T.RootN(value, n);
}
private static void AssertBound(DoubleDouble input, DoubleDouble actual, int degree)
{
DoubleDouble.IsFinite(actual).ShouldBeTrue();
DoubleDouble.IsCanonical(actual).ShouldBeTrue();
(actual.High > 0.0).ShouldBeTrue();
int n = Math.Abs(degree);
BigInteger x = Units(input.High) + Units(input.Low);
BigInteger y = Units(actual.High) + Units(actual.Low);
BigInteger scale = BigInteger.One << 100;
BigInteger power = BigInteger.Pow(y, n) << (100 * n);
BigInteger target;
if (degree > 0)
{
target = x << (1074 * (n - 1));
}
else
{
power *= x;
target = BigInteger.One << (1074 * (n + 1));
}
// Positive degree: x*(1-t)^n <= y^n <= x*(1+t)^n.
// Negative degree: (1-t)^n <= x*y^n <= (1+t)^n.
(power >= target * BigInteger.Pow(scale - 1, n)
&& power <= target * BigInteger.Pow(scale + 1, n)).ShouldBeTrue(
$"RootN bound failed for ({input.High:R}, {input.Low:R}), {degree}: ({actual.High:R}, {actual.Low:R})");
}
private static BigInteger Units(double value)
{
long bits = BitConverter.DoubleToInt64Bits(value);
int exponent = (int)((bits >> 52) & 0x7ff);
BigInteger significand = bits & 0xfffffffffffffL;
if (exponent != 0)
{
significand += BigInteger.One << 52;
significand <<= exponent - 1;
}
return bits < 0 ? -significand : significand;
}
private static void AssertBits(DoubleDouble expected, DoubleDouble actual)
{
BitConverter.DoubleToInt64Bits(actual.High).ShouldBe(BitConverter.DoubleToInt64Bits(expected.High));
BitConverter.DoubleToInt64Bits(actual.Low).ShouldBe(BitConverter.DoubleToInt64Bits(expected.Low));
}
}
@@ -0,0 +1,552 @@
// Generated by generate_rootn.py; do not hand-edit reference literals.
// Exact component sums; Decimal ln/exp at 450/650 digits, rounded to 120 digits.
using Xunit;
namespace Just.PreciseMath.Tests.ReferenceData;
internal static class RootNReferenceData
{
internal static IEnumerable<TheoryDataRow<double, double, int, string>> Cases()
{
yield return new(5e-324, 0.0, -2147483648, "1.00000034665698229989419923796875777142350075077854142640012630161140035250946208062185210474013999887450772416095548287e+0");
yield return new(5e-324, 0.0, -2147483647, "1.00000034665698246131896392462575136026763137841817002802990415631982348939017868346053058592181983751719306827754166287e+0");
yield return new(5e-324, 0.0, -1000000000, "1.00000074444034901696036381644003423525905486873887287323824029337273291571015728203130009836888843502733609521183992801e+0");
yield return new(5e-324, 0.0, -65537, "1.01142384002835288586286148750623054509548208019438032340563103479272537894981668040512149540131911093711836321338905673e+0");
yield return new(5e-324, 0.0, -127, "3.51332423149811114020420972638491067314578593704937010495960733201345230188073045551931737928462302543556060659003148773e+2");
yield return new(5e-324, 0.0, -4, "6.70739427389146133442979443040089115095100886804424598010444624697399335178119519563972910651814833367532781502518894456e+80");
yield return new(5e-324, 0.0, 4, "1.49089193085383538923363765955953714632683137184618392935846325784949277701877750660443120422125365510292025771153525999e-81");
yield return new(5e-324, 0.0, 127, "2.84630718404714827561921128805165683120547576725897388984985662361606740551824176452756624111279429201687409288809745411e-3");
yield return new(5e-324, 0.0, 65537, "9.88705190073399253268372770807075564446601108407927473285629397102400555343754225610683684043240475748153422665512860764e-1");
yield return new(5e-324, 0.0, 1000000000, "9.99999255560205174060318520460459025903574964191594743242974034903643759902333796233914558824581283331575333534453596699e-1");
yield return new(5e-324, 0.0, 2147483646, "9.99999653343137548278214219760787616188995075297095288449907228992257872125380304629649124329672415108890653015495698989e-1");
yield return new(5e-324, 0.0, 2147483647, "9.99999653343137709702867138770758688026024754510221793463292812563739593899022538200764508771816592500417149346007889706e-1");
yield return new(1.5e-323, 0.0, -2147483648, "1.00000034614540091008856398784588832934833939940384321821509192422238098397565536039203174108037788806133223389548491563e+0");
yield return new(1.5e-323, 0.0, -2147483647, "1.00000034614540107127510494333143441288758471913357302345902565352196837788167165466174428113228547134613258294156626160e+0");
yield return new(1.5e-323, 0.0, -1000000000, "1.00000074334173591104441344407164987101742829979226698697162253301985187388526450926051853195346190199442614533446902462e+0");
yield return new(1.5e-323, 0.0, -65537, "1.01140688543253041372103223187090116727472103542266225642050743466868456750846473458880554365112511858539629177285826333e+0");
yield return new(1.5e-323, 0.0, -127, "3.48306332827533373443119127669145245901198674876056141874527614089272699787533548759389498627941559001060103414095066068e+2");
yield return new(1.5e-323, 0.0, -4, "5.09651752703788425957703665020926495608911454305921480449451222216463991937051260397794976885539652420438032469828508406e+80");
yield return new(1.5e-323, 0.0, 4, "1.96212412631729705033078154058910173357105507332164681146669468771984961762045773719486689548007756898757149986001752693e-81");
yield return new(1.5e-323, 0.0, 127, "2.87103594092605225026177329476949823881912320702218188422824388198637964426870678987366041312774553778143040578914351038e-3");
yield return new(1.5e-323, 0.0, 65537, "9.88721764112123644791674837505276028791293390686917665393482307041020229197385292630303551980854129993869743716089530119e-1");
yield return new(1.5e-323, 0.0, 1000000000, "9.99999256658816645481195473888974733905771895733114097627438716007644506468932982122581474976899813407205758619840425093e-1");
yield return new(1.5e-323, 0.0, 2147483646, "9.99999653854718584135674368772976285495222654238342476353728283741528505633179340443855404823254001618072042874733382982e-1");
yield return new(1.5e-323, 0.0, 2147483647, "9.99999653854718745322103886473288706299633470528815449108118280195980171720321616584313570188097200437253589935748570860e-1");
yield return new(2.2250738585072014e-308, 0.0, -2147483648, "1.00000032987284258596031552046040790830599004270199566048050787753143852523144289420893543631852366392988521790302868175e+0");
yield return new(2.2250738585072014e-308, 0.0, -2147483647, "1.00000032987284273956935345414973306343177972736116949915708809079535577689366845591060612936945038792964065167023503939e+0");
yield return new(2.2250738585072014e-308, 0.0, -1000000000, "1.00000070839666944506624946706274822650818826658295909649049750542985227975497853111730600357578840179294134794432761409e+0");
yield return new(2.2250738585072014e-308, 0.0, -65537, "1.01086773603532536932331686782943863353085513221167653957750733090842307517354590260390892360515413223706473125346105030e+0");
yield return new(2.2250738585072014e-308, 0.0, -127, "2.64522034845304669747621535741342655777939331006265807634757459073560114047656102617319188703058316015983014706750957576e+2");
yield return new(2.2250738585072014e-308, 0.0, -4, "8.18773715074641276175512015429796283075074324712432370618218536007567547824852929155240369448016154013101539920067009834e+76");
yield return new(2.2250738585072014e-308, 0.0, 4, "1.22133866975546195086019597071117283027094025981639387493045310083030448293378253341035004249805099426031227511728968499e-77");
yield return new(2.2250738585072014e-308, 0.0, 127, "3.78040340036250950702951053691902736360880275129299568249051702347989433785368892472981094503080381972466248075064997203e-3");
yield return new(2.2250738585072014e-308, 0.0, 65537, "9.89249101887503915866461491810556032286036656752873859925040445338527948016932432229660076996017338303459819956738289004e-1");
yield return new(2.2250738585072014e-308, 0.0, 1000000000, "9.99999291603832380419539892619828616382751750227774031050960754752929713544793305606028160552179366557225828202793914033e-1");
yield return new(2.2250738585072014e-308, 0.0, 2147483646, "9.99999670127265922878191434717557873045485282713747668829617111085491819774836659158522557155007471897958277879135166201e-1");
yield return new(2.2250738585072014e-308, 0.0, 2147483647, "9.99999670127266076487128168616471501977721679308186186576508026987264268412404385026183530565121896323124177674585847034e-1");
yield return new(2.225073858507201e-308, 0.0, -2147483648, "1.00000032987284258596031562385801858548696023895983632610360738082749311080125300707121255031888223719325938530486528935e+0");
yield return new(2.225073858507201e-308, 0.0, -2147483647, "1.00000032987284273956935355754734378876103032132259793811022091957089714252022637322029488672893180704626668920803740192e+0");
yield return new(2.225073858507201e-308, 0.0, -1000000000, "1.00000070839666944506624968910751044719811814096296516166110552526513042082095105458821777934200752035311916938314202439e+0");
yield return new(2.225073858507201e-308, 0.0, -65537, "1.01086773603532536932674176868055212180050657224952509547259712474176514057434424709090347320373355178747041730279693014e+0");
yield return new(2.225073858507201e-308, 0.0, -127, "2.64522034845304670210107289451508381257978670850588518861590447195519702378317194530066904902734199762887330121944915070e+2");
yield return new(2.225073858507201e-308, 0.0, -4, "8.18773715074641321626583537117020913511494541443896563298960534639533131600118144026836217696910989194252502981227226227e+76");
yield return new(2.225073858507201e-308, 0.0, 4, "1.22133866975546188306228036933245893141686363606809552923034822452809083249276724715142720468056663605153578269552119074e-77");
yield return new(2.225073858507201e-308, 0.0, 127, "3.78040340036250950041991857242502362407959531536015656154300652485833325055355261364874258892781579394213854338860091398e-3");
yield return new(2.225073858507201e-308, 0.0, 65537, "9.89249101887503915863109836623393774711320735920855410037584420122449942670641163899890493376565559218270542941585193518e-1");
yield return new(2.225073858507201e-308, 0.0, 1000000000, "9.99999291603832380419539670575380986898588509615126250561101716368405228405442527424581721175087930252054286017115588231e-1");
yield return new(2.225073858507201e-308, 0.0, 2147483646, "9.99999670127265922878191331320015315661828707851369965953859576763217516443237533860827507688586064629691809818241452178e-1");
yield return new(2.225073858507201e-308, 0.0, 2147483647, "9.99999670127266076487128065218928992742282015802799386153593420299115046457964607345697750203997776272764966310281895126e-1");
yield return new(1e-308, 0.0, -2147483648, "1.00000033024527400103758415561171827491536112569422922280293403635443021066023550387443074530186544783958352991173805943e+0");
yield return new(1e-308, 0.0, -2147483647, "1.00000033024527415482004903880163282640997264185745141815648807956600084415882765872208722665376951655176037444148049266e+0");
yield return new(1e-308, 0.0, -1000000000, "1.00000070919646012185669645712321274057427259564244859621779091990197530076194341878032270767698095200397040432580684656e+0");
yield return new(1e-308, 0.0, -65537, "1.01088007237893177201822429377414246386552631376767894483656333882829889424379576641116080655681927313604127676038433880e+0");
yield return new(1e-308, 0.0, -127, "2.66193134612613073925290487110242339291144660910469944694682427579093437393117975739543391926830739650693909104628871467e+2");
yield return new(1e-308, 0.0, -4, "1.00000000000000002266834366568788578576688918082216786934503169822053290495945819636764875306200829619210785845479431326e+77");
yield return new(1e-308, 0.0, 4, "9.99999999999999977331656334312114728086915364909915495978338849867251827386069354804974783593763012673903308351645866322e-78");
yield return new(1e-308, 0.0, 127, "3.75667089031159721107064567254577115566506792595422232685256005454633117192975656077437348073699081750912181687839359360e-3");
yield return new(1e-308, 0.0, 65537, "9.89237029518914741706722637984633793238233438732724096447807882487109254856799437585398286103849380300419544683032575765e-1");
yield return new(1e-308, 0.0, 1000000000, "9.99999290804042837405655986706458090614540941309878365415124935746420726074619716211744748068707252260526645781054135847e-1");
yield return new(1e-308, 0.0, 2147483646, "9.99999669754834753302671920112307536738477011911734917314987683265242095109622698360447132830437620583229350963739681148e-1");
yield return new(1e-308, 0.0, 2147483647, "9.99999669754834907085035374708973065368561880135462995625068565408894995273139669283295926764392716904525636823326991849e-1");
yield return new(0.5, 0.0, -2147483648, "1.00000000032277180844536493248552273843658307496786927891303194319273282055207279274560899910825827041716398431879961122e+0");
yield return new(0.5, 0.0, -2147483647, "1.00000000032277180859566726840708505646978792137378497109441088492007257435200513095235613984898693606233800546941310214e+0");
yield return new(0.5, 0.0, -1000000000, "1.00000000069314718080017181643183694246616754030093671697092943849725637366367267953869962182007700078613681030647808347e+0");
yield return new(0.5, 0.0, -65537, "1.00001057648116457167215270349394297497241259861435957360758872150558426213383522387510316657634694682655547830200490957e+0");
yield return new(0.5, 0.0, -127, "1.00547277302221306857687621252345877639796444631811870580077371310514545554465530820363514238115898312615622360304681075e+0");
yield return new(0.5, 0.0, -4, "1.18920711500272106671749997056047591529297209246381741301900222471946666822691715987078134453813767371603739477476921319e+0");
yield return new(0.5, 0.0, 4, "8.40896415253714543031125476233214895040034262356784510813226085974924754953902239814324004199292536172801573743519085080e-1");
yield return new(0.5, 0.0, 127, "9.94557015198170698569268684444940799852443429879734200797346759717920936017114553597195565202843484576595299109473455393e-1");
yield return new(0.5, 0.0, 65537, "9.99989423630696199059051957856192099125312797258828893503844008959857591057955446665637936075276031946365194145573704209e-1");
yield return new(0.5, 0.0, 1000000000, "9.99999999306852819680281197486364482220171244240985209083889726852474576362142530175522871575565518796328395279731427276e-1");
yield return new(0.5, 0.0, 2147483646, "9.99999999677228191358212036018890550795819617840102092160738848623174608504927461571971108701774630323720801581835599653e-1");
yield return new(0.5, 0.0, 2147483647, "9.99999999677228191508514371983406113774081566473621756422724422138637696671801252012588344215482041058766213312547646733e-1");
yield return new(0.5, 2.7755575615628914e-17, -2147483648, "1.00000000032277180844536490663612858781101325817974082185309632348018361768750986133347797701181155732144460680605452344e+0");
yield return new(0.5, 2.7755575615628914e-17, -2147483647, "1.00000000032277180859566724255769089380715593878979026195433102694670753151335954426649391557465115244325529018052775645e+0");
yield return new(0.5, 2.7755575615628914e-17, -1000000000, "1.00000000069314718080017176092068567273094408094496206532703287653683823769363207836703406521596291999900764262651713314e+0");
yield return new(0.5, 2.7755575615628914e-17, -65537, "1.00001057648116457167130567451269721690340741584755599519957031131539451518903592934904538371249763038005869288655923483e+0");
yield return new(0.5, 2.7755575615628914e-17, -127, "1.00547277302221306813738840809709465781017926157000688843565680683269853903869377087334049514564231859793930893066832692e+0");
yield return new(0.5, 2.7755575615628914e-17, -4, "1.18920711500272105021393596900950952810190083893950374621265391372214412900741121440935135307633400819301897172662137216e+0");
yield return new(0.5, 2.7755575615628914e-17, 4, "8.40896415253714554700907495476096914756896438875198116898633081836766669500743544854403361781590350585643334655789770195e-1");
yield return new(0.5, 2.7755575615628914e-17, 127, "9.94557015198170699003985258293555297767116497252732858137251872732246247911937753245268758378189048112051080177486954855e-1");
yield return new(0.5, 2.7755575615628914e-17, 65537, "9.99989423630696199059898968920549972152051701286602220185092235618534950722376882850490513066299597833870621896256344076e-1");
yield return new(0.5, 2.7755575615628914e-17, 1000000000, "9.99999999306852819680281252997515675000598772430766262071671605787830397881300389414121428904361431529850572970119102532e-1");
yield return new(0.5, 2.7755575615628914e-17, 2147483646, "9.99999999677228191358212061868284708808602359998747355618761863159715432869072576038054552026413929509730952726888673918e-1");
yield return new(0.5, 2.7755575615628914e-17, 2147483647, "9.99999999677228191508514397832800259749802147166910333967366807596395483332596922930674459225086523595731432812046289110e-1");
yield return new(0.5, -2.7755575615628914e-17, -2147483648, "1.00000000032277180844536495833491688906215432668562633593165677740447644016246211581971454553843474112263254679006748566e+0");
yield return new(0.5, -2.7755575615628914e-17, -2147483647, "1.00000000032277180859566729425647921913242133888740894838435884524038597790086193573316697481572226315366168558506822296e+0");
yield return new(0.5, -2.7755575615628914e-17, -1000000000, "1.00000000069314718080017187194298821220139408114482760560476223855516006643237142899683874750408955647721113418734162753e+0");
yield return new(0.5, -2.7755575615628914e-17, -65537, "1.00001057648116457167299973247518873308843805270686164767890629514118603441612772142650785642178245087193751649571677487e+0");
yield return new(0.5, -2.7755575615628914e-17, -127, "1.00547277302221306901636401694982291957432182715352481414357394544659235835779529370559036788205252430596396422431517617e+0");
yield return new(0.5, -2.7755575615628914e-17, -4, "1.18920711500272108322106397211144344764883977703601883441142019480364855737336686868211243635542630661445072063660127670e+0");
yield return new(0.5, -2.7755575615628914e-17, 4, "8.40896415253714531361343456990332389470896206334640001405691357837800501523300005629911375081494779148609572890079440457e-1");
yield return new(0.5, -2.7755575615628914e-17, 127, "9.94557015198170698134552110596326277996165624874984511108857673876214065063057832534352157309682172091285906468850430219e-1");
yield return new(0.5, -2.7755575615628914e-17, 65537, "9.99989423630696199058204946791834226051556051378268025354431167097825641544310787333230730082454883377220606198773446755e-1");
yield return new(0.5, -2.7755575615628914e-17, 1000000000, "9.99999999306852819680281141975213289439740634563298353931308554525718932454936455083652304610119722775823419402487806294e-1");
yield return new(0.5, -2.7755575615628914e-17, 2147483646, "9.99999999677228191358212010169496392783035440751829155053689032543046673895129581512703075336315064345712555141586081522e-1");
yield return new(0.5, -2.7755575615628914e-17, 2147483647, "9.99999999677228191508514346134011967798359550850706173420232637990417996919032077230979681311981084900735954125366889879e-1");
yield return new(0.9999999999999999, 0.0, -2147483648, "1.00000000000000000000000005169878828456423254932229952798060705801423260788874332891627451330292496725726238449108659070e+0");
yield return new(0.9999999999999999, 0.0, -2147483647, "1.00000000000000000000000005169878830863835686537313674738146839754785222125091768697741458132003422046618565892619246806e+0");
yield return new(0.9999999999999999, 0.0, -1000000000, "1.00000000000000000000000011102230246251566020533899501121303922012868601342443752764310067064249540219773634901592531998e+0");
yield return new(0.9999999999999999, 0.0, -65537, "1.00000000000000000000169404004550888292423261710120077616732308551762555599393870812292695130494658208659574050178268555e+0");
yield return new(0.9999999999999999, 0.0, -127, "1.00000000000000000087419135797256425396745163406071560529396578496558600048437765775874919413265016476612535931325583645e+0");
yield return new(0.9999999999999999, 0.0, -4, "1.00000000000000002775557561562891543652073608950652123436054811668055287427735824907041019199855906528841129944234488063e+0");
yield return new(0.9999999999999999, 0.0, 4, "9.99999999999999972244424384371085333851241665387905516501351867559804764645872199864814836954450440009765264637937162988e-1");
yield return new(0.9999999999999999, 0.0, 127, "9.99999999999999999125808642027435746796758896293200373874847557445465207384084617901203457495941398006831367457017801847e-1");
yield return new(0.9999999999999999, 0.0, 65537, "9.99999999999999999998305959954491117075770252670475011570805902091226051158840550019015793833234248249514927929010668837e-1");
yield return new(0.9999999999999999, 0.0, 1000000000, "9.99999999999999999999999888977697537484339794661017314738604858182142000365962220201830254817045130707198801983600921438e-1");
yield return new(0.9999999999999999, 0.0, 2147483646, "9.99999999999999999999999948301211667287518796155253245463849473718935340871699646039859828534214211334955016376523563115e-1");
yield return new(0.9999999999999999, 0.0, 2147483647, "9.99999999999999999999999948301211691361643134626865925383244183854203538924947887514943921858653250787526091990804466704e-1");
yield return new(0.9999999999999999, 2.7755575615628914e-17, -2147483648, "1.00000000000000000000000003877409121342317387389311409468393878988401191878794502936114737397107141562213991710314073927e+0");
yield return new(0.9999999999999999, 2.7755575615628914e-17, -2147483647, "1.00000000000000000000000003877409123147876711093124175866289287334624275055488398913386985563497393433861585068077463056e+0");
yield return new(0.9999999999999999, 2.7755575615628914e-17, -1000000000, "1.00000000000000000000000008326672684688674399844627847051015127434424745031679614468738149059612642431044815895399270944e+0");
yield return new(0.9999999999999999, 2.7755575615628914e-17, -65537, "1.00000000000000000000127053003413166217554204756767150853381061267641897489566588272134823503886039045120177383140169046e+0");
yield return new(0.9999999999999999, 2.7755575615628914e-17, -127, "1.00000000000000000065564351847942318130506236129854477957942524865848328607826014888915994902441728715619625002213241632e+0");
yield return new(0.9999999999999999, 2.7755575615628914e-17, -4, "1.00000000000000002081668171172168621627868749452311585771931691272848671244510406686390342876661333891339512398504134642e+0");
yield return new(0.9999999999999999, 2.7755575615628914e-17, 4, "9.99999999999999979183318288278314217055549992604987162199306413524152589650406949752763407970454235149364714064939189764e-1");
yield return new(0.9999999999999999, 2.7755575615628914e-17, 127, "9.99999999999999999344356481520576819124806062025532946771786728105112843794049476348163653830771894814358618550365186961e-1");
yield return new(0.9999999999999999, 2.7755575615628914e-17, 65537, "9.99999999999999999998729469965868337824459566678896122068842138510889913498731321854977859024133235747584883754210448644e-1");
yield return new(0.9999999999999999, 2.7755575615628914e-17, 1000000000, "9.99999999999999999999999916733273153113256001553728462837648519705400868381177075354596971516878440574995062876985386500e-1");
yield return new(0.9999999999999999, 2.7755575615628914e-17, 2147483646, "9.99999999999999999999999961225908750465639635215050485399403608915831369892240163661385866165358860128818205994311876344e-1");
yield return new(0.9999999999999999, 2.7755575615628914e-17, 2147483647, "9.99999999999999999999999961225908768521232889068759744767257953692371885974806300261535463780572696300548847801911609676e-1");
yield return new(0.9999999999999999, -2.7755575615628914e-17, -2147483648, "1.00000000000000000000000006462348535570529158348389199547831951797706676371112415830425482668121128322778524836501837307e+0");
yield return new(0.9999999999999999, -2.7755575615628914e-17, -2147483647, "1.00000000000000000000000006462348538579794697854743893734888272770741319919731843865740918478496698280106407903972987119e+0");
yield return new(0.9999999999999999, -2.7755575615628914e-17, -1000000000, "1.00000000000000000000000013877787807814457718260369007718241720014034531885657417317916072252106705516384030642055967375e+0");
yield return new(0.9999999999999999, -2.7755575615628914e-17, -65537, "1.00000000000000000000211755005688610368467813014021609394951573430700879037106641315419422932425288431516356384150866965e+0");
yield return new(0.9999999999999999, -2.7755575615628914e-17, -127, "1.00000000000000000109273919746570533274352514965421494845884415895304969015464550105918086883591529276268897116895794846e+0");
yield return new(0.9999999999999999, -2.7755575615628914e-17, -4, "1.00000000000000003469446951953614489750402773289446838020499921816153445830849383322606736191348093899283980963616710333e+0");
yield return new(0.9999999999999999, -2.7755575615628914e-17, 4, "9.99999999999999965305530480463856306202187509128106827575595659667294814160264312910834456950799265466292438529698261378e-1");
yield return new(0.9999999999999999, -2.7755575615628914e-17, 127, "9.99999999999999998907260802534294668450553804023778802134775378404831104587602850234443792095480959181879863465238130175e-1");
yield return new(0.9999999999999999, -2.7755575615628914e-17, 65537, "9.99999999999999999997882449943113896315326353878027324391435265339238903114376197276468969576661105934478183469158346712e-1");
yield return new(0.9999999999999999, -2.7755575615628914e-17, 1000000000, "9.99999999999999999999999861222121921855422817396329182117026672220858005632943872080175758775580250549559652312009604340e-1");
yield return new(0.9999999999999999, -2.7755575615628914e-17, 2147483646, "9.99999999999999999999999935376514584109397598363048971327251146689463082081983548591682573236383260053943813493012633875e-1");
yield return new(0.9999999999999999, -2.7755575615628914e-17, 2147483647, "9.99999999999999999999999935376514614202053021452565238845980680733414838769788455538761271237560453828293935087646132075e-1");
yield return new(1.0, 0.0, -2147483648, "1e+0");
yield return new(1.0, 0.0, -2147483647, "1e+0");
yield return new(1.0, 0.0, -1000000000, "1e+0");
yield return new(1.0, 0.0, -65537, "1e+0");
yield return new(1.0, 0.0, -127, "1e+0");
yield return new(1.0, 0.0, -4, "1e+0");
yield return new(1.0, 0.0, 4, "1e+0");
yield return new(1.0, 0.0, 127, "1e+0");
yield return new(1.0, 0.0, 65537, "1e+0");
yield return new(1.0, 0.0, 1000000000, "1e+0");
yield return new(1.0, 0.0, 2147483646, "1e+0");
yield return new(1.0, 0.0, 2147483647, "1e+0");
yield return new(1.0, 5.551115123125783e-17, -2147483648, "9.99999999999999999999999974150605857717885877733292441215563349010503192784050421523101748409009792828148646874365746308e-1");
yield return new(1.0, 5.551115123125783e-17, -2147483647, "9.99999999999999999999999974150605845680823719707874833801900363995536168967790568669524385492969317548891225265329401946e-1");
yield return new(1.0, 5.551115123125783e-17, -1000000000, "9.99999999999999999999999944488848768742174519562373645991565310590469017415380332501748775391912490863929007719609814295e-1");
yield return new(1.0, 5.551115123125783e-17, -65537, "9.99999999999999999999152979977245558608413352482315899757711013246529789986600098938025002561354385545954630560535512239e-1");
yield return new(1.0, 5.551115123125783e-17, -127, "9.99999999999999999562904321013717909698379639957606487779382801961188642669047031644878526758473317676198347234838468513e-1");
yield return new(1.0, 5.551115123125783e-17, -4, "9.99999999999999986122212192185543726187090245673689312009159954765387699501138476653069422955384053318892662051077327470e-1");
yield return new(1.0, 5.551115123125783e-17, 4, "1.00000000000000001387778780781445646640590419304988530252979393494530670007038413358483346021892600523138234453858528890e+0");
yield return new(1.0, 5.551115123125783e-17, 127, "1.00000000000000000043709567898628209049267299263087247519616579139459107467152726831620701461594728115118439449792976232e+0");
yield return new(1.0, 5.551115123125783e-17, 65537, "1.00000000000000000000084702002275444139158736496060304717670175540856273680601756673261119674511887530222275503948985548e+0");
yield return new(1.0, 5.551115123125783e-17, 1000000000, "1.00000000000000000000000005551115123125782548043762943549634570898672481520788190286931216167044010733032272534010970087e+0");
yield return new(1.0, 5.551115123125783e-17, 2147483646, "1.00000000000000000000000002584939416635623844952793117206220838512295079424246269654068003680023125544290437696694380613e+0");
yield return new(1.0, 5.551115123125783e-17, 2147483647, "1.00000000000000000000000002584939415431917628029212583438927778135486649489155156828359745402601637369017578652983912227e+0");
yield return new(1.0, -5.551115123125783e-17, -2147483648, "1.00000000000000000000000002584939414228211555719633569558829479993750163122639565648758805254974376634423409044788917587e+0");
yield return new(1.0, -5.551115123125783e-17, -2147483647, "1.00000000000000000000000002584939415431917771522175397119313624145367244891148975108219859027333814510068234697336638872e+0");
yield return new(1.0, -5.551115123125783e-17, -1000000000, "1.00000000000000000000000005551115123125782856192554045507371059855160400803778524822618220000393459151955893977352169308e+0");
yield return new(1.0, -5.551115123125783e-17, -65537, "1.00000000000000000000084702002275444143860642153962829039644289079920310478146759583967149271494366022243383341061634097e+0");
yield return new(1.0, -5.551115123125783e-17, -127, "1.00000000000000000043709567898628211475635733136770213060143948344979322519992763694345728511612994204128309412121062027e+0");
yield return new(1.0, -5.551115123125783e-17, -4, "1.00000000000000001387778780781445723677788194794423721597981133770007980754814574896657241795401820836751522338875318351e+0");
yield return new(1.0, -5.551115123125783e-17, 4, "9.99999999999999986122212192185542955815112490779358780676823289575783716315114073181954608761587402888244162174341102749e-1");
yield return new(1.0, -5.551115123125783e-17, 127, "9.99999999999999999562904321013717885434695301220776853585212271403974135887231559501635883249058602244949766477461167207e-1");
yield return new(1.0, -5.551115123125783e-17, 65537, "9.99999999999999999999152979977245558561394295903290656538049530020636338670815050991212352262856212449560334887503782716e-1");
yield return new(1.0, -5.551115123125783e-17, 1000000000, "9.99999999999999999999999944488848768742171438074462626414200421025931938468368788187584725726213397233697633756061537187e-1");
yield return new(1.0, -5.551115123125783e-17, 2147483646, "9.99999999999999999999999974150605833643760115542440691133933465929044961310553349881008430235163076133152452881397638226e-1");
yield return new(1.0, -5.551115123125783e-17, 2147483647, "9.99999999999999999999999974150605845680822284778246696998041903896804399070935223647126897860312815433847341387841556752e-1");
yield return new(1.0000000000000002, 0.0, -2147483648, "9.99999999999999999999999896602423430871552120510938585683809197817796501341773422210950500925234448960931091631367152196e-1");
yield return new(1.0000000000000002, 0.0, -2147483647, "9.99999999999999999999999896602423382723303488409272165176227996764409328058220190119293994106278144819615015297565274062e-1");
yield return new(1.0000000000000002, 0.0, -1000000000, "9.99999999999999999999999777955395074968716567176979190354495558380264504278101408431678491828675435467101366607943945476e-1");
yield return new(1.0000000000000002, 0.0, -65537, "9.99999999999999999996611919908982234715772054060928687752933478525665052269131234304068512531772597237971289640856668445e-1");
yield return new(1.0000000000000002, 0.0, -127, "9.99999999999999998251617284054871785521940387782250404299819593767295655839058800338033578936544976250130965803942228815e-1");
yield return new(1.0000000000000002, 0.0, -4, "9.99999999999999944488848768742180682538194144401113671850926086030581158705255201036377218311832424967234855407533190091e-1");
yield return new(1.0000000000000002, 0.0, 4, "1.00000000000000005551115123125782239894971687517556698994799844790777614917174816728505435194256556320612401332195152613e+0");
yield return new(1.0000000000000002, 0.0, 127, "1.00000000000000000174838271594512821753490173363341249424248202397360589222520642161522897792640480671001183768136126031e+0");
yield return new(1.0000000000000002, 0.0, 65537, "1.00000000000000000000338808009101776528423942502577446319575916800188937706716603853840851067821355321571737055145057498e+0");
yield return new(1.0000000000000002, 0.0, 1000000000, "1.00000000000000000000000022204460492503128343282307011345208075484662608450469113456937767720903206517091711606882748880e+0");
yield return new(1.0000000000000002, 0.0, 2147483646, "1.00000000000000000000000010339757666542494518853395586742727773871528108291422341908166862080056495471814967844671461545e+0");
yield return new(1.0000000000000002, 0.0, 2147483647, "1.00000000000000000000000010339757661727669651159073852588262232884025287473726589495475293974058812524921874103013195654e+0");
yield return new(1.0000000000000002, 5.551115123125783e-17, -2147483648, "9.99999999999999999999999870753029288589443737962743574113212050708073776443154972950713038130718144779920614676724807059e-1");
yield return new(1.0000000000000002, 5.551115123125783e-17, -2147483647, "9.99999999999999999999999870753029228404132947835662218956681690643792913587159583907836454833668502278800125689205257775e-1");
yield return new(1.0000000000000002, 5.551115123125783e-17, -1000000000, "9.99999999999999999999999722444243843710903412691009240603743366704975905688597690797298781560034441104530226977170069435e-1");
yield return new(1.0000000000000002, 5.551115123125783e-17, -65537, "9.99999999999999999995764899886227793512264502631021295924426109220279291823554411085539182829205752013759585592203860287e-1");
yield return new(1.0000000000000002, 5.551115123125783e-17, -127, "9.99999999999999997814521605068589793039267913041064108499846210831337214634527106210476798063484155306940544589323753469e-1");
yield return new(1.0000000000000002, 5.551115123125783e-17, -4, "9.99999999999999930611060960927728260585173164545306351696429722942558484716133550333701537805399207075064342290074972420e-1");
yield return new(1.0000000000000002, 5.551115123125783e-17, 4, "1.00000000000000006938893903907227655423968780354298990589338064189461003432090781932948898575249437951197900703508609133e+0");
yield return new(1.0000000000000002, 5.551115123125783e-17, 127, "1.00000000000000000218547839493141021173704790167090890533371054816409733288337041408013210127051952945716487015713676337e+0");
yield return new(1.0000000000000002, 5.551115123125783e-17, 65537, "1.00000000000000000000423510011377220648775343344195237743191049891968804622457359756358678095013113823784283462634180221e+0");
yield return new(1.0000000000000002, 5.551115123125783e-17, 1000000000, "1.00000000000000000000000027755575615628909658730906779659403212270776421574836814656648747177689897961183980775464253894e+0");
yield return new(1.0000000000000002, 5.551115123125783e-17, 2147483646, "1.00000000000000000000000012924697083178117789834337449227564661995771827186237510668137446559010299299488788554997834588e+0");
yield return new(1.0000000000000002, 5.551115123125783e-17, 2147483647, "1.00000000000000000000000012924697077159586705216435448582277194311256447674225195224248977314536444011253623652468309491e+0");
yield return new(1.0000000000000002, -5.551115123125783e-17, -2147483648, "9.99999999999999999999999922451817573153661937988761734057627257110625964814117295999237149676637610680873994583293108197e-1");
yield return new(1.0000000000000002, -5.551115123125783e-17, -2147483647, "9.99999999999999999999999922451817537042475463912510916390173671569039538479232754199832005509560895242809562738896136363e-1");
yield return new(1.0000000000000002, -5.551115123125783e-17, -1000000000, "9.99999999999999999999999833466546306226532803150863241169155203664006241307698970732868247483377846027769554273677193292e-1");
yield return new(1.0000000000000002, -5.551115123125783e-17, -65537, "9.99999999999999999997458939931736675966299379512780248854461152382846594393487723332029059923744435052309951865516568611e-1");
yield return new(1.0000000000000002, -5.551115123125783e-17, -127, "9.99999999999999998688712963041153802459349833848734415639557131498716369453374178021399731351231982908874946575140505322e-1");
yield return new(1.0000000000000002, -5.551115123125783e-17, -4, "9.99999999999999958366636576556634067456187317874366422346577146541356891031745075161046964544193083451504209722911848173e-1");
yield return new(1.0000000000000002, -5.551115123125783e-17, 4, "1.00000000000000004163336342344336766588076263063761266944488122280776235580662391889682154827506549228271883212444644033e+0");
yield return new(1.0000000000000002, -5.551115123125783e-17, 127, "1.00000000000000000131128703695884619926012385944757606024045175522145114905246463473188545795060611480476161127714711828e+0");
yield return new(1.0000000000000002, -5.551115123125783e-17, 65537, "1.00000000000000000000254106006826332403370707747349027355453689603026389694899868824894032928146668733104735629789770799e+0");
yield return new(1.0000000000000002, -5.551115123125783e-17, 1000000000, "1.00000000000000000000000016653345369377346719684916449222204397252765922735563493884903375928778364519987838622597996855e+0");
yield return new(1.0000000000000002, -5.551115123125783e-17, 2147483646, "1.00000000000000000000000007754818249906871104379490910577568794528944099846347708044594172872606009909654547785972907199e+0");
yield return new(1.0000000000000002, -5.551115123125783e-17, 2147483647, "1.00000000000000000000000007754818246295752453608749509733042963658391677914710093852832723311784141110801354996083710043e+0");
yield return new(2.0, 0.0, -2147483648, "9.99999999677228191658816707807941718273741041868880112443673806175630383600978533229555906993761769452269156830452576800e-1");
yield return new(2.0, 0.0, -2147483647, "9.99999999677228191508514371983406113774081566473621756422724422138637696671801252012588344215482041058766213312547646733e-1");
yield return new(2.0, 0.0, -1000000000, "9.99999999306852819680281197486364482220171244240985209083889726852474576362142530175522871575565518796328395279731427276e-1");
yield return new(2.0, 0.0, -65537, "9.99989423630696199059051957856192099125312797258828893503844008959857591057955446665637936075276031946365194145573704209e-1");
yield return new(2.0, 0.0, -127, "9.94557015198170698569268684444940799852443429879734200797346759717920936017114553597195565202843484576595299109473455393e-1");
yield return new(2.0, 0.0, -4, "8.40896415253714543031125476233214895040034262356784510813226085974924754953902239814324004199292536172801573743519085080e-1");
yield return new(2.0, 0.0, 4, "1.18920711500272106671749997056047591529297209246381741301900222471946666822691715987078134453813767371603739477476921319e+0");
yield return new(2.0, 0.0, 127, "1.00547277302221306857687621252345877639796444631811870580077371310514545554465530820363514238115898312615622360304681075e+0");
yield return new(2.0, 0.0, 65537, "1.00001057648116457167215270349394297497241259861435957360758872150558426213383522387510316657634694682655547830200490957e+0");
yield return new(2.0, 0.0, 1000000000, "1.00000000069314718080017181643183694246616754030093671697092943849725637366367267953869962182007700078613681030647808347e+0");
yield return new(2.0, 0.0, 2147483646, "1.00000000032277180874596960446862733311713999415756678394113658865613268338817468717932028873473804903097531409749939483e+0");
yield return new(2.0, 0.0, 2147483647, "1.00000000032277180859566726840708505646978792137378497109441088492007257435200513095235613984898693606233800546941310214e+0");
yield return new(2.0, 1.1102230246251565e-16, -2147483648, "9.99999999677228191658816681958547584335082611430561169599513723728424576856580718257565489544452237705020459069947882164e-1");
yield return new(2.0, 1.1102230246251565e-16, -2147483647, "9.99999999677228191508514346134011967798360985780333847069259966358007585839150630790421628883798553926885874690633350153e-1");
yield return new(2.0, 1.1102230246251565e-16, -1000000000, "9.99999999306852819680281141975213289439743716051207237584016731569655874945765337488321362949664530428226184353002739314e-1");
yield return new(2.0, 1.1102230246251565e-16, -65537, "9.99989423630696199058204946791834226098574610666386572491828847335444542638143989678076385300355485813923979841750273381e-1");
yield return new(2.0, 1.1102230246251565e-16, -127, "9.94557015198170698134552110596326302127783098519685937928255477363535398448917798333762097169753147298321816070224779651e-1");
yield return new(2.0, 1.1102230246251565e-16, -4, "8.40896415253714531361343456990333037273930712339605549095474201561442065765215381166952041912395670554795993244453114896e-1");
yield return new(2.0, 1.1102230246251565e-16, 4, "1.18920711500272108322106397211144253151700263219769591685932458823782379339473073361605670763436196622268764794342588972e+0");
yield return new(2.0, 1.1102230246251565e-16, 127, "1.00547277302221306901636401694982289517784785134816249915056041303670059954911434134627676603120430745968084045413102624e+0");
yield return new(2.0, 1.1102230246251565e-16, 65537, "1.00001057648116457167299973247518873304141849883167012046891747302097388986443424912520447961621697886872761750815480667e+0");
yield return new(2.0, 1.1102230246251565e-16, 1000000000, "1.00000000069314718080017187194298821220139099965691445010273915595952653528761128675944481872060407331086318118900230989e+0");
yield return new(2.0, 1.1102230246251565e-16, 2147483646, "1.00000000032277180874596963031802150781683415374781615446699803468236660406997413991920105072595167754108588634585506967e+0");
yield return new(2.0, 1.1102230246251565e-16, 2147483647, "1.00000000032277180859566729425647921913241990395778034842566910391711533869444297548606106827235729454681568717045695391e+0");
yield return new(2.0, -1.1102230246251565e-16, -2147483648, "9.99999999677228191658816733657335852212400907236826728936861121512973786603656151560277458862782107652486186439797745912e-1");
yield return new(2.0, -1.1102230246251565e-16, -2147483647, "9.99999999677228191508514397832800259749803582096538007616394135964059256375774369722751252898451082054434045823284486837e-1");
yield return new(2.0, -1.1102230246251565e-16, -1000000000, "9.99999999306852819680281252997515675000601853918675145724379782832109454254783937588221793532867457360688739145176975556e-1");
yield return new(2.0, -1.1102230246251565e-16, -65537, "9.99989423630696199059898968920549972199070260574720767322569567178470058265290262829574351639957004412491555235384479958e-1");
yield return new(2.0, -1.1102230246251565e-16, -127, "9.94557015198170699003985258293555321898733970897434306052301125579488231708164339464417484061410564127086230309536355374e-1");
yield return new(2.0, -1.1102230246251565e-16, -4, "8.40896415253714554700907495476097562559930944880181644734524190847731185308115660697649093610986168995665907658876800146e-1");
yield return new(2.0, -1.1102230246251565e-16, 4, "1.18920711500272105021393596900950861197006369410120625642703806574943503453747826178059735330634342092423949965450872130e+0");
yield return new(2.0, -1.1102230246251565e-16, 127, "1.00547277302221306813738840809709463341370528576464459476982998907441893942517828030474412174779066254340522694470462722e+0");
yield return new(2.0, -1.1102230246251565e-16, 65537, "1.00001057648116457167130567451269721685638786197236446798966114220236890746013124072082464199198066373613250759927643514e+0");
yield return new(2.0, -1.1102230246251565e-16, 1000000000, "1.00000000069314718080017176092068567273094099945704890982500979394154682043200087244578517712524562419087483025384465692e+0");
yield return new(2.0, -1.1102230246251565e-16, 2147483646, "1.00000000032277180874596957861923315841744439963768881345658549678415474062183391932658583519852145530978327249062697717e+0");
yield return new(2.0, -1.1102230246251565e-16, 2147483647, "1.00000000032277180859566724255769089380715450386016166199564128562351107643004736633916818878270333313519693411293572981e+0");
yield return new(81.0, 0.0, -2147483648, "9.99999997953675151720548274836456532846885478889096519484409535509045204346367372146476496522683428992246955854065620638e-1");
yield return new(81.0, 0.0, -2147483647, "9.99999997953675150767654012268072453125196352681260641331020911522249834643826735151670871497223370405459354207594595431e-1");
yield return new(81.0, 0.0, -1000000000, "9.99999995605550854983152906776005982396860509500372960475969270082893070170480731288048724776245830001726339865584975174e-1");
yield return new(81.0, 0.0, -65537, "9.99932949298448561454012152926320641635328645269371540884789610568942854964509927145683761076933578936718300260987356479e-1");
yield return new(81.0, 0.0, -127, "9.65989840555887148969217550077403971354516363872179681774450522143254931517680366106189052793449473619326327704543324247e-1");
yield return new(81.0, 0.0, -4, "3.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333e-1");
yield return new(81.0, 0.0, 4, "3.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0");
yield return new(81.0, 0.0, 127, "1.03520757467236033530543471288810022494088079600069305193374347011395988538050538471388319049046761733844078421133773453e+0");
yield return new(81.0, 0.0, 65537, "1.00006705519764948361423716244794675338601948936662461164012021889870230765706274666593292157958282024079296414803229970e+0");
yield return new(81.0, 0.0, 1000000000, "1.00000000439444916432803046622530569418042241089634134263709292574059098835890918049534151352113171108211517096641746995e+0");
yield return new(81.0, 0.0, 2147483646, "1.00000000204632485437268565224228310592409670452122348099825563365809215156076135811360127268551268339371689581311981503e+0");
yield return new(81.0, 0.0, 2147483647, "1.00000000204632485341979138488658465545255815924147291691528125897789412620393583797475378619089111778411488026131876557e+0");
yield return new(81.0, 3.552713678800501e-15, -2147483648, "9.99999997953675151720548254412243919011146830770935958350900360773622300802850967916662690335507295568393937424277670883e-1");
yield return new(81.0, 3.552713678800501e-15, -2147483647, "9.99999997953675150767653991843859829778692581590703910114487212520803992317733131791965726152853321266366539486765331944e-1");
yield return new(81.0, 3.552713678800501e-15, -1000000000, "9.99999995605550854983152862915343473899560964452044574553905506851944282433824814712831727288411868278387266594299252229e-1");
yield return new(81.0, 3.552713678800501e-15, -65537, "9.99932949298448561453342947411679505757177889008659801705464697829300832828769143728393791748793890372077230477548931972e-1");
yield return new(81.0, 3.552713678800501e-15, -127, "9.65989840555887148635603734569946492320255693200169929676175951815336380909892128732789953342772860889871488119942584837e-1");
yield return new(81.0, 3.552713678800501e-15, -4, "3.33333333333333329678278108229937415673471064382680099801478904651305169342611206833234474930584025521058313804092610036e-1");
yield return new(81.0, 3.552713678800501e-15, 4, "3.00000000000000003289549702593056361964333528155806054292362775870476646462356741677018423459517913648800660398250581685e+0");
yield return new(81.0, 3.552713678800501e-15, 127, "1.03520757467236033566295353382096553818723844000461087086238289608233192459410292214131865526216439513474217866131813643e+0");
yield return new(81.0, 3.552713678800501e-15, 65537, "1.00006705519764948361490645771301300939842250502944446176628212170658921357479799289060217785312223286655626511873850904e+0");
yield return new(81.0, 3.552713678800501e-15, 1000000000, "1.00000000439444916432803051008596858816462621762544084455281511052671439785814350475153187174225080408952640379644598318e+0");
yield return new(81.0, 3.552713678800501e-15, 2147483646, "1.00000000204632485437268567266649582237051357618387727952830257732690495549543553915311068681404724698204100289880701364e+0");
yield return new(81.0, 3.552713678800501e-15, 2147483647, "1.00000000204632485341979140531079736238820982122567978006018092670841577912727902929236265745260752401624662049341836864e+0");
yield return new(81.0, -3.552713678800501e-15, -2147483648, "9.99999997953675151720548295260669146682625022826757891642473180391014620268366545751514497642613536170654263652711765849e-1");
yield return new(81.0, -3.552713678800501e-15, -2147483647, "9.99999997953675150767654032692285076471701019591318600720570558586823316669893771456364761008584725062347804698132478197e-1");
yield return new(81.0, -3.552713678800501e-15, -1000000000, "9.99999995605550854983152950636668490894161978306427408311952692975143906557073176403287965435996544008442485174277679296e-1");
yield return new(81.0, -3.552713678800501e-15, -65537, "9.99932949298448561454681358440961777542831646751618930226946955647716641453205118777190111722327662820710663818812238640e-1");
yield return new(81.0, -3.552713678800501e-15, -127, "9.65989840555887149302831365584861465136516785797409441419449282016696677202308000477989427384640472600349948769479087080e-1");
yield return new(81.0, -3.552713678800501e-15, -4, "3.33333333333333336988388558436729451384626080618540601242204802808724919275262667286949180105243198761208525632285528775e-1");
yield return new(81.0, -3.552713678800501e-15, 4, "2.99999999999999996710450297406943529824294013543534767144048022101150474947433251744180451014309821010093857265247169471e+0");
yield return new(81.0, -3.552713678800501e-15, 127, "1.03520757467236033494791589195523489613698327641020925033316214815623990875574587118576713418208378841043639647481712243e+0");
yield return new(81.0, -3.552713678800501e-15, 65537, "1.00006705519764948361356786718288049734426118776131224904095546417634770768519231673882800203230037693861291725943726682e+0");
yield return new(81.0, -3.552713678800501e-15, 1000000000, "1.00000000439444916432803042236464280019621668040950271861183269824978669778445336689214327319445823513512431270481642420e+0");
yield return new(81.0, -3.552713678800501e-15, 2147483646, "1.00000000204632485437268563181807038947767893703906520516823309322645725463387513845431586644786635676434459238880421942e+0");
yield return new(81.0, -3.552713678800501e-15, 2147483647, "1.00000000204632485341979136446237194851690560143776199361887049838641682019884703637662642561544491139338887661467725135e+0");
yield return new(1e+308, 0.0, -2147483648, "9.99999669754835060867398723195218791326991427498538637371948190354122788311804960394428617533500866151893426408670645847e-1");
yield return new(1e+308, 0.0, -2147483647, "9.99999669754834907085035411819516293942997025201092362487693165134292211930637518666855779147038604526207326933076186678e-1");
yield return new(1e+308, 0.0, -1000000000, "9.99999290804042837405656066400712605042434016975548903742491073332714697157573471301606460038262639354756235897027851526e-1");
yield return new(1e+308, 0.0, -65537, "9.89237029518914741707925570122451348700382476019331160034738533886864989404239803017703333034176438925901825317363884388e-1");
yield return new(1e+308, 0.0, -127, "3.75667089031159721342801022673693733746820734892571643635301261952019300174152540960672418138554228805803270984627109828e-3");
yield return new(1e+308, 0.0, -4, "9.99999999999999997255234092639886164483118941322693002202644466118298883688905501765798127653785006601604392452173303686e-78");
yield return new(1e+308, 0.0, 4, "1.00000000000000000274476590736011384305062094488369602433687160865381803822283746860825719590929513268274096591178940102e+77");
yield return new(1e+308, 0.0, 127, "2.66193134612613073758250499198827902827076725914565617542164746424082297594721007507115768273386965561918862293063279447e+2");
yield return new(1e+308, 0.0, 65537, "1.01088007237893177201699504326060747428284587692839590936991112888267274372447738613818581891247782590566552411502701205e+0");
yield return new(1e+308, 0.0, 1000000000, "1.00000070919646012185669637742884518833990916296723151534878606554095918526875396003177140962595763319943478196366700898e+0");
yield return new(1e+308, 0.0, 2147483646, "1.00000033024527430860251402810208452903269459333607441020022743177379303006250203974777017702808163183034198605526344277e+0");
yield return new(1e+308, 0.0, 2147483647, "1.00000033024527415482004900169106508666844503918180778637396065330366093947941333214951754596932587856763218421901912301e+0");
yield return new(1e+308, 4.9896007738368e+291, -2147483648, "9.99999669754835060867398699960587269488885148601539419155133556341818996071592829581100730034690703366769368458499898971e-1");
yield return new(1e+308, 4.9896007738368e+291, -2147483647, "9.99999669754834907085035388584884761285425889763503864534801553131791167983542893071462869729292249885354224498709524667e-1");
yield return new(1e+308, 4.9896007738368e+291, -1000000000, "9.99999290804042837405656016504740252721407122286880922225880153258800673517830122751490396865002670206734381087157705765e-1");
yield return new(1e+308, 4.9896007738368e+291, -65537, "9.89237029518914741707172423373592598114221536618186055045083850269007290251950970328259376749450521294485484233404572523e-1");
yield return new(1e+308, 4.9896007738368e+291, -127, "3.75667089031159721195208203922914809163940501735404837185321378469127304072823502683528326598792173658912533397790110228e-3");
yield return new(1e+308, 4.9896007738368e+291, -4, "9.99999999999999984781232158047887901823676337415865078929218046142145311665451458644883601390276065847030561419372147855e-78");
yield return new(1e+308, 4.9896007738368e+291, 4, "1.00000000000000001521876784195211232978721828981988568931547300757177242546605561282654673053122176800730435966797549587e+77");
yield return new(1e+308, 4.9896007738368e+291, 127, "2.66193134612613073862832977187263925710630129895927392740024124361108940300066515378163418252354233894569812884551807010e+2");
yield return new(1e+308, 4.9896007738368e+291, 65537, "1.01088007237893177201776466774622599782007594774654862571682344726723325714727413419229972038135939041865672529683398500e+0");
yield return new(1e+308, 4.9896007738368e+291, 1000000000, "1.00000070919646012185669642732488831277996492510914472434753542052742785401708380986217157671797255184217885767139237517e+0");
yield return new(1e+308, 4.9896007738368e+291, 2147483646, "1.00000033024527430860251405133673141876679967917468123056251212486346698276480535564537386580046383335106848530694849615e+0");
yield return new(1e+308, 4.9896007738368e+291, 2147483647, "1.00000033024527415482004902492571196558307096608776916110219302203522257370944547201576225545134624605282600400251122932e+0");
yield return new(1e+308, -4.9896007738368e+291, -2147483648, "9.99999669754835060867398746429850313165098865710892607200161129428667556698395119353159299532370764291482054059113003320e-1");
yield return new(1e+308, -4.9896007738368e+291, -2147483647, "9.99999669754834907085035435054147826600569319954036151900085791921664093585886494878737456720420404189753746498974298498e-1");
yield return new(1e+308, -4.9896007738368e+291, -1000000000, "9.99999290804042837405656116296684957363463401274041979674462458858591386950189895673755627152713728449493453584090815549e-1");
yield return new(1e+308, -4.9896007738368e+291, -65537, "9.89237029518914741708678716871310099324123004831188229375606957187263442161685531435202413254854469052246022940941769308e-1");
yield return new(1e+308, -4.9896007738368e+291, -127, "3.75667089031159721490393841424472665751979949105648024816706058038805060922799845533697189074027552411648793543608157728e-3");
yield return new(1e+308, -4.9896007738368e+291, -4, "1.00000000000000000972923602723188520514618286625414810014485384087593930960680082100760109027835573669796708623596338045e-77");
yield return new(1e+308, -4.9896007738368e+291, 4, "9.99999999999999990270763972768114889511850807332727492031621711279322588573758160280977540651371629098482878910872212292e+76");
yield return new(1e+308, -4.9896007738368e+291, 127, "2.66193134612613073653668021210391874766363758885197898567839813469119065960724837274531596184798498430264585076455605709e+2");
yield return new(1e+308, -4.9896007738368e+291, 65537, "1.01088007237893177201622541877498895070721520276689014312641166889738336580541516930327584914132043615865163819711601497e+0");
yield return new(1e+308, -4.9896007738368e+291, 1000000000, "1.00000070919646012185669632753280206389985091121196694495912762956405919089982604860207784579421412784422273606390519619e+0");
yield return new(1e+308, -4.9896007738368e+291, 2147483646, "1.00000033024527430860251400486743763929858834818134712126578357394720908634167015276320944363533889855487877645102553964e+0");
yield return new(1e+308, -4.9896007738368e+291, 2147483647, "1.00000033024527415482004897845641820775381795295972648292238445627641681505133451796063777800312059523263663117065260742e+0");
yield return new(1.7976931348623157e+308, 0.0, -2147483648, "9.99999669481722826465117435386976948342107936031989673865218868781888935318907599395825073603473067968269630805495549131e-1");
yield return new(1.7976931348623157e+308, 0.0, -2147483647, "9.99999669481722672555576371318018995851073920880658770768273929732126297892521930138317645770719010289957523033659774987e-1");
yield return new(1.7976931348623157e+308, 0.0, -1000000000, "9.99999290217539002306167341463050715678964286598129188091549109572144398346147322215063776616206069393783375690468680537e-1");
yield return new(1.7976931348623157e+308, 0.0, -65537, "9.89228176670490881197007837638381180315076928480059686472643713938449857234504315081834645364772235512522141232078817501e-1");
yield return new(1.7976931348623157e+308, 0.0, -127, "3.73936204240359858431392626661716510073843597455000769515838556045473967372702485958018207961023474321002798177436901061e-3");
yield return new(1.7976931348623157e+308, 0.0, -4, "8.63616855509444486508818122304097055415111538584065636011289536797300988764707973121273069940936828291643022408397584041e-78");
yield return new(1.7976931348623157e+308, 0.0, 4, "1.15792089237316192209694896490707222964874608799567844200466962889572704321535999944925308227539057659339055339681605199e+77");
yield return new(1.7976931348623157e+308, 0.0, 127, "2.67425295721624466668055053864756772962064008507350326031301900994352702596675163325520840634150917319380015469674320560e+2");
yield return new(1.7976931348623157e+308, 0.0, 65537, "1.01088911899554311098818861889612056746965306444907634348051101306639917879372594731419735820185731890890822809484680683e+0");
yield return new(1.7976931348623157e+308, 0.0, 1000000000, "1.00000070978296478919335497166435299517459580890220582295692617067802908675450037170016139538617087580132809475448149745e+0");
yield return new(1.7976931348623157e+308, 0.0, 2147483646, "1.00000033051838672372182067663744348054125113142207904822572636386893043897582061214864025605254492371298344050311243108e+0");
yield return new(1.7976931348623157e+308, 0.0, 2147483647, "1.00000033051838656981217772934576675933587458237208296338252492692852030276973055222630198026689392817200222219541819761e+0");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, -2147483648, "9.99999669481722826465117422462284149049658203977730691177620160558888071923363689156319793389648787326081551919429569180e-1");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, -2147483647, "9.99999669481722672555576358393326190540097088282409121061392394844297088507070939850864310072342127536314546297804252483e-1");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, -1000000000, "9.99999290217539002306167313707494800470814948378621791700279348334837580755188241247627918081203557890519997469061018852e-1");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, -65537, "9.89228176670490881196588889602024793385177044152075281205143852298138618576294969087668520599513209425064709197880671026e-1");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, -127, "3.73936204240359858349669677116719925636364968738969014814908093023397831213385346395914573071697673511328898574089570503e-3");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, -4, "8.63616855509444480516272388298082468976940693701934262155287904721286694029555962874437939859727373029276969525682272167e-78");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, 4, "1.15792089237316193013163918620202419275311801113039901781425408506670203535359999986930517479777335259071819175446281896e+77");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, 127, "2.67425295721624466726500274470532142872794291011613109790485913995178327028896408890294568583629575992882978266237211471e+2");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, 65537, "1.01088911899554311098861674055840747859184875149885269247373796221765482950460451708695544232859017529865473543970267747e+0");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, 1000000000, "1.00000070978296478919335499941994831123826190752762875639444000431905690742327147179518382792974418227711949696424995972e+0");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, 2147483646, "1.00000033051838672372182068956214483556940079530743192705761129327807565311777327614952935547282627768771645543655684361e+0");
yield return new(1.7976931348623157e+308, 4.9896007738368e+291, 2147483647, "1.00000033051838656981217774227046810834548918316883553964492793630628632323132425672291210898445292652634170108073959678e+0");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, -2147483648, "9.99999669481722826465117448311669747634558026818537123136722509442160033001556055975288557886342597385486604895967609593e-1");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, -2147483647, "9.99999669481722672555576384242711801162051112211197054106744586493125129972911899794292358589724168692341172107359001592e-1");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, -1000000000, "9.99999290217539002306167369218606630887114395189068313230507578843306757324746751957548790202205932204621027519424635239e-1");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, -65537, "9.89228176670490881197426785674737567256605134138840685551561682096314433807473036412309984821565045034747139504294652296e-1");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, -127, "3.73936204240359858513115576206713096797450105859477999411756817464599318795695017805428527798671744461550576596422600464e-3");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, -4, "8.63616855509444492501363856310111849761477696364233315980107827284676758712602285586084378478360279452396707828870307249e-78");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, 4, "1.15792089237316191406225874361212009928878517588125180875116688662481229316095999831925379112362843167644711836553553909e+77");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, 127, "2.67425295721624466609609833258981401441926062799468182846853218111582562553339344952182228179908048391557972406096353261e+2");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, 65537, "1.01088911899554311098776049723383365633557479554281695199304619195521971101638070966545626044858958454134518817634965355e+0");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, 1000000000, "1.00000070978296478919335494390875767911092893990425910809106322596711849375098075545811812979336642245362364623466143971e+0");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, 2147483646, "1.00000033051838672372182066371274212551310110880420056753635878098051014528956787702795952197194570487070061209584818025e+0");
yield return new(1.7976931348623157e+308, -4.9896007738368e+291, 2147483647, "1.00000033051838656981217771642106541032625962284280495231054414736561982135841189956819866041115979121483252410318300874e+0");
yield return new(-2.1249313539597645e+148, 7.098034416949286e+131, -2147483647, "-9.99999840959763964179712921675691428515177718723571125780356831687858337194530199366841567701767531684180057320600539734e-1");
yield return new(4.147625292410626e+216, 1.5309010345804195e+200, 65537, "1.00763971146755381356101977036748995722022832175355406561587388662802510175034004187147375035572203474817319914211890904e+0");
yield return new(-6.723931397868513e+213, -0.0, 127, "-4.82705306355030649541384882095489431503608390910772341499236257472207239776711667187328298638897436079156939466143776782e+1");
yield return new(2.0719930910441882e+176, -7.029552803973744e+159, -2147483648, "9.99999810949224521798166743711040733472235756808201697990471160035993573185085833146199024328917202123788955401907082392e-1");
yield return new(-3.3000510598222188e-99, -0.0, -127, "-5.96272416257708074819707187424664138298406053061723556918481976790686544194847136104871206302072128236666876371239128647e+0");
yield return new(6.130809850815003e-231, -2.860444667617094e-247, -53170702, "1.00000996952178597269401615194114127424567017535626214352498682835322932680726382255436788740947477760137973996366756928e+0");
yield return new(1.0673131375869938e+265, 0.0, 1000000000, "1.00000061025038025015090687096894188043000474816658796696872180079595604871392884901404633292112522859287160273558300629e+0");
yield return new(7.571974537692792e+227, 2.1040543606193494e+211, 2147483647, "1.00000024433775540814709993203556477142342652538709914250421563870957566249488312232755435709274304465678630881380442052e+0");
yield return new(-6.710722759246113e-258, -2.310648801106982e-274, -127, "-1.05921974655416148266259807170021903487171620132278754624074405537762865610447581686271516136378559574900914136952384983e+2");
yield return new(4.4219592497775426e-302, 1.295163e-318, -4, "2.18070197038685288902412936528224870839186931685767063796651126203731881886399195485722555076600676063807363859488083148e+75");
yield return new(5.4503591398500374e-179, 1.712351053912815e-195, 2147483646, "9.99999808861403122340379966561346260951072969762338308700177635445127758284926222248627773674083017121470554595737059345e-1");
yield return new(1.9788769873e-313, -0.0, 4, "6.66967542059683665866478315331038565571951139888143170901431132901687415366540334211174115503638858465164768069764946390e-79");
yield return new(4.150578829354881e+228, 0.0, 4, "1.42733911242931247429577876386562625555391280785402393751085960246020631826474043170759793748194238395109051675300160075e+57");
yield return new(3.1411739986208755e+244, 0.0, -127, "1.18802627899609840586180371314299308798100247692469762386569922845562671535199037531971188200436874453678195425031896091e-2");
yield return new(-8.53402411825752e-293, 2.781342323134e-309, -65537, "-1.01031441369176016576967882174010708468727721476587298167757702115437890155267583089462561862575444494310152437126750570e+0");
yield return new(1.879983117875532e-78, 0.0, 2147483646, "9.99999916660428435723604792884923782999102066850050801736796396704762313932397550766648884955754721895217582610630103528e-1");
yield return new(2.7085161747010475e-104, -7.745183829698637e-121, 4, "1.28287061770418613919758339932187218888180987652433606278863966228345395667101239913544061761004265525949095359522423004e-26");
yield return new(-1.146787127910177e-157, -0.0, 65537, "-9.94501206405199288572143322681749502751866013332995552873909125174983998263146163002403000642369556374492818074932925528e-1");
yield return new(6.095063458890788e+165, 0.0, 127, "2.02019610473746063644113231143831566578614369963072931079608925885278036059691214673576519332238370795516744981732185760e+1");
yield return new(9.419192233451517e+271, 3.75375841440235e+255, 65537, "1.00960136896884983332153416368889555175398504957762309840108452367861317987951740784721255099720995866244099475129384015e+0");
yield return new(-1.9284912425757565e-264, -5.509016039626555e-281, 65537, "-9.90777403547877938857947185871148394545659670700306921262686248205798360370672564111186426509274736954311796100019763240e-1");
yield return new(4.537464672119312e-31, 0.0, -2147483648, "1.00000003253471600151508957129925679543386258946918407983548660837927682091867286971768423599429958543220440960502244458e+0");
yield return new(2.074671233602811e-40, -1.0195788231247695e-56, -2147483647, "1.00000004254914960207101566481974026852769930674618737351465375027363016070691350819341436531561259481379421466054037733e+0");
yield return new(3.782603411569593e-284, 0.0, 1678787032, "9.99999611264791411916583072884556276528610707320261433869695743811086052422178350392875695442003904089456692599002314350e-1");
yield return new(2.6616983223047094e+121, -1.1467493079950358e+105, -2147483648, "9.99999869804949295874918922284487208644069629167057527270641986535082738387266594843180725512794064572965094105764792431e-1");
yield return new(4.825008666001236e+245, 0.0, 1000000000, "1.00000056570732032671875016807413753414765153117520087708394175074792027588990170328600460087926335806169666445097028526e+0");
yield return new(-1.5e-322, -0.0, -65537, "-1.01137135116170984240934522864436163916836395622381981239847760066875578196608025327220015655646529097907724124018110612e+0");
yield return new(8.844526457207711e-71, 4.021529366771898e-87, -2147483648, "1.00000007511291134744092917798352066633252091438029252481430366772388051227176237362623066399710195206004044994556290920e+0");
yield return new(-1.1787287859059328e+129, -0.0, -2147483647, "-9.99999861606446501249297209346091269794233555102852065202749688038741272191181079531538877469824452000169406703683226833e-1");
yield return new(2.3350871320145874e+180, 0.0, 2147483646, "1.00000019339537550305130301742589754522576267979304110089461106484148629948218728903316643333187870183496866196900863674e+0");
yield return new(-5.737115427319538e-215, -2.5764595078388533e-231, 127, "-2.05617739071458567917218646485167850251579039481661277943517266484366258646370472457755736536256468593145852187610735573e-2");
yield return new(6.232446458923528e+147, 1.7745086042373215e+131, -2147483648, "9.99999841530923428205499510049696468394303333502304939200623486234522701253580555760436868800603798465892158669820479774e-1");
yield return new(8.86758227496169e-85, 2.8574684782056875e-101, 4, "9.70401159215481242958894596465183172264702128871277134121554110391166902608968169099277300707752299732738646510049898011e-22");
yield return new(1.4652643542498693e+241, 7.40298315191607e+224, 65537, "1.00850915199303793446218185009094172923619467801463183307008625882587081879256845894899134910986077117616579793198678057e+0");
yield return new(9.942317307166815e+135, 3.227812347608636e+119, -2147483648, "9.99999854180140026961534388398578738485909789196093559996464369495464048983163023862748688498228642539386242086511605514e-1");
yield return new(-3.913734663518928e-150, 1.3566642758087631e-166, -127, "-1.50119216248492058529247361242447879462074991235942344876928947155856098146907556730116610938716387154966633746595211178e+1");
yield return new(916490419270.2593, 0.0, -4, "1.02204029269375628922508541744587141595150707924840493727978386568825257230768330044522076847231386056741188096207033492e-3");
yield return new(1.9038429550492584e-208, 5.403227209783267e-225, -2147483648, "1.00000022272294301301616871872044096804599391197663863566625894798433795617689637727708932167462312873587564170225541740e+0");
yield return new(1.626982079293464e-126, -8.200532357869981e-143, 2147483646, "9.99999865126341748491073661679962863415533786512719346489319213481823788161475499644878346102476165022677695366369701146e-1");
yield return new(9.447758514200265e+80, 0.0, -2147483648, "9.99999913176253035490573610006805571817927543590094876509804010780006538578081188614978928528826277934113938899202365569e-1");
yield return new(5.396284183652472e-194, -1.520873253036128e-210, 1000000000, "9.99999554984301581243033862324002124786986989493302527202460182455595352186605190715821128233682799524266195830635327728e-1");
yield return new(4.3199835477524154e+95, 0.0, -2147483648, "9.99999897457275475428768039101163249022352314370889690214826632436071737776425349061702177724925914302226849643696622297e-1");
yield return new(4.5872338840381304e-288, 1.8227805048890994e-304, -65537, "1.01014651504979221720668658338108968123272232998008247778126815819597417542793825031315875640294302428386629660815427417e+0");
yield return new(1.2068303045666464e+237, 0.0, -2147483648, "9.99999745795226193124934994066765071631871383912168307491429321374387316571782529547607144613543664269456211614675397633e-1");
yield return new(4.7625512484234156e-88, -1.3952482803738708e-104, 1376157086, "9.99999853892631852063577219837254098756897104046550152723519593693575903527392459510082430765824993678100299233533025416e-1");
yield return new(1.0513145438304164e+270, -2.932623761251836e+253, -4, "3.12296294983883607851336713752414784201127948516079717906180320823257000669955357806200044373499489855749221265736950030e-68");
yield return new(5.589422625399524e-209, 2.7016136048916335e-225, -287493552, "1.00000166793239364143231691107584263920961145635638194715363314972530397861177096817329061949894289808780228167099545492e+0");
yield return new(9.615901074926444e-33, 0.0, -4, "1.00983984674504747176184394157868224681809918602354860972647042167880073495413474904683668927311521592203203546840513572e+8");
yield return new(-1.4012400209486434e-48, 7.596454196607839e-65, -65537, "-1.00168270452972400782734718583655504768846563273007622173469378155886027962955040980088132719478098658430261762146121159e+0");
yield return new(3.0221268469846867e-89, -8.720301752336693e-106, 2147483646, "9.99999905087005833148610228969076804861474126455243503205524487577298430899247839908037055646833423327992237755515911757e-1");
yield return new(-8.112565918300184e+307, -0.0, 65537, "-1.01087684601302523180576498789829049312508009625204767473744208676403325568780073007238549378204405092655945868643786569e+0");
yield return new(4.9935058803537105e+169, -1.6759759912428246e+153, -2147483647, "9.99999818045187930911224446224482494300714248375911104055452182966626158801625625828244203767999083958280689899711932406e-1");
yield return new(3.1490401162258356e-16, 1.232595164407831e-32, -4, "7.50681048108497054324406404249243435200625398767498323401986335673087607760661351855173437240522820447015177386211811797e+3");
yield return new(-3.711354237109857e+159, 1.9510928439474951e+143, -1696990351, "-9.99999783485871544903782361780700641036204683545478083114994805712095431762655829454281094820910460066602574183740225785e-1");
yield return new(5.7309522218258495e+54, 1.7014118346046923e+38, -2147483647, "9.99999941286876295835265117247595151130920191781550351733086706866642724199221699806648402627879594439089323961256900331e-1");
yield return new(1.5097634622323465e-198, -4.641336831775293e-215, 4, "3.50531642383722160523262156357848280688354417986285681432244990751101959271496262851673832398644174941536798059859087175e-50");
yield return new(-1.306744008329486e+82, -4.2124916667422875e+65, -127, "-2.25639860574197311275127836096912955860498225890896759803965714537679468930051846938231596555251151627951278618600141405e-1");
yield return new(3.34331251507222e-09, 1.0339757656912846e-25, -1000000000, "1.00000001951630394090106065437907584290293576107256441134586317200311441575920883468529736876207801527320150943790203606e+0");
yield return new(-7.7183963962973715e+177, -0.0, -2147483647, "-9.99999809264610889491610122352101269808108060370249749234926740489078549833848552947839319435827082391470081448810832648e-1");
yield return new(2.4746306664250554e+229, -1.3465947907963836e+213, -264698264, "9.99998004529601097627222871737544495143911415613166764290120809034966902699848214806513821333738538094018135643019116138e-1");
yield return new(6.539020872461836e-39, 3.2626522339992623e-55, 127, "5.00420100578283124538413626088226788750431023492643460708634689309751940531689993467162302884615936318471074965479617955e-1");
yield return new(7.370176192288791e+114, 0.0, -65537, "9.95972364542456800622180565560918857306928177692353341371133294656266258220093452978654461653130140664353767395207945668e-1");
yield return new(3.672438494588782e-258, 0.0, -4, "2.28434327527581428547537990347253839001328374006662709886425144021656532257826014871037562906367464086527751349161331674e+64");
yield return new(3.7946133980463076e+306, 0.0, -1000000000, "9.99999294075628174287847828145404398040555810945548414332025537979689241000862781965316611278042618779273314873642185108e-1");
yield return new(5.214312182655994e-233, 0.0, -2014436629, "1.00000026550896800825660566661370448515587366060346784619323074507712987415985543738345440665041084696192119429780869485e+0");
yield return new(5.482507924459564e+164, 0.0, -2147483648, "9.99999823362806627413350777611240471330272282369558603747243546863527948017347530189340060725638769191057061046348743426e-1");
yield return new(4.791478301944406e+90, 2.261564242916332e+74, -221640664, "9.99999057937315127854056660282027850679325658330346746760387138587814098157070692943467936015076398246996664446012532096e-1");
yield return new(7.094453661392563e-208, 2.161290883913307e-224, 448787579, "9.99998937185085132390741206105477340106059076021932449319402386181584592483093831211054543454803803179561038489268359922e-1");
yield return new(-1.5299279906036949e+162, -4.994797680505588e+145, 65537, "-1.00571448207764218254394335724791622004661125124897421569807375515534060138267705749766151486113634675862726821655194354e+0");
yield return new(2.1956345791758541e+133, 6.304320991423117e+116, 2147483647, "1.00000014297212966086444707305936402291520154065936241728804774840618710195577821638039418000261317353473072729477195680e+0");
yield return new(1.363223602490958e-65, 0.0, -1000000000, "1.00000014935819000756943197112251515000670928296411213060681825637761834366568255807272246114125508576637183785253781991e+0");
yield return new(4.139015047904233e+124, -1.1742712913869166e+108, -1307873984, "9.99999780605026620859373986278204453882845217141126956645379842118844267825460673797353777003094719085659362917360916389e-1");
yield return new(-3.0476766336554833e-177, -1.0959046745042015e-193, 127, "-4.07483465690623096144982821089593883294576565812933472885300486643125559704468985861045809256160770039774448763706252522e-2");
yield return new(4.2413190257712564e-109, 0.0, -2147483647, "1.00000011619968127401343762179001090324301417297472518286050965237911121334465301501150476612005267236557227826367327542e+0");
yield return new(1.717425831066361e+229, 6.732973953981918e+212, 2147483647, "1.00000024579133743873458028998613473024927167247685714936459519996729470213564659698034334840469739485200339319830620054e+0");
yield return new(3.638111390158817e+69, 0.0, 2147483647, "1.00000007458489488924001547879127636700692262115764720462803219525978265146128734105039369825667775325164971837562487525e+0");
yield return new(1.0345198924418813e-164, 0.0, -127, "1.95534109916375607675029254620595780865017064859500712835689868164702653559566991115773183726212212909385133179152053015e+1");
yield return new(2.7444129262342785e-214, 0.0, -127, "4.80382316585726757792338360424348090562028880381675459618443378188496551100766249787536001988031521453566842883761552636e+1");
yield return new(7.438051478184081e+150, 3.6341936214780345e+134, -1000000000, "9.99999652605687475861141057571799724595441166283463672002265613592389361373386045452200025149274744144210055520736947380e-1");
yield return new(-4.2597739132243285e+102, -1.2433080910244666e+86, 2147483647, "-1.00000011004177326543213484812227885632383510083155670501530271424581092244430106134733927517918711933489596954654052577e+0");
yield return new(-1.5706963483578736e-198, -0.0, 2147483647, "-9.99999787909779106008527685251180855950833593562688359568846346430694972350275818050472003356017315663315729098282114555e-1");
yield return new(211.89402314672793, 7.105427357601002e-15, 2147483647, "1.00000000249412202650732834610980320594256417047400774142914274190118361856052595085236408284360973222648923505954459702e+0");
yield return new(3845.8509267737836, 1.1368683772161603e-13, 2147483647, "1.00000000384391759732620859812337468689827732807422971207704645551725241212328716285635291521643450282589991322548812538e+0");
yield return new(7.194211435727692e+43, -2.4758800785707605e+27, -2147483648, "9.99999952975458763643386305058877486036271472333829400321552162516612299438695772346592103090439829465002853181773642631e-1");
yield return new(-8.511077515644868e+234, 3.530017448385272e+218, 2147483647, "-1.00000025189777309831131009623824123776775550295700902051108260673320291667364766634010017385802245185030999231074593344e+0");
yield return new(2.340661158076484e-166, 0.0, 127, "4.96388330698122356918647136417083074020060521165476013617866219817106177365125157388922277565202745752053695364810163365e-2");
yield return new(4.1275614106280375e-271, -1.3134517764154804e-287, 4, "2.53468144652280153556564611352264072257884133969229693013950444296212067942472990824642268732420375796345295708964932872e-68");
yield return new(-9.213242775985736e-17, -0.0, -639047811, "-1.00000005777862803187000272965251737775232550995641263281601383372607441597676684696685792365793705604581986807174244908e+0");
yield return new(-2.8177282979766444e-179, -0.0, 65537, "-9.93746434039797726984894795713540288393487399471650024864191895435377419145563061809435828145413282412517879292791262550e-1");
yield return new(7.760878248329169, -2.220446049250313e-16, -2147483648, "9.99999999045815550189167034707965663409053897698279007700498639296358980422573380113993812792497680208514920153218926296e-1");
yield return new(1.8419099676959588e+174, 0.0, -4, "2.71445658827725156181076683334444614481310154460521810740678887487181766908905713199541635980218473584787818838214263006e-44");
yield return new(-4.58057917440228e-98, -1.6242827758820155e-114, 127, "-1.71218447286765365790130497482630913052641396082053156274452170324892729526321035852729208455618253989588853024865708890e-1");
yield return new(5.530440212706587e+165, 2.0458691299350887e+149, 719523440, "1.00000053040232986901483575057711851457513670998666378008926078179870444432128630874341502190163778421727886219376473113e+0");
yield return new(-7.447226329194892e+122, -0.0, -65537, "-9.95692304941108527193994638909786165038801340972425596567932720287173772731456072607886472076620104037162386218316014717e-1");
yield return new(1.2874265305647036e+282, 6.448907850777164e+265, -1989476957, "9.99999673491299720756272177699742024123053449392723140115069438158817979406378411321796237705169801046516661605404838861e-1");
yield return new(8.130944145689043e-189, 3.986877980439027e-205, 1752848613, "9.99999752920560959020900176252112960242209047173598898749713649167774053647839881849651271885455936856117383063344704400e-1");
yield return new(3.876183036820604e+214, -1.1960164332659527e+198, 2147483646, "1.00000023008702235336384382383614715214062478898779417654927956135141492163277461711548319623347540883688732271471319614e+0");
yield return new(2.3641941970577807e+134, -1.0086913586276987e+118, 2147483646, "1.00000014407879779239530775616128802042207490750772367715257157529727765365034575704539634159047113973472205977586206209e+0");
yield return new(1.9936857683827697e+157, 7.621456421669903e+140, -4, "4.73244769673434352383694491221270547002175645583108454523996488948364213532651761498900807162529157525174755421604992108e-40");
yield return new(1.9084940105219224e+251, -6.359114106063704e+234, 1000000000, "1.00000057859534018260592056053976143664903654482007171833995932261407873448614467658931085729626058463392189189485771106e+0");
yield return new(2.7949104333320924e-117, 0.0, -4, "1.37533351497915778437600229137150021298713951320621732125280688878540514344889084092761491451204936030572159631438592438e+29");
yield return new(2.195423021185122e-306, 0.0, 188663626, "9.99996269533423749853867589661341375595492223304861156828649008665259861671991360119557481840037697819901725171015581450e-1");
yield return new(-1.3476092412136668e+94, -4.631683569492648e+77, -65537, "-9.96698302844303395351717468126818581523166928407903886345435693244846133223521568222471555440850787346461086087787139439e-1");
yield return new(1.8657452817557343e+23, 8388608.0, -418208531, "9.99999871874650270253390180030108539493406134433687301956381164274040243484286936855223710751807717621276257771838093727e-1");
yield return new(3.0577532342784968e+57, -8.711228593176025e+40, -1340787680, "9.99999901278161971090596420772026770098283785227452211510197363850356005305608601020250792584323142174244864962667657797e-1");
yield return new(1.200446821794621e-191, 3.8934355277724873e-208, 1000000000, "9.99999560389037706048535894703202705167720037375994927440591354086581535097938045433773608495441210689837138303311476253e-1");
yield return new(407298368777235.6, 0.0, 2147483646, "1.00000001566510993076042694191285932805091574774807710218272935884494883557926583788156121769964023426355182984760245330e+0");
yield return new(2.553152947715566e-256, -7.394076163542342e-273, -1000000000, "1.00000058852462794154661513094287176579695358607723506900030111985549473747010193929024394381202850185229851179349631104e+0");
yield return new(-8.089804228406667e-96, -0.0, -127, "-5.60733358752204256505303564370453421006744321857002992231614645467680865099542076304144316652330013155324183886348359710e+0");
yield return new(1.5848183572932293e-221, 6.142758149716505e-238, 4, "6.30949896244072396113027807326015467716157454837279787415516116381525930567061185697721080732531988657736085607783192420e-56");
yield return new(-5.400811906966802e-165, 2.409919865102884e-181, 65537, "-9.94245226339258584622472338249494929517881175825041035140083444388302426426673246620758209380365419777419693221540892761e-1");
yield return new(1.2467239335212755e-194, 3.80218313259032e-211, 1000000000, "9.99999553519110889459914545781680656587977473793294069157520601453343753010644623624163888707011803016287684726711554573e-1");
yield return new(-0.0001948344460245681, 6.776263578034403e-21, 127, "-9.34942214783034135539245070771771093859563789033835855877426324483608824490562600749535782057442886608439593908885790348e-1");
yield return new(-6.416747067394642e-66, -2.635549485807631e-82, -65537, "-1.00229311306113946815089917251601295418224344456637035651219084135914843239201102259668875578560015258615740089330510839e+0");
yield return new(-1.9044882322677707e+50, -0.0, 127, "-2.48830588153866380614487162514486985507024178399639839808774218882641263195653644147887825640478553900719541565908138514e+0");
yield return new(2.090698705146643e+95, -7.410693711188237e+78, 2147483646, "1.00000010220477989583480519579838471403236714515717529108154991815187557929846398836908271262964710242349631301026077396e+0");
yield return new(1.197469438278476e+216, -3.827252586451049e+199, -2147483648, "9.99999768315566247587557829846422278270850487965058812317251200309548908719951952268107946717915207682664369244347218050e-1");
yield return new(1.4325686162863053e-198, 4.641336831775293e-215, 127, "2.76805131703498506950946442003834590959556969649772371562393365770074789605935809748874669745913611398186747568718219748e-2");
yield return new(8.278146179900204e+28, 4398046511104.0, -1000000000, "9.99999933414000561001114382792928588119982748717931721884590292180884808272693121431301018425984839616562010808691145327e-1");
yield return new(-6.46953423188362e-287, 2.916448807822559e-303, 65537, "-9.89995378237226425736836362869430740957609347565097513012226701232437043165635327221365866022852771414913372479087224388e-1");
yield return new(2.3203253413093892e+232, 6.894565328877484e+215, -65537, "9.91869274580625281355601787002286264911499679547846224482940533268157589486848769844758178431887459072571833648488110041e-1");
yield return new(6.942208929397988e+283, -2.0636505122486924e+267, -1000000000, "9.99999346431012245575047758202155308987669710247702466994199995434672356021744010985371956830033807612252779129972505001e-1");
yield return new(1.5657194360141887e+74, 6.277101735386681e+57, 4, "3.53735368848383592943287999138846407139876094526073947555242245136981989528797475587989021130057883731043718973909766738e+18");
yield return new(1.390358791636951e+138, -4.131599804939054e+121, 65537, "1.00486533526076262818537314310295266061745925769196282883113448968241314578756017565713525728200833312599088720706550773e+0");
yield return new(9.348734100869121e-52, 0.0, -1668134332, "1.00000007043748562451548319528373646253405802865824138390576584077472469081147391600624650441760905785682143075705476529e+0");
yield return new(5.178613773208296e-92, 0.0, 65537, "9.96797891566569842800049585877877528127936415829353028192957166154442160635270768183594779549246721749721632293408430855e-1");
yield return new(5.0698267559551676e+151, 1.4536774485912138e+135, -2147483648, "9.99999837338166647266350174723685949013840814786201550832745996724358377917411268025669096148626418410905344600615923294e-1");
yield return new(1.034081095065623e-251, 4.845781754539109e-268, -1559378052, "1.00000037060637828545488805849060888397685461087262205738101272004964085330467362025703567192367910711932923038183371924e+0");
yield return new(5.791360190131223e-307, 0.0, 2147483646, "9.99999671644931075345309086648411894880937948221630629423613276787165385319606396272193015123081378100976754939511822170e-1");
yield return new(3.1912726020696516e+93, 1.157920892373162e+77, -65537, "9.96720210424809643195460585585345032365924291220844697285519347350438099114791572893450810018343537673375717597774521975e-1");
yield return new(8.03058474954203e-111, 3.6931914471142943e-127, 2147483647, "9.99999881953153232202262291518000434956020453260694517983299137824431868487737164388099237580353011145056661838951380078e-1");
yield return new(2.5716376285935388e-306, -8e-323, -1566221104, "1.00000044926393330741218605535007621690756604827093176375016511671389558134278666076860075230766034954906607033670027553e+0");
yield return new(1.8398707077556116e-147, -6.946121092140867e-164, 2147483646, "9.99999842666887164084108667095974690029187671198470502507407582564312410787533069805456056930069491986671976754661608315e-1");
yield return new(-3.30509212760339e+249, 9.936115790724537e+232, -2147483647, "-9.99999732459394300862374803801064442288845757057651033966190540721139526893177694863892140496876295874925340942670874971e-1");
yield return new(2.6075806986752073e+116, 0.0, -65537, "9.95918170855849105018928408920364369751082373624741073813007896568306115498669086958253119187756514513692368147968431238e-1");
yield return new(1.7194682538687896e-213, 0.0, -1000000000, "1.00000048990872972467452708796197761722411163691124717656309940040393025231577669792505649185211633418813178677598852976e+0");
yield return new(9.283304623938825e+38, -3.777893186295716e+22, 2147483647, "1.00000004178213562591174618971926870964597389286142791370619443871801932482348571453127807926668605591142723233402126928e+0");
yield return new(-29.863764427512745, -8.881784197001252e-16, 1860190475, "-1.00000000182596669650524853637025515251383605308449188703748631144884343004677391701001858671287174270746932945573042305e+0");
yield return new(-4.2676029742400253e+254, -0.0, 2147483647, "-1.00000027302081987069667460513200540345897074176718889183120969832862103453902965595415356330303052580713689487373980706e+0");
yield return new(-1.2495399091493833e-207, 4.322581767826614e-224, 2147483647, "-9.99999778153241511682335912169117627921421238241223276516635694621422792380317611836323676103160771569618145541946452282e-1");
yield return new(-3.237099341581014e+110, 1.668739871813211e+94, 65537, "-1.00389022489656233489139161409503494171714439670952589297443836449608606855458658142809198309820497341024317818424378928e+0");
yield return new(5.928034092430919e-273, 2.0522684006491881e-289, 127, "7.18587423017942264667593353946128371685538993537989697926984841146193472263548979008216163052791208446408060022659906783e-3");
yield return new(-7.002249664452283e-219, 3.1450921726548502e-235, 127, "-1.91534038242071261078453423201789649388251780126961812394298790734722238205110405605317613811759588670119806126595506850e-2");
yield return new(-1.7043622022420916e+249, -4.968057895362269e+232, -65537, "-9.91281694140230336016766475373925084549157933431974614837124920047225953951838180039301249910233622531316562779569122227e-1");
yield return new(9.527094080692736e+49, 5.192296858534828e+33, 4, "3.12420924700163130594830839437242830109011892848502568546609912734780333951782227893326527258375302229190864203112869753e+12");
yield return new(6.507489929274241e+227, 0.0, 1000000000, "1.00000052455990750147713999080233311815420762808590177472242433609731429934097738171224173744953605172833282978719789162e+0");
yield return new(5.290346928108257e+107, 1.629628781067589e+91, 4, "8.52846827442236959278408089678801198216809550226192670261387678476545698832914470223015974175819887132964020315307614232e+26");
yield return new(4.50467536892071e-142, -1.8208839675781755e-158, -1000000000, "1.00000032546202033961547851786351136311568918394038176183362621822125204117251117181989607384880539227660611939373768935e+0");
yield return new(3.40442595555678e-226, -1.8746210173695387e-242, -375217534, "1.00000138362274360042592849450718126563831971523761345371255819697510140963585300541560779166137330903010476958901622325e+0");
yield return new(9.406402187281749e-30, 0.0, 2147483646, "9.99999968876987103932087248329640714805889435499902178097563345622217774551073024598157198647600848378694897257622459998e-1");
yield return new(-2.2606664499036677, 1.1102230246251565e-16, -127, "-9.93598063278491865561122265063379829983457588848534382350968318906475351215983574612945039749645084105116543746115511511e-1");
yield return new(2.9686257747532166e-141, -1.4567071740625404e-157, -2147483648, "1.00000015067701383786785310618039391509027487717112356123331845038729823168524216734973205672624769847329408634160970425e+0");
yield return new(2.4429246575911563e+33, -7.205759403792794e+16, 2147483646, "1.00000003579934382260962854602507341817773082725192995839888339488982888465350593773249573921291793241774135897054745669e+0");
yield return new(-3.3869862816314936e+144, -0.0, -2147483647, "-9.99999845031570511173808423646736533527316810988792722911256156906815858030627091821281129293493629186943253272071814757e-1");
yield return new(2.082433985866284, 1.1102230246251565e-16, 2147483646, "1.00000000034157996806357694227518406697945620653291173191992400226258605740920621716491602041286186672114263155868134766e+0");
yield return new(-8.00074107062234e-176, -0.0, 65537, "-9.93867008882567484926971157172212439008323279078747059999968037201514544545603197811237076607713953168366487940419542216e-1");
yield return new(4.782055213399832e+292, 2.2158278651204453e+276, -1000000000, "9.99999326080509514521567917867658467649955336350602060763736581071289825463095097877326778914143580546988380293379203968e-1");
yield return new(-3.911094773942849e-13, -1.262177448353619e-29, 65537, "-9.99564161275031603674208440138132132076911199556349768541916174188626619198242301699097125515433399419061397353997422175e-1");
yield return new(3.2323184998191025e-111, -9.232978617785736e-128, -127, "7.41316771373334974704707310475452764651308798187991236053535121857379252737856087405404581704639907841483598231517519659e+0");
yield return new(8.50733799716881e+216, -3.061802069160839e+200, 65537, "1.00765075691389445388761716901924128856465626346358997109444725431682550419542628802718773813774625907651326027945144844e+0");
yield return new(6.822720636297485e+151, 2.9073548971824276e+135, 65537, "1.00534880717635509911862344432239101620302447974752476017083008952674209041158885703341742338508216200644353869910555851e+0");
yield return new(2.5148010091452363e-228, -7.322738349099761e-245, -4, "7.94097984083363964717434593833912174414208055701225727478690372691207652687552968588395552870305134854005140436009252606e+56");
yield return new(2.274366904916594e+134, 1.0086913586276987e+118, 65537, "1.00473166977755143042050199564225048751743245547219670260107760131511187974443269675486987825119112769677476931330407588e+0");
yield return new(4.66102099783489e+296, 0.0, -65537, "9.89630945934300978628014785899623091488939794853343967141108052043453068342812804080815561476876457566745422538392837453e-1");
yield return new(7.329403297733799e-287, 0.0, -774361326, "1.00000085083059515686647088014915734346069336113719564137852986414650769396406897862663074933687793623968704541567337352e+0");
yield return new(3.002155134780217e-286, -1.1665795231290236e-302, 1000000000, "9.99999342560209926354471914398470166430817976965411937438270987643086458881075142419081024445689360682949830853620658847e-1");
yield return new(5.148517738656379e-173, 0.0, 4, "8.47072442738447554572844895348745109337898464461978416360865048353969629348121630200665482065079070543083904545408049187e-44");
yield return new(1.7596423883680487e-28, -5.605193857299268e-45, -2147483647, "1.00000002975914300630241196097170309794556641781906136435313725880986645126229497601116652338236448216630026420892746694e+0");
yield return new(408988352478.6724, 1.52587890625e-05, -1000000000, "9.99999973263047842895861730292735288694519402567871481600124646936313227671046590712048975430310698245174537675230140831e-1");
yield return new(1.5622940179640235e+197, -8.299031137761986e+180, 65537, "1.00695228584730754963423025032266621731542753968072748036732547389997298873817246098518855776065322203775911376176868856e+0");
yield return new(2.945877775190306e+282, 0.0, -372999610, "9.99998256274755929921801031270711978088318789491278345501794105149834796972419091036724814094860185027214804184276294552e-1");
yield return new(5.490742494230184e-34, 0.0, -178423553, "1.00000042923058541965400877781486081135730222137682140392083768831054953099968966791732827505043492889345728277931475002e+0");
yield return new(-0.012189473504087868, 4.336808689942018e-19, -65537, "-1.00006724950357789197825048507090927566078556528650583654352033842105064398061203275492892572405532556513218247285634302e+0");
yield return new(3.492031375473187e+156, 1.9053641054174757e+140, -2147483648, "9.99999832150653060990722311513683255874288082127195082020162678364589548681943322383725064312202742527559819702420679717e-1");
yield return new(8.54395894740883e+245, -2.4258095192198577e+229, -4, "3.28916160305874816795257876986270287439992256944275372029294363630216921625254532288551531840797217278759837285332701527e-62");
yield return new(4.730269133184354e-141, 0.0, -127, "1.27327484345976243951250303325270531714709638688114769719191343218565399429490239331108496755994285419222452843455982501e+1");
yield return new(7.247927092725443e+37, -2.3611832414348226e+21, 2147483646, "1.00000004059465872177657209530344287933141751217669601847096909386853787771407668347260438464880057870596684634113373114e+0");
yield return new(2.983386071693106e-147, -1.3892242184281734e-163, -127, "1.42476239933536814162987280140427439820415853972452097683300979398773801510291431809818527031686311479471639200765823634e+1");
yield return new(-8.434229609096888e+281, -0.0, 1161283319, "-1.00000055900130513350607153711111153207696797022597897669175821208187429708923725633237332223728994507033679999659930981e+0");
yield return new(2.1249966937065933e+252, 1.0174582569701926e+236, -1000000000, "9.99999418994955102524571670681225162129377215045179611381410261019296346666622783273710633160704344321857317321109210464e-1");
yield return new(2.3562951965630124e+66, 0.0, -65537, "9.97670786680017019551761514287146332833852335069843086019124138245078225906369328029580956078906592959565200183521446878e-1");
yield return new(2.19934054611654e+147, -8.872543021186608e+130, -1697275144, "9.99999800110115602063608175827920269677445595886600513702700293196185420393623240505818150691057879982767568894559758724e-1");
yield return new(3.723612085826178e-28, 0.0, 628590675, "9.99999899524940864012837431207602901705446337688745154126451943513207111373762585068307216910833396591650368381146332837e-1");
yield return new(8.27429963953444e-97, 2.598852441411225e-113, 1454096851, "9.99999847852237107936935278161046793789919468972115951458087277505614246262168703107872870744504752604597236794299111142e-1");
yield return new(8.80127389806102e-285, 0.0, 2147483646, "9.99999695428760705480824162446971926882079327342011684595607301211741817420396861015126524410192250400014881213971769219e-1");
yield return new(2.37e-321, 0.0, -4, "1.43299121000516229210780300997594144222621650467393763902519451332474365775140734553999063518699325312875686956828218043e+80");
yield return new(1.397172630062729e+22, -524288.0, 2147483647, "1.00000002374468525854188561540049639103404663000432796644410385472727873708370934772620937274178319124206536963284272180e+0");
yield return new(3.4135408696738415e+145, 0.0, 595303896, "1.00000056291028024992293105425216089589013983141845639009895653925536046152845580605000269221884477576820321279790716094e+0");
yield return new(4.5885623477675914e-79, -1.4981364335015035e-95, 51672230, "9.99996509143484927274438061314275514298012607698048581312578365779740057455897762569048130956160931454225970790205647115e-1");
yield return new(-7.940780653230948e-249, 2.481040258324024e-265, -127, "-8.98554418811462828003467444384223268701071872180950009986048869892767579001670397242684562888725012463339591898961615167e+1");
yield return new(4.751340980299204e+96, 2.3714219875802357e+80, -127, "1.73286698206959275279726305600342072765724502774477119626882651426453042362863192067891586952126938124347056404659568047e-1");
yield return new(4.040267235518782e-231, 0.0, 1683086412, "9.99999684804797747503627700550309310151217931250328641481546176109918819087942658423850411108452012974025503634311011481e-1");
}
}
@@ -0,0 +1,93 @@
"""Generate independent RootN fixtures using only Python's standard library.
Run: python3 path/to/generate_rootn.py [--check]. Exact binary64 input sums
are formed at 2200 digits and verified with Fraction. Decimal ln/exp at 450
and 650 digits must agree after rounding to 120 significant decimal digits.
Sparse corrections below that reference precision have separate exact tests.
"""
from decimal import Decimal, localcontext
from fractions import Fraction
from pathlib import Path
import argparse
import math
import random
import sys
OUTPUT = Path(__file__).with_name('RootNReferenceData.cs')
def reference(high, low, degree, precision):
with localcontext() as context:
context.prec = 2200
value = Decimal.from_float(high) + Decimal.from_float(low)
assert Fraction(value) == Fraction(high) + Fraction(low)
negative = value < 0
assert not negative or degree % 2
with localcontext() as context:
context.prec = precision
result = (abs(value).ln() / degree).exp()
if negative:
result = -result
with localcontext() as rounded_context:
rounded_context.prec = 120
rounded = +result
assert abs(result - rounded) <= abs(rounded) * Decimal(2) ** -350
return format(rounded, 'e')
def inputs():
degrees = [-2147483648, -2147483647, -1000000000, -65537, -127, -4,
4, 127, 65537, 1000000000, 2147483646, 2147483647]
for high in [math.ulp(0.0), 3 * math.ulp(0.0), sys.float_info.min,
math.nextafter(sys.float_info.min, 0.0), 1e-308, 0.5,
math.nextafter(1.0, 0.0), 1.0, math.nextafter(1.0, math.inf),
2.0, 81.0, 1e308, sys.float_info.max]:
for low in [0.0, math.ulp(high) / 4, -math.ulp(high) / 4]:
for degree in degrees:
yield high, low, degree
rng = random.Random(20260916)
for _ in range(192):
high = math.ldexp(rng.uniform(1.0, 1.999), rng.randint(-1074, 1023))
low = rng.choice([-1, 0, 1]) * math.ulp(high) / 4
degree = rng.choice(degrees + [rng.randint(4, 2147483647), -rng.randint(4, 2147483648)])
if degree % 2 and rng.randrange(2):
high, low = -high, -low
yield high, low, degree
def generate():
rows = []
for high, low, degree in dict.fromkeys(inputs()):
first = reference(high, low, degree, 450)
assert first == reference(high, low, degree, 650), (high, low, degree)
rows.append(f' yield return new({high!r}, {low!r}, {degree}, "{first}");')
content = '''// Generated by generate_rootn.py; do not hand-edit reference literals.
// Exact component sums; Decimal ln/exp at 450/650 digits, rounded to 120 digits.
using Xunit;
namespace Just.PreciseMath.Tests.ReferenceData;
internal static class RootNReferenceData
{
internal static IEnumerable<TheoryDataRow<double, double, int, string>> Cases()
{
''' + '\n'.join(rows) + '\n }\n}\n'
return content, len(rows)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--check', action='store_true')
args = parser.parse_args()
content, count = generate()
if args.check:
assert OUTPUT.read_text() == content, 'Fixture is stale; regenerate it'
print(f'Verified {count} RootN references at 450/650 digits with exact input sums.')
else:
OUTPUT.write_text(content)
print(f'Generated {count} RootN references in {OUTPUT.name}.')
if __name__ == '__main__':
main()