back to table · edit · history · where entries came from · files · download
3694 bytes, as of the version from 2026-10-28 15:11 (current). Recorded here, not run.
"""Gram points of the Riemann zeta function -- numberdb.org/T583.
Run with SageMath:
sage -pip install numberdb
sage -python generate.py # verify all stored entries
sage -python generate.py --fill # fill the existing draft
The draft requires NUMBERDB_API_KEY to read or fill. For a key piped on stdin,
set NUMBERDB_KEY_FROM_STDIN=1. --fill writes entries, never publishes a table.
The finite prefix is -1 <= n <= 200. See argument-selection.md for its purpose
and certification.md for the global uniqueness proof and endpoint certificate.
The working precision is digits plus 160 guard bits; the 100-digit run uses
493 bits. Newton midpoints are candidates only. Opposite strict signs at exact
rational endpoints certify the final interval independently of Newton.
"""
import os
import sys
import re
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.rings.complex_arb import ComplexBallField
WORKING_GUARD = 160
ROOT_GUARD_DIGITS = 10
def phase(t):
"""Continuous Riemann-Siegel phase, using analytic log-gamma."""
R = t.parent()
C = ComplexBallField(R.precision())
return C(QQ(1)/4, t/2).log_gamma().imag() - t*R.pi().log()/2
def phase_derivative(t):
R = t.parent()
C = ComplexBallField(R.precision())
return (C(QQ(1)/4, t/2).psi().real() - R.pi().log())/2
def gram_point(n, digits=100):
if not isinstance(n, int) or n < -1:
raise ValueError('The phase index must be an integer at least -1')
R = RealBallField(numberdb.bits(digits, losing=WORKING_GUARD))
assert phase_derivative(R(7)) > 0
assert phase(R(7)) < -R.pi()
target = n*R.pi()
t = R(10 + 6*(n+1))
# No claim that a Newton candidate is an enclosure of the root.
for _ in range(20):
t_next = R((t - (phase(t)-target)/phase_derivative(t)).mid())
if t_next == t:
break
t = t_next
center = t.mid().exact_rational()
radius = QQ(1)/10**(digits+ROOT_GUARD_DIGITS)
left, right = center-radius, center+radius
assert left > 7
low_value = phase(R(left)) - target
high_value = phase(R(right)) - target
assert low_value.is_finite() and high_value.is_finite()
assert low_value < 0 < high_value, ('failed endpoint certificate', n)
ball = R(left).union(R(right))
assert ball.is_finite() and phase_derivative(ball) > 0
assert ball.accuracy() >= numberdb.bits(digits)
return ball
class GramPoints(numberdb.Generator):
table = 'T583'
parameters = ('n',)
type = 'R'
digits = 100
rigour = 'proven'
files = ('generate.py', 'checks.py', 'argument-selection.md',
'certification.md', 'skill-manifest.json')
def enumerate(self, maximum=200):
for n in range(-1, maximum+1):
yield {'n': str(n)}
def value(self, params, digits):
return gram_point(int(params['n']), digits)
def client_from_environment():
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
key = sys.stdin.read().strip()
if re.match(r'^[A-Z_][A-Z0-9_]*\s*=', key):
key = key.split('=', 1)[1].strip().strip('\"\'')
return numberdb.Client(api_key=key)
return numberdb.Client()
if __name__ == '__main__':
generator = GramPoints()
client = client_from_environment()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(client=client,
message='Certified 202 Gram points with independent checks'))
else:
report = generator.verify(sample=None, client=client)
print(report)
sys.exit(0 if report.ok else 1)