generate.py

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

5020 bytes, as of the version from 2026-11-02 06:04 (current). Recorded here, not run.

"""Stable Faltings heights of CM elliptic curves -- numberdb.org/T670.

Run with SageMath (install numberdb once with sage -pip install numberdb):
    sage -python generate.py                  # verify all stored entries
    sage -python generate.py --fill           # fill the existing draft
    sage -python checks.py                    # local independent checks
    sage -python checks.py --stored           # also check live stored values

Filling needs NUMBERDB_API_KEY; it writes numbers, never changes draft status.
Reading a private draft also needs a key permitted to view it.
The campaign can supply the key on stdin with NUMBERDB_KEY_FROM_STDIN=1.
NUMBERDB_PUBLISH=1 is its legacy flag for filling numbers, not publication.

The height is in the Silverman/Faltings metric (i/2) integral omega wedge
conjugate(omega), following Barquero-Sanchez et al., Theorem 1.3,
DOI 10.1007/s40993-017-0077-7. Delta=f^2 D is recovered exactly.
Maximal-order class numbers are obtained from the exact character sum;
all transcendental operations use Arb enclosures. The 96 extra working bits
retain at least 408 relative accuracy bits over the entire selection, as
measured by checks.py. No sibling rounded digits
are used. argument-selection.md explains the discriminant cutoff.
"""
import os
import sys
from functools import lru_cache
import numberdb.sage as numberdb
from sage.arith.misc import kronecker_symbol
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField

MAX_DISCRIMINANT = 1000
WORKING_GUARD = 96
TABLE = 'T670'


def decompose(delta):
    delta = ZZ(delta)
    if delta >= 0 or delta % 4 not in (0, 1):
        raise ValueError('Expected a negative order discriminant')
    k = delta.squarefree_part()
    D = k if k % 4 == 1 else 4*k
    square = delta // D
    f = square.isqrt()
    assert f*f*D == delta
    return D, f


@lru_cache(maxsize=None)
def field_data(D):
    D = ZZ(D)
    d = -D
    w = 6 if D == -3 else 4 if D == -4 else 2
    weighted = sum(a*kronecker_symbol(D, a) for a in range(1, int(d)))
    numerator = -w*weighted
    assert numerator % (2*d) == 0
    h = numerator // (2*d)
    assert h > 0
    return d, w, h


@lru_cache(maxsize=None)
def log_period(D, precision):
    R = RealBallField(precision)
    D = ZZ(D)
    d, w, h = field_data(D)
    s = R(0)
    for a in range(1, int(d)):
        chi = kronecker_symbol(D, a)
        if chi:
            s += chi * R(QQ(a)/d).log_gamma()
    return R.pi().log()/2 + R(QQ(w)/(4*h))*s


def correction(D, f, R):
    answer = R(f).log()/2
    for p, v in ZZ(f).factor():
        chi = kronecker_symbol(D, p)
        c = (QQ(1-chi)/(p-chi)) * (1-QQ(1)/p**v)/(1-QQ(1)/p)
        answer -= R(c)*R(p).log()/2
    return answer


def height(delta, precision):
    D, f = decompose(delta)
    R = RealBallField(precision)
    answer = R(-D).log()/4 - log_period(D, precision) + correction(D, f, R)
    assert answer.is_finite() and answer.accuracy() > 340
    return answer


class StableCMHeights(numberdb.Generator):
    table = TABLE
    parameters = ('Delta',)
    type = 'R'
    digits = 100
    rigour = 'proven'
    files = ('generate.py', 'checks.py', 'argument-selection.md', 'check.py',
             'numerical-evidence.json', 'skill-evidence.json')

    def enumerate(self, limit=MAX_DISCRIMINANT):
        for d in range(3, limit+1):
            if (-d) % 4 in (0, 1):
                yield {'Delta': str(-d)}

    def value(self, params, digits):
        delta = int(params['Delta'])
        result = height(delta, numberdb.bits(digits, losing=WORKING_GUARD))
        comments = {
            -3: r'The maximal order in $\mathbb Q(\sqrt{-3})$ has singular modulus $j=0$. Its height equals HREF{Faltings_heights_of_elliptic_curves_over_Q#27,0,5832,stable}[the stable height of Cremona 27a1].',
            -4: r'The Gaussian maximal order has singular modulus $j=1728$. Its height equals HREF{Faltings_heights_of_elliptic_curves_over_Q#32,48,0,stable}[the stable height of Cremona 32a2].',
            -23: r'This maximal order has class number $3$, so its conjugate singular moduli are nonrational and share this stable height.',
            -28: r'The order has field discriminant $D=-7$ and conductor $f=2$. The prime $2$ splits, so $c_2=0$ in CITE{formula-conductor}; this is CITE{Barquero}, Example 2.1.',
        }
        if delta in comments:
            return {'number': result, 'comment': comments[delta]}
        return result


if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()
    generator = StableCMHeights()
    if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        print(generator.publish(message='CM-order stable heights with certified Gamma sums and independent eta checks'))
    else:
        report = generator.verify(sample=None)
        print(report)
        if not report.ok:
            raise SystemExit(1)