back to table · edit · history · where entries came from · files · download
5505 bytes, as of the version from 2026-09-13 15:43. Recorded here, not run.
"""Values of zeta derivative and logarithmic derivative -- numberdb.org/T228
For each rational s = a/b in lowest terms with b <= 4 and -20 <= s <= 20,
this stores zeta'(s) where s != 1, and zeta'(s)/zeta(s) where s is neither
the pole at 1 nor a zero of zeta. In this real range the excluded zeros are
the negative even integers.
Run it with SageMath:
$ sage -pip install numberdb # once
$ sage -python generate.py # check the table against this code
$ sage -python generate.py --publish # send it, with NUMBERDB_API_KEY set
Values are computed as complex balls using arb's zeta derivative. The
logarithmic derivative is stored with its own sign, not negated.
"""
import os
import sys
from math import gcd
import numberdb.sage as numberdb
from sage.rings.complex_arb import ComplexBallField
from sage.rings.rational_field import QQ
MAX_DENOMINATOR = 4
MIN_ARGUMENT = QQ(-20)
MAX_ARGUMENT = QQ(20)
WORKING_GUARD = 96
QUANTITY_DERIVATIVE = "derivative"
QUANTITY_LOG_DERIVATIVE = "logderivative"
def _key_from_stdin():
if os.environ.get("NUMBERDB_KEY_FROM_STDIN") != "1":
return
token = sys.stdin.read().strip()
if "=" in token and token.split("=", 1)[0].isupper():
token = token.split("=", 1)[1].strip().strip("'\"")
if token:
os.environ["NUMBERDB_API_KEY"] = token
def _argument_order_key(s):
return (s.denominator(), abs(s), s < 0)
def _arguments(max_denominator=MAX_DENOMINATOR):
found = []
for denominator in range(1, max_denominator + 1):
for numerator in range(
int(MIN_ARGUMENT * denominator),
int(MAX_ARGUMENT * denominator) + 1,
):
if gcd(numerator, denominator) != 1:
continue
s = QQ(numerator) / QQ(denominator)
if s.denominator() != denominator:
continue
if MIN_ARGUMENT <= s <= MAX_ARGUMENT:
found.append(s)
for s in sorted(found, key=_argument_order_key):
yield s
def _field(digits):
return ComplexBallField(numberdb.bits(digits, losing=WORKING_GUARD))
def _is_negative_even_integer(s):
return s.denominator() == 1 and s < 0 and int(s) % 2 == 0
def _finite_real(value, label):
if not value.real().is_finite() or not value.imag().is_finite():
raise ArithmeticError("computed a non-finite ball for %s" % (label,))
if not value.imag().contains_zero():
raise ArithmeticError("expected a real value for %s" % (label,))
return value.real()
def zeta_derivative(s, digits):
field = _field(digits)
value = field(s).zetaderiv(1)
return _finite_real(value, "zeta'(%s)" % (s,))
def zeta_log_derivative(s, digits):
field = _field(digits)
point = field(s)
value = point.zetaderiv(1) / point.zeta()
return _finite_real(value, "zeta'(%s)/zeta(%s)" % (s, s))
def _comment(s, quantity):
text = str(s)
if quantity == QUANTITY_DERIVATIVE:
if text == "0":
return "$-\\frac12\\log(2\\pi)$."
if text == "-1":
return (
"$\\frac1{12}-\\log A$, where $A$ is "
"HREF{T227#1,A}[the Glaisher-Kinkelin constant] "
"CITE{DLMFBarnes}."
)
if text == "-2":
return "$-\\zeta(3)/(4\\pi^2)$."
if text == "-4":
return "$3\\zeta(5)/(4\\pi^4)$."
if text == "2":
return (
"$\\frac{\\pi^2}{6}(\\gamma+\\log(2\\pi)-12\\log A)$ "
"CITE{DLMFBarnes}."
)
if quantity == QUANTITY_LOG_DERIVATIVE:
if text == "1/2":
return "$\\frac12(\\frac\\pi2+\\gamma+\\log(8\\pi))$."
if text == "2":
return (
"$\\gamma+\\log(2\\pi)-12\\log A$, where $A$ is the "
"Glaisher-Kinkelin constant."
)
if text == "0":
return "$\\log(2\\pi)$."
return ""
class RiemannZetaDerivativeRationalValues(numberdb.Generator):
table = os.environ.get("NUMBERDB_TABLE", "T228")
parameters = ("s", "quantity")
type = "R"
digits = 100
rigour = "proven"
def enumerate(self, max_denominator=MAX_DENOMINATOR):
for s in _arguments(max_denominator):
if s == 1:
continue
yield {"s": str(s), "quantity": QUANTITY_DERIVATIVE}
if not _is_negative_even_integer(s):
yield {"s": str(s), "quantity": QUANTITY_LOG_DERIVATIVE}
def value(self, params, digits):
s = QQ(params["s"])
quantity = str(params["quantity"])
if quantity == QUANTITY_DERIVATIVE:
number = zeta_derivative(s, digits)
elif quantity == QUANTITY_LOG_DERIVATIVE:
number = zeta_log_derivative(s, digits)
else:
raise ValueError("unknown quantity %r" % (quantity,))
comment = _comment(s, quantity)
if comment:
return {"number": number, "comment": comment}
return number
if __name__ == "__main__":
_key_from_stdin()
generator = RiemannZetaDerivativeRationalValues()
if os.environ.get("NUMBERDB_PUBLISH") == "1" or "--publish" in sys.argv:
print(generator.publish(
message="zeta derivative values at rational arguments",
assisted_by=os.environ.get("NUMBERDB_ASSISTED_BY", "codex-cli"),
))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)