"""Checks on values read back from T647; no website writes.
Run with Sage: sage -python readback_checks.py
Needs generate.py, checks.py, T647-stored.json and numerical-evidence.json.
"""
import json
from pathlib import Path
import numberdb.sage as numberdb
from sage.rings.real_arb import RealBallField
import mpmath as mp
from checks import recorded_ball, frac, recursive_values
from generate import determinant
root=Path(__file__).resolve().parent
stored=json.loads((root/'T647-stored.json').read_text())
evidence=json.loads((root/'numerical-evidence.json').read_text())
R=RealBallField(800);expect=recursive_values();numbers=stored['Numbers']
assert list(map(int,numbers))==list(range(3,23))
rows=[]
for n in range(3,23):
    text=numbers[str(n)]
    if isinstance(text,dict):text=text['number']
    b=recorded_ball(text,R)
    assert R(determinant(n,180)) in b
    assert R(frac(mp.nstr(expect[n],170))) in b
    center=mp.mpf(text)
    for q in evidence['quadratures']:
        result=next(r for r in q['rows'] if r['n']==n)
        # Saved quadrature values have 60 or 90 significant digits.
        # Check their last-place intervals, not a fixed relative threshold.
        assert b in recorded_ball(result['determinant'],R), (n,q['working_digits'])
    rows.append({'n':n,'product_ball_contained':True,'independent_recursion_contained':True,
                 'quadrature_roundings_contain_stored_intervals_at_60_and_90_significant_digits':True})
# Test the recursions on the stored enclosures themselves, not on fresh rows.
balls={n:recorded_ball(numbers[str(n)],R) for n in range(3,23)}
identities=0
for k in range(2,11):
    A=R(k)*R(frac(str(k)) / 2).gamma()**2/R(2*(2*k+1))
    for j in range(1,k+1):
        q=R((2*j)**2)/R((2*j)**2-1)
        A*=q**R(frac(str(k))-frac('0.5'))
    assert (balls[2*k-1]*balls[2*k+1]-A*balls[2*k]**2).contains_zero()
    B=R(2*k+1)/R((k+1)*int(mp.factorial(k-1)))
    for j in range(2,k+2):
        B*=(R((2*j-1)**2)/R((2*j-1)**2-1))**k
    assert (balls[2*k]*balls[2*k+2]-B*balls[2*k+1]**2).contains_zero()
    identities+=2
assert R(determinant(3,180)*R(1+frac('1e-90'))) not in balls[3]
print(json.dumps({'table':'T647','skill_manifest':'../20261101T092014Z-build-skills/manifest.json',
 'rows':rows,'stored_recursion_identities':identities,'negative_control_passed':True},indent=2))
