repair-checks.py

back to table · edit · history · where entries came from · files · download

2790 bytes, as of the version from 2026-10-26 04:07 (current). Recorded here, not run.

"""Repair checks for Jacobi theta3 singular-nome constants -- numberdb.org/T504.

Run with SageMath beside the table's generate.py, checks.py and check.py:
    sage -python repair-checks.py
Set NUMBERDB_API_KEY to read the draft, or pipe the key on stdin and set
NUMBERDB_KEY_FROM_STDIN=1. This script performs no writes.

The existing generator and bounded Arb checks are rerun on every stored row.
Additional independent mpmath quadrature checks the integral being moved to
Formulas. The eta product is checked in both nome conventions, against the
theta identity, with the product remainder bounded by Q**101/(1-Q).
These additional fixed-precision comparisons are agreement checks, not a new
proof of the table's precision. The existing Arb checks supply that proof.
"""
import json
import os
import sys

if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
    os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()

import numberdb.sage as numberdb
import mpmath as mp
from checks import main as existing_checks


def additional_checks():
    mp.mp.dps = 160
    tolerance = mp.mpf('1e-145')
    assert abs(mp.quad(lambda t: mp.mpf(1), [0, mp.pi/2])-mp.pi/2) < tolerance
    assert abs(mp.gamma(mp.mpf(1)/2)**2-mp.pi) < tolerance
    assert abs(mp.ellipk(mp.mpf(1)/2)-mp.ellipk(mp.mpf(1)/4)) > mp.mpf('0.1')
    evidence = []
    for r in range(1, 13):
        q = mp.exp(-mp.pi*mp.sqrt(r))
        Q = mp.exp(-2*mp.pi*mp.sqrt(r))
        t2, t3, t4 = [mp.jtheta(j, 0, q) for j in (2, 3, 4)]
        m = (t2/t3)**4
        integral = mp.quad(lambda t: 1/mp.sqrt(1-m*mp.sin(t)**2), [0, mp.pi/2])
        eta_q = q**(mp.mpf(1)/12)*mp.fprod(1-q**(2*n) for n in range(1, 101))
        eta_Q = Q**(mp.mpf(1)/24)*mp.fprod(1-Q**n for n in range(1, 101))
        tail = Q**101/(1-Q)
        residuals = {
            'integral_vs_ellipk': abs(integral-mp.ellipk(m)),
            'integral_vs_theta': abs(integral-mp.pi*t3**2/2),
            'eta_nome_conventions': abs(eta_q-eta_Q),
            'eta_vs_theta_identity': abs(2*eta_q**3-t2*t3*t4),
            'quartic': abs(t3**4-t2**4-t4**4),
        }
        assert all(mp.isfinite(x) and x < tolerance for x in residuals.values())
        assert tail < mp.mpf('1e-270')
        assert eta_q > 0
        evidence.append({'r': r, 'residuals': {k: mp.nstr(v, 12) for k,v in residuals.items()},
                         'eta_relative_remainder_bound': mp.nstr(tail, 12)})
    return {'mpmath': mp.__version__, 'decimal_precision': 160,
            'tolerance': str(tolerance), 'controls_passed': True,
            'all_passed': True, 'evidence': evidence}


if __name__ == '__main__':
    print(json.dumps({'existing_bounded_checks': existing_checks(stored=True),
                      'additional_checks': additional_checks()}, indent=2))