from pathlib import Path
import re, math, random

HERE=Path(__file__).resolve().parent
PAPER=HERE/"CSM_RH_Paper_77_Exact_Renormalized_Vaughan_Extraction_for_Signed_Root_Sequence_v0.1_2026-09-09.md"

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 Lambda(n):
    x=n
    p=2
    while p*p<=x:
        if x%p==0:
            q=p
            while x%p==0:
                x//=p
            if x==1:
                return math.log(p)
            return 0.0
        p+=1
    return math.log(n) if n>=2 else 0.0

def divisors(n):
    out=[]
    for d in range(1,int(math.sqrt(n))+1):
        if n%d==0:
            out.append(d)
            if d*d!=n:
                out.append(n//d)
    return out

def bU(k,U):
    return sum(mobius(d) for d in divisors(k) if d<=U)

def aUV(k,U,V):
    s=0.0
    for d in divisors(k):
        e=k//d
        if d<=U and e<=V:
            s += mobius(d)*Lambda(e)
    return s

def check_vaughan_coeff():
    for U,V in [(3,4),(5,7),(7,11)]:
        for n in range(V+1,160):
            t1=sum(mobius(d)*math.log(n/d) for d in divisors(n) if d<=U)
            t2=sum(aUV(k,U,V) for k in divisors(n) if k<=U*V)
            t3=sum(Lambda(e)*bU(n//e,U) for e in divisors(n)
                   if e>V and n//e>U)
            assert abs((t1-t2-t3)-Lambda(n))<1e-10,(U,V,n,t1,t2,t3,Lambda(n))
    return True

def check_a_bound():
    for U,V in [(5,7),(7,13)]:
        for k in range(2,U*V+1):
            assert abs(aUV(k,U,V))<=math.log(k)+1e-12
    return True

def check_renormalized_algebra():
    random.seed(77)
    N=120
    U,V=5,7
    # arbitrary signed test sequence on (N,2N)
    f={n: random.uniform(-2,2) for n in range(N+1,2*N)}
    F=sum(f.values())
    G=sum(val*math.log(n/N) for n,val in f.items())
    def Fd(d):
        return sum(val for n,val in f.items() if n%d==0)
    def Gd(d):
        return sum(val*math.log(n/N) for n,val in f.items() if n%d==0)
    r={d:Fd(d)-F/d for d in range(1,U*V+1)}
    s={d:Gd(d)-G/d for d in range(1,U+1)}
    MU=sum(mobius(d)/d for d in range(1,U+1))
    JU=sum(mobius(d)*math.log(d)/d for d in range(1,U+1))
    LV=sum(Lambda(e)/e for e in range(1,V+1))
    M=F*(MU*(math.log(N)-LV)-JU-1)+G*MU
    EI=sum(mobius(d)*((math.log(N)-math.log(d))*r[d]+s[d]) for d in range(1,U+1))
    EI-=sum(aUV(k,U,V)*r[k] for k in range(1,U*V+1))
    T3=0.0
    for n,val in f.items():
        for e in divisors(n):
            k=n//e
            if e>V and k>U:
                T3 += Lambda(e)*bU(k,U)*val
    R=sum(Lambda(n)*val for n,val in f.items())-F
    rhs=M-T3+EI
    assert abs(R-rhs)<1e-9,(R,rhs,M,T3,EI)
    return R,rhs

def check_exponent_gate():
    random.seed(770)
    for _ in range(10000):
        k=random.uniform(0.02,0.8)
        tau=random.uniform(0.001,0.9*(1-k))
        eta=random.uniform(0.001,0.05)
        room=1-tau-k-eta
        if room<=0:
            continue
        u=room*0.3
        v=room*0.4
        saving=1-tau-u-v
        assert saving>k+eta
    return True

def check_main_exponent():
    for k in [0.1,0.3,0.8]:
        d=k/2
        for u in [0.1,0.4,0.9]:
            assert d*(1+u)<2*d
    return True

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("vaughan_coeff",check_vaughan_coeff())
    print("a_bound",check_a_bound())
    print("renormalized_algebra",check_renormalized_algebra())
    print("exponent_gate",check_exponent_gate())
    print("main_exponent",check_main_exponent())
    print("source_delimiters",check_source())
    print("PASS")
