from mpmath import mp, mpf, nint
import mpmath as M
mp.dps = 60
SPLITS = list(range(2, 31)) OUT = "tests/data/fasc_ulp_refs_q16.rs"
FUNCS = {
"exp": M.exp, "ln": M.log, "sqrt": M.sqrt, "sin": M.sin, "cos": M.cos,
"tan": M.tan, "atan": M.atan, "asin": M.asin, "acos": M.acos, "sinh": M.sinh,
"cosh": M.cosh, "tanh": M.tanh, "asinh": M.asinh, "acosh": M.acosh, "atanh": M.atanh,
}
INPUTS = [
("exp", ["0.5", "1.0", "-0.5", "2.0", "-1.0", "0.1"]),
("ln", ["0.5", "1.0", "2.0", "3.0", "0.1", "10.0"]),
("sqrt", ["0.25", "1.0", "2.0", "4.0", "9.0", "0.5"]),
("sin", ["0.0", "0.5", "1.0", "-1.0", "1.5", "3.0"]),
("cos", ["0.0", "0.5", "1.0", "-1.0", "1.5", "2.0"]),
("tan", ["0.0", "0.5", "1.0", "-0.5", "0.75", "-0.75"]),
("atan", ["0.0", "0.5", "1.0", "-1.0", "0.1", "100.0"]),
("asin", ["0.0", "0.5", "-0.5", "0.9", "-0.9", "0.1"]),
("acos", ["0.0", "0.5", "-0.5", "0.9", "-0.9", "0.1"]),
("sinh", ["0.0", "0.5", "1.0", "-1.0", "2.0", "-0.5"]),
("cosh", ["0.0", "0.5", "1.0", "-1.0", "2.0", "-0.5"]),
("tanh", ["0.0", "0.5", "1.0", "-1.0", "2.0", "-0.5"]),
("asinh", ["0.0", "0.5", "1.0", "-1.0", "2.0", "10.0"]),
("acosh", ["1.0", "1.5", "2.0", "3.0", "10.0", "1.1"]),
("atanh", ["0.0", "0.5", "-0.5", "0.9", "-0.9", "0.1"]),
]
def nearest(v):
return int(nint(v))
def table(rows, F):
lo, hi = -(1 << 31), (1 << 31) - 1
out = []
for s, f in rows:
x = mpf(s)
ir, er = nearest(x * 2**F), nearest(FUNCS[f](x) * 2**F)
if not (lo <= ir <= hi and lo <= er <= hi):
continue
if ir == 0 and x != 0:
continue
out.append((s, ir, er, f))
return out
def main():
rows = [(s, f) for f, inputs in INPUTS for s in inputs]
lines = [
"// GENERATED by scripts/generate_realtime_ulp_refs.py - do not edit.",
"// mpmath 60 digits. Per row: (input literal, nearest input raw, nearest raw of",
"// f at the EXACT decimal input, function), one table per realtime split.",
"",
]
for F in SPLITS:
name = "Q16_REFS" if F == 16 else f"Q{32 - F}_{F}_REFS"
lines.append(f"/// Realtime at GMATH_FRAC_BITS={F}.")
lines.append(f"pub const {name}: &[(&str, i32, i32, &str)] = &[")
for s, ir, er, f in table(rows, F):
lines.append(f' ("{s}", {ir}_i32, {er}_i32, "{f}"),')
lines.append("];")
lines.append("")
arms = " ".join(f"{F} => Q{32 - F}_{F}_REFS," for F in SPLITS if F != 16)
lines.append("/// The table for the build's split (every GMATH_FRAC_BITS the build accepts).")
lines.append("pub const REALTIME_REFS: &[(&str, i32, i32, &str)] =")
lines.append(f" match g_math::fixed_point::frac_config::FRAC_BITS {{ {arms} _ => Q16_REFS }};")
lines.append("/// The split `REALTIME_REFS` was generated for (equals FRAC_BITS for 2..=30).")
lines.append("pub const REALTIME_REFS_FRAC_BITS: u32 =")
lines.append(" match g_math::fixed_point::frac_config::FRAC_BITS { f @ 2..=30 => f, _ => 16 };")
open(OUT, "w").write("\n".join(lines) + "\n")
if __name__ == "__main__":
main()