generate.py

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

2686 bytes, as of the version from 2026-10-25 15:06. Recorded here, not run.

"""Values of the Kelvin function bei_nu(x) -- numberdb.org/T491.

Run with SageMath (or a compatible passagemath installation):
    sage -pip install numberdb
    sage -python generate.py                 # verify every stored entry
    sage -python generate.py --fill          # fill the existing draft
    sage -python checks.py                   # independent local checks
    sage -python checks.py --stored          # repeat on database values

Reading this draft and filling it require NUMBERDB_API_KEY. --fill only sends
entries and source files; it never publishes or offers the table for review.
The campaign wrapper may instead supply the key through standard input with
NUMBERDB_KEY_FROM_STDIN=1 and select filling with NUMBERDB_PUBLISH=1.

Convention: DLMF 10.61.1, Im J_nu(x exp(3*pi*i/4)), principal branch.
Orders 0, 1, 2 and positive reduced rational x <= 20 of denominator <= 4.
The rotation (-1+i)/sqrt(2), rational arguments and Bessel evaluation all use
complex balls. The 64-bit guard is measured over the entire rectangle;
checks.py bounds every relative radius by 1e-110 and confirms containment
in each written 100-significant-digit interval.
"""
import os
import sys
import numberdb.sage as numberdb
from sage.rings.complex_arb import ComplexBallField
from sage.rings.rational_field import QQ

WORKING_GUARD = 64


class KelvinBei(numberdb.Generator):
    table = 'T491'
    parameters = ('nu', 'x')
    type = 'R'
    digits = 100
    rigour = 'proven'
    files = ('generate.py', 'checks.py', 'check.py', 'document.json')

    def enumerate(self):
        arguments = sorted({QQ(a) / QQ(b)
                            for b in range(1, 5)
                            for a in range(1, 20*b + 1)})
        for nu in range(3):
            for x in arguments:
                yield {'nu': str(nu), 'x': str(x)}

    def value(self, params, digits):
        C = ComplexBallField(numberdb.bits(digits, losing=WORKING_GUARD))
        nu, x = QQ(params['nu']), QQ(params['x'])
        z = C(x) * C(-1, 1) / C(2).sqrt()
        result = z.bessel_J(C(nu)).imag()
        if not result.is_finite():
            raise ArithmeticError('nonfinite Bessel enclosure')
        return result


if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()
    generator = KelvinBei()
    if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        print(generator.publish(message='Fill Kelvin bei values with certified balls and independent checks.'))
    else:
        report = generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)