#!/usr/bin/env python3 """Every rate write is a receipt. Stdlib only.""" from __future__ import annotations from fractions import Fraction as F def as_exact(x): if isinstance(x, bool): raise TypeError("theta bool") if isinstance(x, int): return F(x) if isinstance(x, F): return F(x) raise TypeError("theta not Q: %s" % type(x).__name__) def isolate(v, seed): v, seed = as_exact(v), as_exact(seed) if seed == 0: raise ValueError("theta seed 0") return (v, seed) def mix(a, b): (v, r), (w, s) = a, b return (v * w, r * w + v * s) def rate(top, bot): if bot[1] == 0: raise ValueError("theta dead isolator") return top[1] / bot[1] def receipt(fn, v, seeds=(1, 2, F(1, 2), -1)): """One row per seed, plus gauge (all rates equal or split).""" if not seeds: raise ValueError("theta empty seeds") rows = [] for s in seeds: x = isolate(v, s) y = fn(x) r = rate(y, x) rows.append({"seed": s, "value": y[0], "channel": y[1], "rate": r}) rates = [row["rate"] for row in rows] gauge = all(r == rates[0] for r in rates) return {"at": as_exact(v), "gauge": gauge, "rate": rates[0] if gauge else None, "rows": rows, "theta": not gauge} if __name__ == "__main__": sq = lambda x: mix(x, x) rec = receipt(sq, 3) print("gauge", rec["gauge"], "rate", rec["rate"]) for row in rec["rows"]: print(row) try: receipt(sq, 3, seeds=()) except ValueError as e: print(e)