back to table · edit · history · where entries came from · files · download
4007 bytes, as of the version from 2026-11-11 03:31 (current). Recorded here, not run.
"""T715: Central binomial sums, U_p(v).
Install numberdb in SageMath (or a suitable modular passagemath environment).
sage -pip install numberdb
sage -python generate.py # verify all stored entries
sage -python generate.py --publish # add/update the selected entries
The second command requires the draft owner's configured NumberDB API key.
It fills the target; it does not publish or offer the private draft.
Parameters are ordered (p,v), with p>=1 integral and -1/4<=v<=1/4 rational.
The default selection is p=1..9 at v=-1/4,-1/16,1/16,1/4. Values include n=0.
No normalization factors are applied. All computations use rigorous real balls.
See computation.md for the beta coefficient identity and certified tails.
At v=1/4 use finite coefficients of the beta generating function; at -1/4
use the Euler transform of a Hausdorff moment sequence, with tail <=2^-N.
Interior points use the defining series and a geometric absolute tail.
The Euler difference computation uses extra precision to absorb cancellation.
Session/model attribution is supplied externally, never fixed by this file.
"""
import argparse
import os
import sys
from functools import lru_cache
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
ARGUMENTS = ('-1/4', '-1/16', '1/16', '1/4')
def selection(max_order=9):
for p in range(1, int(max_order) + 1):
for v in ARGUMENTS:
yield {'p': p, 'v': v}
@lru_cache(maxsize=256)
def central_sum(p, v, digits):
p, v, digits = ZZ(p), QQ(v), int(digits)
if p < 1 or abs(v) > QQ(1)/4:
raise ValueError('Require integer p>=1 and rational |v|<=1/4')
target = numberdb.bits(digits + 25)
work_bits = 2*target + 80
R = RealBallField(work_bits)
if v == 0:
return R(1)
if v == QQ(1)/4:
# sum U_(m+1)(1/4) h^m = pi/2 exp(sum a_k h^k).
a = [R(0), R(2).log()]
a.extend((1 - R(2)**(1-k))*R(k).zeta()/k for k in range(2, int(p)))
e = [R(1)]
for m in range(1, int(p)):
e.append(sum(k*a[k]*e[m-k] for k in range(1, m+1))/m)
result = R.pi()*e[int(p)-1]/2
elif v == -QQ(1)/4:
N = int(target)
c = QQ(1)
differences = []
for n in range(N):
differences.append(R(c)/(2*n+1)**p)
c *= QQ(2*n+1)/(2*n+2)
result = R(0)
for k in range(N):
result += differences[0]*R(2)**(-k-1)
differences = [differences[j]-differences[j+1]
for j in range(len(differences)-1)]
result = result.add_error(R(2)**(-N))
else:
q = 4*abs(v)
# Choose N by an exact geometric inequality, without float logs.
N = 1
while q**N/(1-q) > QQ(1)/ZZ(2)**target:
N += 1
coefficient = R(1)
result = R(0)
for n in range(N):
result += coefficient/(2*n+1)**p
coefficient *= R(v)*2*(2*n+1)/(n+1)
tail = R(q)**N/((1-R(q))*(2*N+1)**p)
result = result.add_error(tail)
assert result.is_finite()
assert R(result.rad()) < R(10)**(-digits-15)
return result
class CentralBinomialSums(numberdb.Generator):
table = 'T715'
parameters = ('p', 'v')
type = 'R'
digits = 100
rigour = 'proven'
def enumerate(self, max_order=9):
yield from selection(max_order)
def value(self, params, digits):
return central_sum(params['p'], params['v'], digits)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--publish', action='store_true')
args = parser.parse_args()
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
numberdb.configure(api_key=sys.stdin.read().strip())
generator = CentralBinomialSums()
if args.publish:
print(generator.publish())
else:
print(generator.verify(sample=None))