import random
from fractions import Fraction
from mpmath import mp, mpf, exp, log, sin, cos, sqrt, nint
mp.dps = 120
SEED = 20260924
ONE = 1 << 64
PROFILES = [
*[(f"REALTIME_F{F}", 32, F) for F in range(2, 31)],
("COMPACT", 64, 32),
("EMBEDDED", 128, 64),
("BALANCED", 256, 128),
("SCIENTIFIC", 512, 256),
]
WIDE_FRAC_BITS = [0, 1, 10, 16, 20, 32, 52, 64, 100, 126, 127]
def q64(v):
return int(nint(v * ONE))
def nearest_up(v, f):
t = v * (1 << f) + Fraction(1, 2)
return t.numerator // t.denominator
def decimal_of(v):
sign = "-" if v < 0 else ""
v = abs(v)
digits = 0
while (v * 10 ** digits).denominator != 1:
digits += 1
n = int(v * 10 ** digits)
if digits == 0:
return f"{sign}{n}"
s = str(n).rjust(digits + 1, "0")
return f"{sign}{s[:-digits]}.{s[-digits:]}"
def literal_value(s):
s = s.strip()
mant, _, e = s.replace("E", "e").partition("e")
neg = mant.startswith("-")
mant = mant.lstrip("+-")
ip, _, fp = mant.partition(".")
v = Fraction(int((ip or "0") + (fp or "")), 10 ** len(fp))
v *= Fraction(10) ** int(e or "0")
return -v if neg else v
def random_literal(rng, max_int_digits):
int_len = rng.randint(0, max_int_digits)
frac_len = rng.randint(0, 45)
ip = "".join(rng.choice("0123456789") for _ in range(int_len))
fp = "".join(rng.choice("0123456789") for _ in range(frac_len))
if not ip and not fp:
ip = "0"
form = rng.randint(0, 5)
if form == 0 and ip:
body = f"{ip}."
elif form == 1 and fp:
body = f".{fp}"
else:
body = f"{ip or '0'}.{fp}" if fp else (ip or "0")
if rng.random() < 0.3:
e = rng.randint(-40, 3)
body += rng.choice("eE") + (str(e) if e < 0 else rng.choice(["", "+"]) + str(e))
return rng.choice(["", "", "-", "+"]) + body
def literal_cases(rng, width, f, count):
lo, hi = -(1 << (width - 1)), (1 << (width - 1)) - 1
int_digits = max(1, (width - 1 - f) * 30103 // 100000)
lits = [random_literal(rng, int_digits) for _ in range(count)]
half = Fraction(1, 1 << (f + 1))
ulp = Fraction(1, 1 << f)
tiny = Fraction(1, 10 ** (f + 10))
for _ in range(12):
k = rng.randrange(0, 1 << min(width - 2, 40))
tie = k * ulp + half
for v in (tie, -tie, tie + tiny, tie - tiny, -tie - tiny, -tie + tiny):
lits.append(decimal_of(v) if (v * 10 ** (f + 11)).denominator == 1 else None)
lits.append(decimal_of(tie) + "000")
d = decimal_of(tie)
if "." in d:
ip, fp = d.split(".")
lits.append(f"{ip}{fp}e-{len(fp)}")
top = Fraction(hi, 1 << f)
bottom = Fraction(lo, 1 << f)
for v in (top, top + half, top + half - tiny, bottom, bottom - half, bottom - half - tiny):
lits.append(decimal_of(v) if (v * 10 ** (f + 11)).denominator == 1 else None)
lits += ["0", "-0", "0.0", "-0.000", "00012.5000", " 1.5 ", "1e400", "-1e400", "1e-400", "-1e-400",
"1e-06", "1e-05", "1E6", "6.283185307179586476925286766559"]
out = []
for s in lits:
if s is None:
continue
r = nearest_up(literal_value(s), f)
out.append((s, r if lo <= r <= hi else None))
return out
def rust_i128(v):
return f"{v}" if v >= 0 else f"-{-v}"
def main():
rng = random.Random(SEED)
lines = [
"// Generated by scripts/generate_wide_refs.py - do not edit.",
"// mpmath 120 significant digits (transcendentals); exact fractions.Fraction",
"// (literals: nearest, ties toward +infinity).",
"",
]
xs = [rng.randrange(-40 * ONE, 41 * ONE) for _ in range(600)]
xs += [rng.randrange(-ONE, ONE) >> rng.randint(0, 60) for _ in range(150)]
xs += [k * ONE + d for k in range(-40, 41, 7) for d in (-1, 1, 1 << 40)]
xs = [x for x in xs if -40 * ONE <= x < 41 * ONE]
lines.append("/// (x, nearest Q64.64 of e^x), x in [-40, 41).")
lines.append("pub const EXP: &[(i128, i128)] = &[")
for x in xs:
lines.append(f" ({rust_i128(x)}, {rust_i128(q64(exp(mpf(x) / ONE)))}),")
lines.append("];\n")
xs = []
for _ in range(700):
bits = rng.randint(1, 127)
xs.append(rng.randrange(1 << (bits - 1), (1 << bits) if bits < 127 else (1 << 127) - 1))
xs += [1, 2, ONE - 1, ONE + 1, (1 << 127) - 1]
lines.append("/// (x, nearest Q64.64 of ln x), x > 0.")
lines.append("pub const LN: &[(i128, i128)] = &[")
for x in xs:
lines.append(f" ({rust_i128(x)}, {rust_i128(q64(log(mpf(x) / ONE)))}),")
lines.append("];\n")
bands = [
("SINCOS_0_2PI", 0, q64(2 * mp.pi)),
("SINCOS_2PI_2P12", q64(2 * mp.pi), 1 << (64 + 12)),
("SINCOS_2P12_2P20", 1 << (64 + 12), 1 << (64 + 20)),
("SINCOS_2P20_2P32", 1 << (64 + 20), 1 << (64 + 32)),
("SINCOS_2P32_2P62", 1 << (64 + 32), 1 << (64 + 62)),
]
for name, lo, hi in bands:
lines.append(f"/// (x, nearest Q64.64 of sin x, of cos x), |x| in [{name}).")
lines.append(f"pub const {name}: &[(i128, i128, i128)] = &[")
for _ in range(300):
x = rng.randrange(lo, hi) * rng.choice([1, -1])
v = mpf(x) / ONE
lines.append(f" ({rust_i128(x)}, {rust_i128(q64(sin(v)))}, {rust_i128(q64(cos(v)))}),")
lines.append("];\n")
lines.append("/// (literal, frac_bits, i128 raw or None = TierOverflow).")
lines.append("pub const LITERALS_WIDE: &[(&str, u32, Option<i128>)] = &[")
for f in WIDE_FRAC_BITS:
for s, r in literal_cases(rng, 128, f, 250):
lines.append(f" ({s!r}, {f}, {'None' if r is None else f'Some({rust_i128(r)})'}),".replace("'", '"'))
lines.append("];\n")
lines.append("/// (literal, raw as (negative, hex magnitude), or None = TierOverflow).")
lines.append("pub type Storage = (&'static str, Option<(bool, &'static str)>);\n")
for name, width, f in PROFILES:
lines.append(f"pub const {name}_LITERALS: &[Storage] = &[")
for s, r in literal_cases(rng, width, f, 250):
ref = "None" if r is None else f'Some(({"true" if r < 0 else "false"}, "{abs(r):x}"))'
lines.append(f' ("{s}", {ref}),')
lines.append("];\n")
eps_q64 = {e: nearest_up(Fraction(e), 64) for e in ("1e-5", "1e-6")}
lines.append("/// Q64.64 epsilons (nearest, ties toward +inf).")
for e, v in eps_q64.items():
lines.append(f"pub const EPS_{e.replace('-', '_M').upper().replace('.', '_')}_Q64: i128 = {v};")
lines.append("")
lines.append("/// (epsilon literal, exact 1/sqrt(eps_c) at 100 digits) per profile, eps_c the")
lines.append("/// Q64.64 epsilon rounded to the compute tier (2F bits, nearest ties toward +inf).")
for name, width, f in PROFILES:
cf = 2 * f
lines.append(f"pub const {name}_RMS_ZERO: &[(&str, &str)] = &[")
for e, v in eps_q64.items():
if cf < 64:
t = Fraction(v, 1 << (64 - cf)) + Fraction(1, 2)
eps_c = Fraction(t.numerator // t.denominator, 1 << cf)
else:
eps_c = Fraction(v, 1 << 64)
if eps_c == 0:
lines.append(f' ("{e}", "DivisionByZero"),')
continue
r = 1 / sqrt(mpf(eps_c.numerator) / eps_c.denominator)
lines.append(f' ("{e}", "{mp.nstr(r, 100, strip_zeros=False)}"),')
lines.append("];\n")
arms = " ".join(f"{F} => REALTIME_F{F}_LITERALS," for F in range(2, 31))
lines.append("/// The realtime literal table for the build's split.")
lines.append(f"pub const REALTIME_LITERALS: &[Storage] = match g_math::fixed_point::frac_config::FRAC_BITS {{ {arms} _ => &[] }};")
arms = " ".join(f"{F} => REALTIME_F{F}_RMS_ZERO," for F in range(2, 31))
lines.append("/// The realtime rms table for the build's split.")
lines.append(f"pub const REALTIME_RMS_ZERO: &[(&str, &str)] = match g_math::fixed_point::frac_config::FRAC_BITS {{ {arms} _ => &[] }};")
lines.append("")
with open("tests/data/wide_q64_refs.rs", "w") as fh:
fh.write("\n".join(lines))
if __name__ == "__main__":
main()