generate.py

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

2970 bytes, as of the version from 2026-10-26 07:45. Recorded here, not run.

"""Jacobi theta₂ constants at singular nomes -- numberdb.org/T507.

Run with SageMath (install numberdb once with sage -pip install numberdb):
    sage -python generate.py                 # verify every stored entry
    sage -python generate.py --fill          # write entries, not publication
    sage -python checks.py                  # independent checks, no key needed
    sage -python checks.py --stored          # check stored draft, with API key

For authenticated operations set NUMBERDB_API_KEY, or pipe the key to stdin
with NUMBERDB_KEY_FROM_STDIN=1. No operation here publishes or offers a draft.
The parameter is a positive integer r, with tau=i*sqrt(r), q=exp(-pi*sqrt(r)).
The square root is positive, including when r has square factors. Store the
full theta-two constant, not a power or a period-normalized value. The initial
range 1..12 follows the common rectangular CM family.

Arb evaluates tau and the theta constant using ball arithmetic throughout.
The 96 guard bits give a 429-bit working precision for 100 significant digits.
The retained accuracy is measured by checks.py; each serialized decimal's
last-place interval must contain the entire computed ball.
"""
import os
import sys
import math
import numberdb.sage as numberdb
from sage.rings.complex_arb import ComplexBallField

WORKING_GUARD = 96

class ThetaTwoCM(numberdb.Generator):
    table = 'T507'
    parameters = ('r',)
    type = 'R'
    digits = 100
    rigour = 'proven'
    files = ('generate.py', 'checks.py', 'check.py', 'evidence.json')

    def enumerate(self, limit=12):
        for r in range(1, limit + 1):
            yield {'r': r}

    def value(self, params, digits):
        r = int(params['r'])
        if r < 1:
            raise ValueError('r must be a positive integer')
        C = ComplexBallField(numberdb.bits(digits, losing=WORKING_GUARD))
        tau = C.gen(0) * C(r).sqrt()
        z = C(0).jacobi_theta(tau)[1]
        assert all(math.isfinite(float(t)) for part in (z.real(), z.imag())
                   for t in (part.mid(), part.rad()))
        assert z.imag().contains_zero()
        x = z.real()
        assert x > 0 and x.accuracy() >= numberdb.bits(digits)
        if r == 1:
            return {'number': x,
                    'comment': r'The square lattice point $\tau_1=i$. Here $\theta_2(0,e^{-\pi})=\theta_4(0,e^{-\pi})$; its Gamma expression is CITE{formula-square}.',
                    'equals': 'HREF{Jacobi_theta₄_constants_at_singular_nomes#1}'}
        return x

if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        numberdb.configure(api_key=sys.stdin.read().strip())
    generator = ThetaTwoCM()
    if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        print(generator.publish(message='Compute theta-two CM constants in ball arithmetic'))
    else:
        report = generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)