from pathlib import Path
import re, math
import mpmath as mp

HERE=Path(__file__).resolve().parent
PAPER=HERE/"CSM_RH_Paper_78_Universal_Zero_Pole_Preservation_in_Renormalized_Vaughan_Coefficient_v0.1_2026-09-09.md"
mp.mp.dps=70

def mobius(n):
    x=n; cnt=0; p=2
    while p*p<=x:
        if x%p==0:
            x//=p; cnt+=1
            if x%p==0:return 0
        p+=1
    if x>1:cnt+=1
    return -1 if cnt%2 else 1

def von_mangoldt(n):
    if n<2:return mp.mpf('0')
    x=n
    p=2
    while p*p<=x:
        if x%p==0:
            while x%p==0:
                x//=p
            return mp.log(p) if x==1 else mp.mpf('0')
        p+=1
    return mp.log(n)

def MU_s(U,s):
    return mp.fsum([mobius(d)/(mp.mpf(d)**s) for d in range(1,U+1)])

def LV_s(V,s):
    return mp.fsum([von_mangoldt(e)/(mp.mpf(e)**s) for e in range(1,V+1)])

def constants(U,V):
    MU=MU_s(U,1)
    JU=mp.fsum([mobius(d)*mp.log(d)/d for d in range(1,U+1)])
    LV=LV_s(V,1)
    return MU,JU,LV

def C(U,V,s):
    z=mp.zeta(s)
    zp=mp.diff(mp.zeta,s)
    return (-zp/z-LV_s(V,s))*(z*MU_s(U,s)-1)

def Q(U,V,s):
    MU,JU,LV=constants(U,V)
    z=mp.zeta(s)
    zp=mp.diff(mp.zeta,s)
    return -MU*zp-(MU*LV+JU+1)*z

def HH(U,V,s):
    return C(U,V,s)-Q(U,V,s)

def check_laurent_one():
    U,V=9,11
    MU,JU,LV=constants(U,V)
    target1=MU
    target2=-JU-1-MU*LV
    vals=[]
    for p in [8,10,12]:
        t=mp.mpf(10)**(-p)
        val=C(U,V,1+t)
        a=t*t*val
        b=t*(val-MU/(t*t))
        vals.append((p,float(abs(a-target1)),float(abs(b-target2))))
    assert vals[-1][0]==12
    assert vals[-1][1]<1e-9
    assert vals[-1][2]<1e-8
    return vals

def check_H_holomorphic_one():
    U,V=9,11
    vals=[]
    for p in [6,8,10]:
        t=mp.mpf(10)**(-p)
        vals.append(complex(HH(U,V,1+t)))
    # bounded sequence, no 1/t divergence
    assert max(abs(z) for z in vals)<1e6
    return vals[-2:]

def check_zero_residue():
    U,V=7,13
    rho=mp.zetazero(1)
    vals=[]
    for p in [5,7,9]:
        eps=mp.mpf(10)**(-p)
        r=eps*HH(U,V,rho+eps)
        vals.append(complex(r))
    assert abs(vals[-1]-1)<1e-6, vals[-1]
    return vals

def check_parameter_difference_zero_pole():
    rho=mp.zetazero(1)
    vals=[]
    for p in [5,7,9]:
        eps=mp.mpf(10)**(-p)
        r=eps*(HH(5,7,rho+eps)-HH(11,17,rho+eps))
        vals.append(complex(r))
    assert abs(vals[-1])<1e-6
    return vals

def check_split():
    U,V=7,13
    MU,JU,LV=constants(U,V)
    s=mp.mpf('1.37')+mp.mpf('2.2')*1j
    z=mp.zeta(s); zp=mp.diff(mp.zeta,s)
    E=zp*(MU-MU_s(U,s))+LV_s(V,s)*(1-z*MU_s(U,s))+(MU*LV+JU+1)*z
    lhs=HH(U,V,s)
    rhs=zp/z+E
    assert abs(lhs-rhs)<mp.mpf('1e-50')
    return float(abs(lhs-rhs))

def check_source():
    s=PAPER.read_text(encoding="utf-8")
    for pat in [r"(?<!\\)\\\(",r"(?<!\\)\\\)",r"(?<!\\)\\\[",r"(?<!\\)\\\]"]:
        assert re.search(pat,s) is None
    assert s.count("$$")%2==0
    tmp=re.sub(r"\$\$.*?\$\$","",s,flags=re.S)
    assert len(re.findall(r"(?<!\\)\$",tmp))%2==0
    return True

if __name__=="__main__":
    print("laurent_one",check_laurent_one())
    print("H_holomorphic_one",check_H_holomorphic_one())
    print("zero_residue",check_zero_residue())
    print("parameter_difference",check_parameter_difference_zero_pole())
    print("split_error",check_split())
    print("source_delimiters",check_source())
    print("PASS")
