"""Analytic Hessian periods used by T651, with arbitrary-precision arguments.

The exterior constant-term series is used for |t|>27; for -27<=t<=-1,
the same 4F3 is continued along the negative real axis. For 0<t<27 the
corrected Samart v3 pair of 3F2 series is used, or its integrated 2F1
derivative near the singularity. No quadrature-root code is shared with
integral_checks.py. These are floating approximations, not enclosures.
"""
from functools import lru_cache
import re
import mpmath as mp

def rational(s):
    a,sep,b=s.partition('/')
    return mp.mpf(a)/mp.mpf(b) if sep else mp.mpf(a)

def argument(key):
    if 'sqrt' not in key:return rational(key)
    a,b,d=re.fullmatch(r'(-?\d+(?:/\d+)?)([+-]\d+(?:/\d+)?)\*sqrt\((\d+)\)',key).groups()
    return rational(a)+rational(b)*mp.sqrt(int(d))

@lru_cache(maxsize=None)
def nu(key,working):
    with mp.workdps(working):
        t=argument(key); q=mp.mpf(1)/3
        if -1<t<27:
            assert t>0, 'This evaluator covers the selected positive interior arguments.'
            k=mp.root(t,3)
            A=mp.gamma(q)**3; B=mp.gamma(2*q)**3
            if t<22:
                value=-(A*k*mp.hyper([q,q,q],[2*q,4*q],t/27)+B*k*k*mp.hyper([2*q,2*q,2*q],[4*q,5*q],t/27)/2)/(4*mp.pi**2)
            else:
                def f(u):
                    z=u**3/27
                    return -(A*mp.hyp2f1(q,q,2*q,z)+B*u*mp.hyp2f1(2*q,2*q,4*q,z))/(4*mp.pi**2)
                points=[mp.mpf(0)]; n=1
                while 3-mp.power(2,-n)<k:
                    points.append(3-mp.power(2,-n)); n+=1
                points.append(k)
                value=mp.quad(f,points,method='gauss-legendre',maxdegree=8)
        elif abs(t)>27:
            term=2/t;total=term;n=1;ratio=27/abs(t)
            target=mp.power(10,-working+8)
            while True:
                term*=mp.mpf(3*n*(3*n+1)*(3*n+2))/((n+1)**3*t)
                total+=term;n+=1
                if abs(term)*ratio/(1-ratio)<target:break
                if n>1000000:raise ArithmeticError('Series did not converge')
            value=mp.log(abs(t))/3-total
        else:
            value=mp.log(abs(t))/3-mp.re(2/t*mp.hyper([4*q,5*q,1,1],[2,2,2],27/t))
        assert mp.isfinite(value)
        return mp.nstr(value,working-5)
