back to table · edit · history · where entries came from · files · download
5503 bytes, as of the version from 2026-10-27 01:04 (current). Recorded here, not run.
"""Intrinsic argument families for Airy, Si/Ci, Fresnel, and Gaussian values.
Real Arb enclosures propagate root, pi and square-root uncertainty. Default
enumeration never samples a rational or decimal argument mesh. Parameter x
retains its meaning; exact integer arguments keep their existing identities.
"""
import argparse
import math
from fractions import Fraction
import numberdb
from flint import arb
from scorer import as_interval, precision, working_precision
KINDS = {'T192': 'si', 'T193': 'ci', 'T197': 'erf', 'T198': 'ai',
'T201': 'ai_prime', 'T202': 'bi', 'T203': 'bi_prime',
'T204': 'erfc', 'T207': 'fresnel_s', 'T208': 'fresnel_c'}
def sqrt_identity(radicand):
integer = math.isqrt(radicand)
return str(integer) if integer ** 2 == radicand else 'sqrt(%d)' % radicand
def argument_for(identity):
if identity.startswith('ai-prime-zero-'):
return arb.airy_ai_zero(int(identity[len('ai-prime-zero-'):]), derivative=1)
if identity.startswith('bi-prime-zero-'):
return arb.airy_bi_zero(int(identity[len('bi-prime-zero-'):]), derivative=1)
if identity.startswith('ai-zero-'):
return arb.airy_ai_zero(int(identity[len('ai-zero-'):]))
if identity.startswith('bi-zero-'):
return arb.airy_bi_zero(int(identity[len('bi-zero-'):]))
if identity.startswith('sqrt(') and identity.endswith(')'):
return arb(int(identity[5:-1])).sqrt()
if identity.endswith('*pi/2'):
return arb(int(identity[:-5])) * arb.pi() / 2
if identity.endswith('*pi'):
return arb(int(identity[:-3])) * arb.pi()
if identity.endswith('/sqrt(2)'):
return arb(int(identity[:-8])) / arb(2).sqrt()
return arb(str(Fraction(identity)))
def evaluate(kind, argument):
if kind == 'ai':
return argument.airy_ai()
if kind == 'ai_prime':
return argument.airy()[1]
if kind == 'bi':
return argument.airy_bi()
if kind == 'bi_prime':
return argument.airy()[3]
return getattr(argument, kind)()
def display(identity):
prefixes = {'ai-prime-zero-': r'a^{\prime}', 'bi-prime-zero-': r'b^{\prime}',
'ai-zero-': 'a', 'bi-zero-': 'b'}
for prefix, symbol in prefixes.items():
if identity.startswith(prefix):
return '$%s_{%d}$' % (symbol, int(identity[len(prefix):]))
if identity.startswith('sqrt('):
return r'$\sqrt{%d}$' % int(identity[5:-1])
if identity.endswith('*pi/2'):
return r'$%d\pi/2$' % int(identity[:-5])
if identity.endswith('*pi'):
return r'$%d\pi$' % int(identity[:-3])
if identity.endswith('/sqrt(2)'):
return r'$%d/\sqrt{2}$' % int(identity[:-8])
return '$%s$' % identity
class CuratedValues(numberdb.Generator):
parameters = ('x',)
type = 'R'
digits = 100
rigour = 'proven'
files = ('generate.py', 'curated_values.py', 'scorer.py', 'checks.py',
'selection.md', 'checks-evidence.json')
def enumerate(self, limit=None):
kind = KINDS[self.table]
limit = (6 if kind in ('erf', 'erfc') else 20) if limit is None else limit
if limit < 1:
raise ValueError('limit must be positive')
if kind != 'ci':
yield {'x': '0'}
prefixes = {'ai': 'ai-prime-zero-', 'ai_prime': 'ai-zero-',
'bi': 'bi-prime-zero-', 'bi_prime': 'bi-zero-'}
for index in range(1, limit + 1):
if kind in prefixes:
identity = prefixes[kind] + str(index)
elif kind == 'si':
identity = '%d*pi' % index
elif kind == 'ci':
identity = '%d*pi/2' % (2 * index - 1)
elif kind == 'fresnel_s':
identity = sqrt_identity(2 * index)
elif kind == 'fresnel_c':
identity = sqrt_identity(2 * index - 1)
else:
identity = '%d/sqrt(2)' % index
yield {'x': identity}
def value(self, params, digits):
identity = str(params['x'])
kind = KINDS[self.table]
with precision(working_precision(digits)):
argument = argument_for(identity)
value = evaluate(kind, argument)
if value.is_exact():
if not value == 0 and not value == 1:
raise ArithmeticError('unexpected exact value')
number = int(value == 1)
else:
if value.rel_accuracy_bits() < math.ceil((digits + 10) * math.log2(10)):
raise ArithmeticError('insufficient certified accuracy')
number = as_interval(value)
result = {'number': number}
if identity not in ('0', '1', '2', '3', '4', '5', '6'):
result['param-latex'] = display(identity)
if identity != '0':
result['comment'] = 'The argument is specified by CITE{argument-selection}.'
return result
def run(generator):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--fill', action='store_true')
parser.add_argument('--remove-unselected', action='store_true')
arguments = parser.parse_args()
if arguments.fill:
print(generator.publish(removing=arguments.remove_unselected,
message='Recompute intrinsic special-function arguments'))
else:
report = generator.verify(sample=None)
print(report)
raise SystemExit(0 if report.ok else 1)