from __future__ import annotations
import math
import random
from pathlib import Path
import scipy.special
REPO_ROOT = Path(__file__).resolve().parent.parent
OUT_PATH = REPO_ROOT / "tests" / "embedded" / "native" / "statistics_oracle_data.rs"
def stdtr_grid() -> list[tuple[int, float, float]]:
rng = random.Random(0)
rows: list[tuple[int, float, float]] = []
explicit_df = [1, 2, 3, 4, 10, 100]
explicit_t = [-100.0, -1.0, -0.5, 0.0, 0.5, 1.0, 100.0]
for df in explicit_df:
for t in explicit_t:
rows.append((df, t, float(scipy.special.stdtr(df, t))))
for _ in range(200):
df = rng.randint(1, 100)
exp = rng.uniform(-3, 6)
t = math.copysign(10**exp, rng.random() - 0.5)
rows.append((df, t, float(scipy.special.stdtr(df, t))))
return rows
def stdtrit_strict_grid() -> list[tuple[int, float, float]]:
rng = random.Random(1)
rows: list[tuple[int, float, float]] = []
for df in (1, 2):
for p in (0.0001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.9999):
rows.append((df, p, float(scipy.special.stdtrit(df, p))))
for _ in range(50):
log_p = rng.uniform(-12, -1e-6)
p = 10**log_p
if rng.random() < 0.5:
p = 1 - p
rows.append((df, p, float(scipy.special.stdtrit(df, p))))
return rows
def stdtrit_lax_grid() -> list[tuple[int, float, float]]:
rng = random.Random(2)
rows: list[tuple[int, float, float]] = []
explicit_df = [3, 4, 5, 10, 100]
for df in explicit_df:
for p in (0.001, 0.01, 0.1, 0.5, 0.9, 0.99, 0.999):
rows.append((df, p, float(scipy.special.stdtrit(df, p))))
for _ in range(100):
df = rng.randint(3, 100)
p = rng.uniform(1e-6, 1 - 1e-6)
rows.append((df, p, float(scipy.special.stdtrit(df, p))))
return rows
def fmt_float(x: float) -> str:
if math.isnan(x):
return "f64::NAN"
if math.isinf(x):
return "f64::INFINITY" if x > 0 else "f64::NEG_INFINITY"
return repr(x)
def main() -> None:
stdtr_rows = stdtr_grid()
stdtrit_strict_rows = stdtrit_strict_grid()
stdtrit_lax_rows = stdtrit_lax_grid()
out_lines: list[str] = []
out_lines.append(
"// Auto-generated by scripts/generate_statistics_oracle.py.\n"
"// Do not edit by hand; regenerate against scipy if the oracle\n"
"// needs refreshing. Each row is (df, x, expected_scipy_result).\n"
f"// Source: scipy {scipy.__version__}.\n"
)
out_lines.append(
f"pub const STDTR_CASES: &[(i32, f64, f64)] = &[\n"
)
for df, t, expected in stdtr_rows:
out_lines.append(f" ({df}, {fmt_float(t)}, {fmt_float(expected)}),\n")
out_lines.append("];\n\n")
out_lines.append(
f"pub const STDTRIT_STRICT_CASES: &[(i32, f64, f64)] = &[\n"
)
for df, p, expected in stdtrit_strict_rows:
out_lines.append(f" ({df}, {fmt_float(p)}, {fmt_float(expected)}),\n")
out_lines.append("];\n\n")
out_lines.append(
f"pub const STDTRIT_LAX_CASES: &[(i32, f64, f64)] = &[\n"
)
for df, p, expected in stdtrit_lax_rows:
out_lines.append(f" ({df}, {fmt_float(p)}, {fmt_float(expected)}),\n")
out_lines.append("];\n")
OUT_PATH.write_text("".join(out_lines))
print(f"wrote {OUT_PATH} ({len(stdtr_rows)} stdtr, "
f"{len(stdtrit_strict_rows)} stdtrit-strict, "
f"{len(stdtrit_lax_rows)} stdtrit-lax rows)")
if __name__ == "__main__":
main()