#!/usr/bin/env python3
"""Precompute mpmath O3 vectors for engineering.uncertainty.tur.

ANSI/NCSL Z540.3 two-sided TUR = span / (2U). U is already expanded.
80 dps, round-to-nearest binary64. Not a pass/fail, not a guard band, and not U = k·u_c.

Re-run: python3 scripts/lib/cvp/oracles/generate-tur-o3.py
"""
from __future__ import annotations

import json
import math
import shutil
from pathlib import Path

import mpmath as mp

DPS = 80
GENERATOR_ID = "tur-mpmath-o3"
GENERATOR_VERSION = "1.0.0"
SEED = "20260923.tur-o3"


def f64(x: mp.mpf) -> float:
    return float(x)


def tur_row(span, U) -> dict:
    s = mp.mpf(str(span))
    u = mp.mpf(str(U))
    tur = s / (2 * u)
    return {
        "TUR_f64": f64(tur),
        "T_f64": f64(tur * 2 * u),
        "U_f64": f64(u),
        "TUR_decimal": mp.nstr(tur, 40, strip_zeros=False),
        "T_decimal": mp.nstr(s, 40, strip_zeros=False),
    }


def row(vid: str, inputs: dict, span, U, *, kind: str) -> dict:
    return {"id": vid, "kind": kind, "inputs": inputs, **tur_row(span, U)}


def vectors() -> list[dict]:
    return [
        row("o3-limits", {"U": 1, "lsl": 0, "usl": 5}, 5, 1, kind="limits"),
        row("o3-span", {"U": 0.5, "T": 4}, 4, 0.5, kind="span"),
        row("o3-tol", {"U": 0.5, "tol": 2}, 4, 0.5, kind="half"),
        row("o3-alias", {"U_exp": 1, "LSL": -1, "USL": 3}, 4, 1, kind="alias"),
        row("o3-span-alias", {"span": 8, "U": 2}, 8, 2, kind="alias"),
        row("o3-half", {"U": 0.25, "tol": 1}, 2, 0.25, kind="half"),
        row("o3-wide", {"U": 1, "lsl": -10, "usl": 10}, 20, 1, kind="limits"),
        row("o3-awkward", {"U": 0.15, "lsl": 1.1, "usl": 3.4}, "2.3", "0.15", kind="limits"),
    ]


def main() -> None:
    mp.mp.dps = DPS
    here = Path(__file__).resolve().parent
    table = {
        "family": "tur",
        "generator_id": GENERATOR_ID,
        "generator_version": GENERATOR_VERSION,
        "seed": SEED,
        "mpmath_dps": DPS,
        "precision_bits": int(DPS * math.log2(10)),
        "library": f"mpmath {mp.__version__}",
        "notes": "ANSI/NCSL Z540.3 two-sided TUR only. Independent of Node Math and the IUT. Pass/fail, guard band, and U=k·u_c are not tabulated.",
        "vectors": vectors(),
    }
    dest = here / "tur-o3-tables.json"
    dest.write_text(json.dumps(table, indent=2) + "\n", encoding="utf-8")
    public = here.parents[3] / "public/developers/cvp/reproduce"
    public.mkdir(parents=True, exist_ok=True)
    shutil.copy2(dest, public / "tur-o3-tables.json")
    shutil.copy2(Path(__file__), public / "generate-tur-o3.py")
    print(f"wrote {dest} ({len(table['vectors'])} vectors)")


if __name__ == "__main__":
    main()
