Hilbert class polynomials
#include <flint/acb_modular.h>void acb_modular_hilbert_class_poly(fmpz_poly_t res, slong D)sourceSets res to the Hilbert class polynomial of the negative discriminant , the minimal polynomial over of at a CM point of discriminant . If or , res is set to the zero polynomial. See Hilbert class polynomials.
For a negative discriminant (that is, and ), the Hilbert class polynomial is
where ranges over the primitive reduced positive definite binary quadratic forms of discriminant . It has integer coefficients and degree equal to the class number , and its roots generate the ring class field of the order of discriminant [Coh1996]. It is used to construct elliptic curves with complex multiplication, for instance in elliptic curve primality proving.
acb_modular_hilbert_class_poly computes numerically [Enge2009]:
- It enumerates the reduced forms with [Coh1996, Algorithm 5.3.5], pairing with , whose roots are complex conjugate.
- It estimates the bit size of the coefficients from and chooses a working precision 0.5% above it, plus 20 bits.
- It evaluates the roots with
acb_modular_j, forming a real quadratic factor for each conjugate pair, and multiplies the factors by binary splitting witharb_poly_mul, in parallel withflint_parallel_binary_splittingwhen several threads are available. - It converts the result with
arb_poly_get_unique_fmpz_poly. Since the real polynomial is an enclosure of , this succeeds only when every coefficient ball contains a unique integer, and then the result is proven correct. If the enclosure is too wide, it prints a message to standard output and retries with 1.2 times the precision.
Each -value costs multiplications at precision , and grows like ; this simple method is practical for discriminants up to several million. Faster methods for large use class invariants smaller than (Weber functions and other modular functions) and the Chinese remainder theorem [EngeCM].
If or , the output is the zero polynomial.
Example#
The class polynomial of discriminant (class number 3), the size of the class polynomial of discriminant , and the near-integer for the class number one discriminant .
#include <flint/fmpz_poly.h>
#include <flint/acb.h>
#include <flint/acb_modular.h>
int main(void)
{
fmpz_poly_t H;
acb_t tau, j;
fmpz_poly_init(H);
acb_init(tau);
acb_init(j);
acb_modular_hilbert_class_poly(H, -23);
fmpz_poly_print_pretty(H, "x");
flint_printf("\n");
acb_modular_hilbert_class_poly(H, -1000003);
flint_printf("D = -1000003: degree %wd, %wd bits\n",
fmpz_poly_degree(H), FLINT_ABS(fmpz_poly_max_bits(H)));
arb_set_ui(acb_imagref(tau), 163);
arb_sqrt(acb_imagref(tau), acb_imagref(tau), 128);
arb_one(acb_realref(tau));
acb_mul_2exp_si(tau, tau, -1);
acb_modular_j(j, tau, 128);
acb_printn(j, 30, 0);
flint_printf("\n");
fmpz_poly_clear(H);
acb_clear(tau);
acb_clear(j);
return 0;
}x^3+3491750*x^2-5151296875*x+12771880859375 D = -1000003: degree 105, 8527 bits [-262537412640768000.000000000000 +/- 2.85e-19]
References#
- [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996
- [Enge2009] A. Enge. The complexity of class polynomial computation via floating point approximations. Mathematics of Computation 78 (2009), 1089–1107. https://doi.org/10.1090/S0025-5718-08-02200-X
- [EngeCM] A. Enge, CM - a library for the computation of class polynomials and elliptic curve primality proving, https://www.multiprecision.org/cm/
The FLINT team, “Hilbert class polynomials (acb_modular.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/acb_modular/class-polynomials.html (generated 2026-11-02).
@misc{flint-doc-acb-modular-class-polynomials,
author = {{The FLINT team}},
title = {{Hilbert class polynomials (acb\_modular.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/acb_modular/class-polynomials.html},
note = {Generated 2026-11-02}
}