generate.py

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

3078 bytes, as of the version from 2026-10-27 01:18 (current). Recorded here, not run.

"""Bessel Rayleigh sums -- numberdb.org/T533.

Run with SageMath and the numberdb package:
    sage -pip install numberdb
    sage -python generate.py                 # verify every stored entry
    sage -python generate.py --values        # print exact values without a key
    sage -python checks.py                   # independent checks, no writes

For the private draft, set NUMBERDB_API_KEY to a key allowed to read it.
This module never offers or publishes a table.

The normalized entire function F_nu(t) has coefficients
    c_0 = 1, c_m = -c_(m-1)/(4*m*(nu+m)).
Its product is product_k(1-t/j_(nu,k)^2). Thus -F'_nu/F_nu has
coefficient sigma_n(nu) at t^(n-1). Exact coefficient comparison gives
    sigma_n = -n*c_n - sum_(i=1)^(n-1) c_i*sigma_(n-i).
All arithmetic is in QQ. No root truncation or floating-point approximation
enters the generated values. DLMF 10.2.2, 10.21.15 and 10.21.55 fix the
normalization. argument-selection.md explains both parameters and the bounds.
"""

import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from functools import lru_cache
import sys


@lru_cache(maxsize=None)
def rayleigh_prefix(nu, maximum):
    """Exact logarithmic-derivative coefficients through the given moment."""
    nu = QQ(nu)
    if nu < 0 or maximum < 1:
        raise ValueError('Require nonnegative order and positive moment order')
    coefficients = [QQ(1)]
    moments = [QQ(0)]
    for n in range(1, maximum + 1):
        coefficients.append(-coefficients[-1] / (QQ(4) * QQ(n) * (nu + n)))
        moments.append(-QQ(n) * coefficients[n]
                       - sum((coefficients[i] * moments[n-i]
                              for i in range(1, n)), QQ(0)))
    return tuple(moments[1:])


class BesselRayleighSums(numberdb.Generator):
    table = 'T533'
    parameters = ('nu', 'n')
    type = 'Q'
    rigour = 'exact'
    digits = 100  # ignored for exact rational output
    files = ('generate.py', 'argument-selection.md', 'checks.py', 'check.py')

    def enumerate(self, angular_max=3, moment_max=12):
        """Disk orders ell and ball orders ell+1/2, sorted by nu then n."""
        if angular_max < 0 or moment_max < 1:
            raise ValueError('Invalid prefix bound')
        orders = {QQ(ell) + QQ(d - 2) / QQ(2)
                  for d in (2, 3) for ell in range(angular_max + 1)}
        for nu in sorted(orders):
            for n in range(1, moment_max + 1):
                yield {'nu': str(nu), 'n': str(n)}

    def value(self, params, digits):
        numerator, separator, denominator = str(params['nu']).partition('/')
        nu = QQ(int(numerator)) / QQ(int(denominator) if separator else 1)
        n = int(params['n'])
        return rayleigh_prefix(nu, n)[n - 1]


if __name__ == '__main__':
    generator = BesselRayleighSums()
    if '--values' in sys.argv:
        for params in generator.enumerate():
            print(params['nu'], params['n'], generator.value(params, 100))
    else:
        report = generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)