"""Reproduce DoubleDouble's precomputed mathematical constants. Run: python3 -B 1-tests/Just.PreciseMath.Tests/ReferenceData/generate_constants.py Standard library only; no dependency on the implementation under test. Decimal evaluates formulas at 160 and 240 digits; Fraction-based splitting rounds the high and then the exact residual to nearest-even binary64. """ from decimal import Decimal, localcontext from fractions import Fraction from generate_irrational_arithmetic import arctan_inverse, split def constants(precision: int) -> dict[str, tuple[float, float]]: with localcontext() as context: context.prec = precision one = Decimal(1) pi = 16 * arctan_inverse(5) - 4 * arctan_inverse(239) e = one.exp() ln2 = Decimal(2).ln() ln10 = Decimal(10).ln() sqrt2 = Decimal(2).sqrt() sqrt3 = Decimal(3).sqrt() sqrt5 = Decimal(5).sqrt() sqrt_pi = pi.sqrt() sqrt_tau = (2 * pi).sqrt() values = { "Pi": pi, "E": e, "Ln2": ln2, "Tau": 2 * pi, "PiOver2": pi / 2, "PiOver3": pi / 3, "PiOver4": pi / 4, "PiOver6": pi / 6, "InvPi": one / pi, "InvTau": one / (2 * pi), "DegToRad": pi / 180, "RadToDeg": 180 / pi, "InvE": one / e, "Ln10": ln10, "Log2E": one / ln2, "Log10E": one / ln10, "Log2Of10": ln10 / ln2, "Log10Of2": ln2 / ln10, "Sqrt2": sqrt2, "Sqrt3": sqrt3, "Sqrt5": sqrt5, "InvSqrt2": one / sqrt2, "InvSqrt3": one / sqrt3, "SqrtPi": sqrt_pi, "InvSqrtPi": one / sqrt_pi, "TwoInvSqrtPi": 2 / sqrt_pi, "SqrtTau": sqrt_tau, "InvSqrtTau": one / sqrt_tau, "GoldenRatio": (one + sqrt5) / 2, } pairs = {name: split(Fraction(value)) for name, value in values.items()} for name, value in values.items(): high, low = pairs[name] assert high + low == high, f"Unnormalized constant: {name}" assert low != 0.0, f"Lost residual: {name}" assert abs(Fraction(high) + Fraction(low) - Fraction(value)) <= abs(Fraction(value)) / (1 << 105) return pairs if __name__ == "__main__": pairs = constants(160) assert pairs == constants(240), "Increase precision: binary64 constants did not stabilize" print("// Expected test components") for name, (high, low) in pairs.items(): print(f' [InlineData("{name}", {high!r}, {low!r})]') print("\n// Precomputed properties") for name, (high, low) in pairs.items(): print(f" public static DoubleDouble {name} => new({high!r}, {low!r});")