"""Independent 1024-bit genus-character CM check for T673.

Run `sage -python cm_checks.py`, or `sage -python cm_checks.py --stored`.
The generator uses eta products; this checker instead enumerates reduced
binary quadratic forms and evaluates Arb's modular j function. It checks
all positive fundamental discriminant grades in the stored range, not just
the overlap with T671. HR equations (2.10)--(2.14), with stabilizer weights
and zero genus character on forms sharing a common divisor with D.
"""
import numberdb.sage as numberdb
from sage.rings.complex_arb import ComplexBallField
from sage.rings.real_arb import RealBallField
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from math import gcd,isqrt
import json
import os
import sys
from generate import coefficients,MAX_GRADE
from checks import table_values

BITS=1024
C=ComplexBallField(BITS)
R=RealBallField(BITS)
LIMIT=R(10)**(-110)


def validate(ball,exact):
    assert ball.real().is_finite() and ball.imag().is_finite()
    assert ball.real().rad_as_ball()<LIMIT and ball.imag().rad_as_ball()<LIMIT
    assert ball.imag().contains_zero()
    assert exact in ball.real()


def fundamental(d):
    return (d%4==1 and ZZ(d).is_squarefree()) or (d%4==0 and (d//4)%4 in (2,3) and ZZ(d//4).is_squarefree())


def trace(d):
    disc=3*d
    total=C(0);forms=0
    for a in range(1,isqrt(disc//3)+1):
        for b in range(-a,a+1):
            c,rem=divmod(b*b+disc,4*a)
            if rem or c<a or ((abs(b)==a or a==c) and b<0):continue
            if gcd(gcd(gcd(a,b),c),d)>1:continue
            represented=None
            # Any coprime represented integer defines the same genus character.
            for radius in range(1,d+1):
                for x,y in [(radius,1),(1,radius),(radius,0),(0,radius)]:
                    v=a*x*x+b*x*y+c*y*y
                    if gcd(v,d)==1:represented=v;break
                if represented is not None:break
            assert represented is not None
            chi=ZZ(d).kronecker(represented)
            w=3 if a==b==c else (2 if b==0 and a==c else 1)
            tau=(C(-b)+C(0,1)*C(disc).sqrt())/C(2*a)
            j=tau.modular_j()
            assert j.real().is_finite() and j.imag().is_finite()
            total += C(chi)*(j-744)/C(w)
            forms+=1
    return total/C(d).sqrt(),forms


def run(values):
    validate(C(0,1).modular_j(),1728)
    validate(((C(-1)+C(0,1)*C(3).sqrt())/2).modular_j(),0)
    control,_=trace(5);validate(control,-85995)
    for bad,known in [(control,85995),(C(R('nan')),0),(C(R(0).add_error(R(1))),0)]:
        try:validate(bad,known)
        except AssertionError:pass
        else:raise AssertionError('A wrong or uninformative CM enclosure was accepted')
    rows=[];worst=R(0)
    for d in range(2,MAX_GRADE+1):
        if not fundamental(d):continue
        value,forms=trace(d)
        validate(value,QQ(values[d])/2)
        worst=max(worst,value.real().rad_as_ball(),value.imag().rad_as_ball())
        rows.append({'D':d,'form_count':forms,'coefficient':str(values[d]),'radius':str(value.real().rad_as_ball())})
    return {'table':'T673','method':'independent reduced forms and Arb modular_j','bits':BITS,
        'fundamental_discriminant_comparisons':len(rows),'max_radius':str(worst),'required_radius':'<1e-110',
        'rows':rows,'skill_manifest':'agents/runs/20261102T085118Z-build-skills/manifest.json'}


if __name__=='__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN')=='1':
        token=sys.stdin.read().strip()
        if '=' in token and token.split('=',1)[0].isupper():token=token.split('=',1)[1].strip().strip('\'"')
        numberdb.configure(api_key=token)
    if '--stored' in sys.argv:
        values=table_values(numberdb.table('T673'))['1A'];mode='stored'
    else:values=coefficients()['1A'];mode='computed'
    result=run(values);result['mode']=mode;print(json.dumps(result,indent=2))
