acb_theta.h
#include <flint/acb_theta.h>This module evaluates the Riemann theta functions with characteristics
and their partial derivatives with respect to z, for any genus g \ge 1, with rigorous error bounds. Here \tau is in the Siegel upper half-space \mathcal{H}_g of symmetric complex g \times g matrices with positive definite imaginary part, and z \in \mathbb{C}^g. The main function acb_theta_jet reduces (z, \tau) with the action of the symplectic group \mathrm{Sp}_{2g}(\mathbb{Z}), evaluates the theta functions at the reduced point with the algorithm of Elkies and Kieffer [EK2025], which combines duplication formulas with short summations and runs in time quasi-linear in the precision for every fixed g, and applies the theta transformation formula. The module also provides arithmetic in \mathrm{Sp}_{2g}(\mathbb{Z}), reduction in \mathcal{H}_g, the summation and duplication building blocks, and, for g = 2, Siegel modular forms and covariants of binary sextics computed from theta values.
For g = 1, the theta functions are those of acb_modular, whose summation code this module uses; in that notation, (\theta_{0,0}, \theta_{0,1}, \theta_{1,0}, \theta_{1,1}) = (\theta_3, \theta_4, \theta_2, -\theta_1).
Start with the guide Characteristics, derivatives and precision, which explains the numbering of characteristics and derivatives and the meaning of the precision argument, and the function page Evaluating Riemann theta functions. The algorithms are described in Theta functions and Quasi-linear evaluation of theta functions.
AlgorithmQuasi-linear evaluation of theta functionsThe algorithm of Elkies and Kieffer for Riemann theta functions in any genus: duplication formulas as a generalised AGM, square roots chosen from low-precision summations, an auxiliary real shift for robustness, dimension lowering for skewed matrices, and derivatives by finite differences.Guides#
Conventions#
- \tau is an
acb_mat_tof size g \times g; z is anacb_ptrof length g, and a list of \mathit{nb} vectorszshas length \mathit{nb} \cdot g. Y = \operatorname{Im}(\tau) and y = \operatorname{Im}(z). - A characteristic (a, b) is encoded as the integer whose 2g binary digits, most significant first, are a_0, \ldots, a_{g-1}, b_0, \ldots, b_{g-1}, and vectors of 2^{2g} theta values are ordered by this integer. Characteristics a or b alone are encoded on g bits.
- Derivatives are taken with respect to z_0, \ldots, z_{g-1} and normalised as Taylor coefficients; derivation tuples are ordered by total order, then reverse-lexicographically (Derivatives).
- The working precision is an absolute precision for the normalised function \widetilde\theta_{a,b}(z, \tau) = e^{-\pi y^T Y^{-1} y} \theta_{a,b}(z,\tau); see Precision.
- Outputs are certified: if Y is not certainly positive definite at the working precision, or the reduction fails, the outputs are indeterminate.
- Symplectic matrices are
fmpz_mat_tof size 2g \times 2g, written m = \begin{pmatrix} \alpha & \beta \\ \gamma & \delta \end{pmatrix} with g \times g blocks; they act by m \cdot \tau = (\alpha\tau + \beta)(\gamma\tau + \delta)^{-1} and m \cdot (z, \tau) = ((\gamma\tau + \delta)^{-T} z, m \cdot \tau).
The low precision (32 bits) used internally for estimates such as Cholesky factors and choices of parameters.
Theta functions#
void acb_theta_jet(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong ord, ulong ab, int all, int sqr, slong prec)Sets th to the partial derivatives with respect to z, up to total order ord, of \theta_{a,b}(z, \tau) at each of the nb vectors z in zs: for the single characteristic ab if all is zero, or for all 2^{2g} characteristics if all is nonzero. With ord = 0 and sqr nonzero, it computes the squares \theta_{a,b}(z,\tau)^2 instead, which is faster when all is set. See Evaluating Riemann theta functions.
void acb_theta_one(acb_ptr th, acb_srcptr z, const acb_mat_t tau, ulong ab, slong prec)void acb_theta_all(acb_ptr th, acb_srcptr z, const acb_mat_t tau, int sqr, slong prec)Set th to the single value \theta_{a,b}(z,\tau) for the characteristic ab, respectively to the vector of 2^{2g} values \theta_{a,b}(z,\tau) (or their squares if sqr is nonzero) for all characteristics. These are acb_theta_jet with nb = 1 and ord = 0; computing all values costs little more than computing one.
void acb_theta_jet_notransform(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong ord, ulong ab, int all, int sqr, slong prec)Same as acb_theta_jet, but without reducing (z, \tau); the input should already be reduced.
int acb_theta_reduce_tau(acb_ptr new_zs, acb_mat_t new_tau, fmpz_mat_t mat, acb_mat_t N, acb_mat_t ct, acb_ptr exps, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec)Reduces \tau under \mathrm{Sp}_{2g}(\mathbb{Z}) and transforms the nb vectors in zs accordingly. Returns 1 on success and 0 on failure (malformed input, or a precision too low to see that Y is positive definite), in which case the outputs are undefined.
int acb_theta_reduce_z(acb_ptr new_zs, arb_ptr rs, acb_ptr cs, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec)Reduces the nb vectors in zs with respect to the lattice \mathbb{Z}^g + \tau \mathbb{Z}^g. For each z, Y^{-1} y is rounded to the nearest even integral vector r (stored in rs), and z' = z - \tau r minus the nearest even integral vector to its real part is stored in new_zs; then \theta_{a,b}(z',\tau) = e^{-\pi i r^T (z + z')} \theta_{a,b}(z,\tau) for all characteristics, and the exponential factor is stored in cs. Returns 0 (with undefined outputs) if the rounding fails because of extreme values, and 1 otherwise.
The Siegel modular group#
Symplectic matrices are ordinary fmpz_mat_t, so the functions of fmpz_mat (such as fmpz_mat_equal and fmpz_mat_mul) apply to them. Except for sp2gz_is_correct, the functions assume that the input is square of even size 2g.
slong sp2gz_dim(const fmpz_mat_t mat)Returns g, half the number of rows of mat.
void sp2gz_set_blocks(fmpz_mat_t mat, const fmpz_mat_t alpha, const fmpz_mat_t beta, const fmpz_mat_t gamma, const fmpz_mat_t delta)Sets mat to \begin{pmatrix} \alpha & \beta \\ \gamma & \delta \end{pmatrix}. The dimensions must match.
void sp2gz_j(fmpz_mat_t mat)void sp2gz_block_diag(fmpz_mat_t mat, const fmpz_mat_t U)void sp2gz_trig(fmpz_mat_t mat, const fmpz_mat_t S)Set mat to J = \begin{pmatrix} 0 & I_g \\ -I_g & 0 \end{pmatrix}, to the block-diagonal matrix \begin{pmatrix} U & 0 \\ 0 & U^{-T} \end{pmatrix} for U \in \mathrm{GL}_g(\mathbb{Z}), and to the trigonal matrix \begin{pmatrix} I_g & S \\ 0 & I_g \end{pmatrix} for a symmetric integer matrix S, respectively.
void sp2gz_embed(fmpz_mat_t res, const fmpz_mat_t mat)void sp2gz_restrict(fmpz_mat_t res, const fmpz_mat_t mat)sp2gz_embed sets the 2g \times 2g matrix res to the embedding of the 2r \times 2r symplectic matrix mat (r \le g) acting on the first r coordinates: \begin{pmatrix} \alpha & 0 & \beta & 0 \\ 0 & I_{g-r} & 0 & 0 \\ \gamma & 0 & \delta & 0 \\ 0 & 0 & 0 & I_{g-r} \end{pmatrix}. sp2gz_restrict sets the 2r \times 2r matrix res to the matrix whose r \times r blocks are the upper left corners of the blocks of mat; the result need not be symplectic.
void sp2gz_fundamental(fmpz_mat_t mat, slong j)sp2gz_nb_fundamental returns the number of fundamental symplectic matrices used in the reduction algorithm, and sp2gz_fundamental sets mat to the j-th of them. For g = 1 there is one (J) and for g = 2 there are 19, which define the boundary of Gottschling's fundamental domain [Got1959]. For g > 2 no such complete set is known; the module uses the 19 g(g-1)/2 matrices obtained by applying the g = 2 matrices to any pair of coordinates and the 2^g embeddings of a lower-dimensional J on any subset of coordinates.
int sp2gz_is_correct(const fmpz_mat_t mat)int sp2gz_is_j(const fmpz_mat_t mat)int sp2gz_is_block_diag(const fmpz_mat_t mat)int sp2gz_is_trig(const fmpz_mat_t mat)Return whether mat is a symplectic matrix, respectively whether the symplectic matrix mat is J, block-diagonal or trigonal as above.
int sp2gz_is_embedded(fmpz_mat_t res, const fmpz_mat_t mat)Given a 2g \times 2g symplectic matrix mat and a square matrix res of size 2r with r \le g, returns whether mat is the result of sp2gz_embed on a 2r \times 2r symplectic matrix, and if so stores that matrix in res (otherwise res is undefined).
void sp2gz_inv(fmpz_mat_t inv, const fmpz_mat_t mat)Sets inv to the inverse \begin{pmatrix} \delta^T & -\beta^T \\ -\gamma^T & \alpha^T \end{pmatrix} of the symplectic matrix mat, without any arithmetic.
fmpz_mat_struct * sp2gz_decompose(slong * nb, const fmpz_mat_t mat)Returns a newly allocated vector of symplectic matrices whose product from left to right is mat, and stores its length in *nb. Each matrix is block-diagonal, trigonal, J, an embedded J from a lower dimension, or an embedded matrix from dimension 1. The caller frees the result by calling fmpz_mat_clear on each entry and then flint_free.
void sp2gz_randtest(fmpz_mat_t mat, flint_rand_t state, slong bits)Sets mat to a random symplectic matrix with entries of about bits bits, a product of block-diagonal and trigonal matrices and J.
The Siegel half-space#
void acb_siegel_cocycle(acb_mat_t c, const fmpz_mat_t mat, const acb_mat_t tau, slong prec)void acb_siegel_transform_cocycle_inv(acb_mat_t w, acb_mat_t c, acb_mat_t cinv, const fmpz_mat_t mat, const acb_mat_t tau, slong prec)void acb_siegel_transform(acb_mat_t w, const fmpz_mat_t mat, const acb_mat_t tau, slong prec)acb_siegel_cocycle sets c to the cocycle \gamma\tau + \delta; acb_siegel_transform sets w to \mathit{mat} \cdot \tau = (\alpha\tau + \beta)(\gamma\tau + \delta)^{-1}; acb_siegel_transform_cocycle_inv computes both and also (\gamma\tau + \delta)^{-1}.
void acb_siegel_cho_yinv(arb_mat_t cho, arb_mat_t yinv, const acb_mat_t tau, slong prec)Sets yinv to Y^{-1} and cho to the upper triangular Cholesky matrix C with positive diagonal and \pi Y = C^T C. If Y is not certainly positive definite at the working precision, both are set to indeterminate matrices.
void acb_siegel_reduce(fmpz_mat_t mat, const acb_mat_t tau, slong prec)Sets mat to a symplectic matrix such that \mathit{mat} \cdot \tau is as reduced as possible, by repeatedly reducing Y with LLL (block-diagonal matrices), the real part of \tau (trigonal matrices), and applying fundamental matrices that increase |\det Y|. If the entries of \tau are not of reasonable size or \det Y is vanishingly small, mat is set to the identity.
int acb_siegel_is_reduced(const acb_mat_t tau, slong tol_exp, slong prec)Returns nonzero if \tau is certainly in the reduced domain with tolerance \varepsilon = 2^{\mathit{tol\_exp}}: |\operatorname{Re}(\tau_{j,k})| \le \frac12 + \varepsilon for all j, k, Y passes arb_mat_spd_is_lll_reduced with parameters (0.99 - \varepsilon, 0.51 + \varepsilon), and |\det(\gamma\tau + \delta)| \ge 1 - \varepsilon for every fundamental matrix of sp2gz_fundamental.
slong acb_siegel_kappa(acb_t sqrtdet, const fmpz_mat_t mat, const acb_mat_t tau, int sqr, slong prec)slong acb_siegel_kappa2(const fmpz_mat_t mat)If sqr is zero, acb_siegel_kappa returns 0 \le r < 8 with \kappa(\mathit{mat}) = \zeta_8^r and sets sqrtdet to the matching square root of \det(\gamma\tau + \delta) in the theta transformation formula; if sqr is nonzero, it returns 0 \le r < 4 with \kappa(\mathit{mat})^2 = i^r and sets sqrtdet to \det(\gamma\tau + \delta). acb_siegel_kappa2 returns 0 \le r < 4 with \kappa(\mathit{mat})^2 = i^r, which does not depend on a choice of square root.
void acb_siegel_randtest(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits)void acb_siegel_randtest_reduced(acb_mat_t tau, flint_rand_t state, slong prec, slong mag_bits)void acb_siegel_randtest_compact(acb_mat_t tau, flint_rand_t state, int exact, slong prec)Set tau to a random matrix in \mathcal{H}_g: possibly far from reduced; reduced, with an imaginary part that may have large entries; or reduced with bounded imaginary part. With exact nonzero, the entries are exact dyadic numbers.
void acb_siegel_randtest_vec(acb_ptr z, flint_rand_t state, slong g, slong prec)void acb_siegel_randtest_vec_reduced(acb_ptr zs, flint_rand_t state, slong nb, const acb_mat_t tau, int exact, slong prec)Set z to a random vector of length g, possibly with large entries, respectively zs to nb random vectors in [-1,1]^g + \tau[-1,1]^g, which are close to reduced with respect to \tau; with exact nonzero, the entries are exact dyadic numbers.
Theta characteristics#
ulong acb_theta_char_set_slong_vec(const slong * vec, slong len)int acb_theta_char_bit(ulong ch, slong j, slong n)acb_theta_char_set_slong_vec returns the integer whose binary digits, most significant first, are the len entries (0 or 1) of vec; with len = 2g and vec = (a, b) this is the index of \theta_{a,b} in vectors of theta values. acb_theta_char_bit returns bit j (counted from 0, most significant first) of ch seen as an element of \{0,1\}^n.
void acb_theta_char_get_arb(arb_ptr v, ulong a, slong g)void acb_theta_char_get_acb(acb_ptr v, ulong a, slong g)Set v to a/2 \in \mathbb{R}^g or \mathbb{C}^g.
slong acb_theta_char_dot(ulong a, ulong b, slong g)slong acb_theta_char_dot_slong(ulong a, const slong * n, slong g)Return \sum_{i} a_i b_i, respectively \sum_i a_i n_i, modulo 4, as an integer in [0, 3].
int acb_theta_char_is_even(ulong ab, slong g)Returns whether the characteristic (a,b) is even, that is, a^T b is even. For odd characteristics, \theta_{a,b}(0, \tau) vanishes identically.
void acb_theta_char_table(ulong * ch, slong * e, const fmpz_mat_t mat, ulong ab, int all)Sets ch to the characteristic (a', b') and e to e(\mathit{mat}, a, b) of the transformation formula (see acb_siegel_kappa) for the characteristic ab, or if all is nonzero, sets the vectors ch and e of length 2^{2g} to these data for all characteristics (ab is then ignored).
void acb_theta_char_shuffle(acb_ptr res, const fmpz_mat_t mat, acb_srcptr th, int sqr, slong prec)Applies the transformation formula for mat to the vector th of 2^{2g} theta values, omitting the factors \kappa, the determinant and the exponential, and stores the result in res. With sqr nonzero, \zeta_8 is replaced by i, as for squared theta values. Used for testing.
Derivatives#
Derivatives with respect to \tau follow from those with respect to z by the heat equation
so only partial derivatives with respect to z are computed. A derivation tuple (k_0, \ldots, k_{g-1}) (a vector of slong of length g) stands for the operator \frac{1}{k_0! \cdots k_{g-1}!} \frac{\partial^{|k|}}{\partial z_0^{k_0}\cdots \partial z_{g-1}^{k_{g-1}}}, as in a Taylor expansion, where |k| = \sum k_i. All tuples of total order at most ord are considered, ordered by total order and then reverse-lexicographically: for g = 2, (0,0), (1,0), (0,1), (2,0), (1,1), (0,2), \ldots. These functions work with such vectors of derivatives of any holomorphic functions.
slong acb_theta_jet_nb(slong ord, slong g)Returns the number \binom{\mathit{ord} + g}{g} of derivation tuples of total order at most ord (0 if ord is negative).
slong acb_theta_jet_total_order(const slong * tup, slong g)void acb_theta_jet_tuples(slong * tups, slong ord, slong g)slong acb_theta_jet_index(const slong * tup, slong g)Return the total order |k| of tup; set tups to the concatenation of all derivation tuples of total order at most ord, in order; and return the index of tup in that order.
void acb_theta_jet_mul(acb_ptr res, acb_srcptr v1, acb_srcptr v2, slong ord, slong g, slong prec)Sets res to the derivatives of fh given the derivatives v1 and v2 of f and h, up to total order ord.
void acb_theta_jet_compose(acb_ptr res, acb_srcptr v, const acb_mat_t N, slong ord, slong prec)Sets res to the derivatives of z \mapsto f(Nz), given the derivatives v of f at Nz; g is the size of N.
void acb_theta_jet_exp_pi_i(acb_ptr res, arb_srcptr a, slong ord, slong g, slong prec)void acb_theta_jet_exp_qf(acb_ptr res, acb_srcptr z, const acb_mat_t N, slong ord, slong prec)Set res to the derivatives at z = 0 of \exp(\pi i (a_0 z_0 + \cdots + a_{g-1} z_{g-1})), respectively to the derivatives at the given z of \exp(\pi i z^T N z).
Ellipsoids#
The summation algorithms sum the theta series over the lattice points in an ellipsoid, as in [DHBHS2004]; see Summation over ellipsoids. Given an upper triangular matrix C with positive diagonal (a Cholesky matrix), a radius R \ge 0, a center v \in \mathbb{R}^g and 1 \le d \le g, the ellipsoid E is the set of n \in \mathbb{Z}^g with (v + Cn)^T (v + Cn) \le R^2 and fixed last coordinates n_d, \ldots, n_{g-1}. It is stored recursively: the range and midpoint of the allowed values of n_{d-1}, and for each value a (d-1)-dimensional child, split into left and right children by the midpoint. For d = g and fixed C, this takes O(R^{g-1}) space for about O(R^g) points.
An ellipsoid as described above. An acb_theta_eld_t is an array of length 1, so that it is passed by reference.
void acb_theta_eld_init(acb_theta_eld_t E, slong d, slong g)void acb_theta_eld_clear(acb_theta_eld_t E)Initialise E as a d-dimensional ellipsoid in ambient dimension g, with 1 \le d \le g, and free it with all its children.
int acb_theta_eld_set(acb_theta_eld_t E, const arb_mat_t C, const arf_t R2, arb_srcptr v)Sets E to the ellipsoid with Cholesky matrix C, squared radius R^2 = R2 and center v, and returns 1. Returns 0 (leaving E undefined) if the coordinates of its points do not fit in slong or the ellipsoid is unreasonably large.
slong acb_theta_eld_nb_pts(const acb_theta_eld_t E)void acb_theta_eld_points(slong * pts, const acb_theta_eld_t E)Return the number of points of E, and set pts (allocated by the caller) to the concatenation of the points, as vectors of length g.
slong acb_theta_eld_box(const acb_theta_eld_t E, slong j)Returns an upper bound for |n_j| over the points n of E, for 0 \le j < g.
slong acb_theta_eld_nb_border(const acb_theta_eld_t E)void acb_theta_eld_border(slong * pts, const acb_theta_eld_t E)Return the number of points in the border of E, a set of points just outside it, and set pts (allocated by the caller) to these points. Used for testing.
int acb_theta_eld_contains(const acb_theta_eld_t E, const slong * pt)Returns whether the point pt of length g is in E.
void acb_theta_eld_print(const acb_theta_eld_t E)Prints a complete description of E, which can be long in high dimension.
void acb_theta_eld_distances(arb_ptr ds, acb_srcptr zs, slong nb, const acb_mat_t tau, slong prec)Sets ds to the concatenation of nb vectors of length 2^g: for each z, the squared distances \mathrm{Dist}_\tau(-Y^{-1}y, \mathbb{Z}^g + \tfrac a2)^2 for all a \in \{0,1\}^g, for the norm \lVert x \rVert_\tau^2 = \pi x^T Y x.
Summation algorithms#
These functions evaluate theta functions by summing the series over an ellipsoid and adding a bound for the tail. They are used at low and moderate precision, and inside the quasi-linear algorithm. The inputs are assumed to be reduced, which allows one ellipsoid to serve several vectors z. For g = 1 they call acb_modular_theta_sum.
Sets eps to 2^{-\mathit{prec}} and R2 to a squared radius R^2 \ge \max(4, 2\,\mathit{ord}) such that (1 + \sqrt{8/\pi}) R^{g - 1 + 2\,\mathit{ord}} e^{-R^2} \prod_{j} (1 + \sqrt{2\pi}/\gamma_j) \le 2^{-\mathit{prec}}, where \gamma_j are the diagonal entries of C = cho. For ord = 0, summing over the ellipsoid of radius R computes \widetilde{\theta}_{a,b} with a tail of absolute value at most eps.
void acb_theta_sum_jet_radius(arf_t R2, arf_t eps, const arb_mat_t cho, arb_srcptr v, slong ord, slong prec)Sets R2 and eps as acb_theta_sum_radius does, but for the derivatives up to order ord, where v = -C Y^{-1} y.
void acb_theta_sum_term(acb_t res, acb_srcptr z, const acb_mat_t tau, const slong * tup, const slong * n, slong prec)Sets res to n_0^{k_0} \cdots n_{g-1}^{k_{g-1}}\exp(\pi i(n^T \tau n + 2 n^T z)), where k = tup (or the zero tuple if tup is NULL). Used for testing.
slong acb_theta_sum_addprec(const arb_t d)Returns an integer close to d/\log 2 if d is finite and of reasonable size, and 0 otherwise: the number of extra bits needed for a term of size e^{-d}.
The type of the function that processes one line (a one-dimensional slice) of an ellipsoid: void worker(acb_ptr th, acb_srcptr v1, acb_srcptr v2, const slong * precs, slong len, const acb_t c, const slong * coords, slong ord, slong g, slong prec, slong fullprec).
void acb_theta_sum_sqr_pow(acb_ptr * sqr_pow, const acb_mat_t exp_tau, const acb_theta_eld_t E, slong prec)For 0 \le j < g, sets sqr_pow[j] (preallocated with length B_j + 1) to the powers e_j^{n^2}, 0 \le n \le B_j, where e_j is the j-th diagonal entry of exp_tau and B_j = acb_theta_eld_box(E, j).
void acb_theta_sum_work(acb_ptr th, slong len, acb_srcptr exp_z, acb_srcptr exp_z_inv, const acb_mat_t exp_tau, const acb_mat_t exp_tau_inv, const acb_ptr * sqr_pow, const acb_theta_eld_t E, slong ord, slong prec, acb_theta_sum_worker_t worker)Runs the summation over the ellipsoid E (g \ge 2), calling worker on each line, without adding a tail bound.
void acb_theta_sum(acb_ptr th, const acb_theta_ctx_z_struct * vec, slong nb, const acb_theta_ctx_tau_t ctx_tau, arb_srcptr distances, int all_a, int all_b, int tilde, slong prec)Evaluates theta functions by summation at the nb pairs (z, \tau) given by the contexts. With all_a (respectively all_b) zero, only a = 0 (respectively b = 0) is computed, otherwise all values; with tilde nonzero, the normalised \widetilde{\theta}_{a,b} are computed. The vector distances of length 2^g (common to all z) sets the precision added for each a; it may be zero, or the output of acb_theta_eld_distances, which is meaningful when the vectors z differ by real vectors.
void acb_theta_sum_jet(acb_ptr th, const acb_theta_ctx_z_struct * vec, slong nb, const acb_theta_ctx_tau_t ctx_tau, slong ord, int all_a, int all_b, slong prec)Sets th to the derivatives up to total order ord of the theta functions at the nb pairs given by the contexts, by summation, with the characteristics selected by all_a and all_b as in acb_theta_sum.
Context structures#
The summation functions only need exponentials of the entries of \tau and z. Context structures store them so that they can be reused for several summations and updated cheaply when (z, \tau) is replaced by (2z, 2\tau) in the quasi-linear algorithm.
The data for summation at a matrix \tau: in particular the matrix exp_tau_div_4 with entries \exp(\pi i (2 - \delta_{j,k}) \tau_{j,k}/4) for j \le k (and its squares, fourth powers and inverses), and for g > 1 the Cholesky matrix of \pi Y and Y^{-1}. With allow_shift, additional fields allow the evaluation of \theta_{a,0} for a \ne 0. An acb_theta_ctx_tau_t is an array of length 1.
The data for summation at a vector z (given a \tau context): the values \exp(2\pi i z_j), their squares and inverses, and for g > 1 the center v of the ellipsoids. An acb_theta_ctx_z_t is an array of length 1.
void acb_theta_ctx_tau_init(acb_theta_ctx_tau_t ctx, int allow_shift, slong g)void acb_theta_ctx_tau_clear(acb_theta_ctx_tau_t ctx)void acb_theta_ctx_z_init(acb_theta_ctx_z_t ctx, slong g)void acb_theta_ctx_z_clear(acb_theta_ctx_z_t ctx)Initialise contexts for dimension g (with the extra fields for \theta_{a,0}, a \ne 0, if allow_shift is nonzero), and free them.
void acb_theta_ctx_z_vec_clear(acb_theta_ctx_z_struct * vec, slong nb)Allocate and initialise a vector of nb contexts for dimension g, and free it.
void acb_theta_ctx_tau_set(acb_theta_ctx_tau_t ctx, const acb_mat_t tau, slong prec)void acb_theta_ctx_z_set(acb_theta_ctx_z_t ctx, acb_srcptr z, const acb_theta_ctx_tau_t ctx_tau, slong prec)Compute the context data for \tau, respectively for z given the context of \tau. The dimensions must match.
void acb_theta_ctx_tau_dupl(acb_theta_ctx_tau_t ctx, slong prec)void acb_theta_ctx_z_dupl(acb_theta_ctx_z_t ctx, slong prec)Replace the context data for \tau by those for 2\tau, respectively those for (z, \tau) by those for (2z, 2\tau), by squaring, which is much cheaper than recomputing them.
void acb_theta_ctx_z_add_real(acb_theta_ctx_z_t res, const acb_theta_ctx_z_t ctx, const acb_theta_ctx_z_t ctx_real, slong prec)Given contexts for (z, \tau) and (t, \tau) with t real, sets res to a context for (z + t, \tau).
void acb_theta_ctx_z_common_v(arb_ptr v, const acb_theta_ctx_z_struct * vec, slong nb, slong prec)Sets v to an ellipsoid center valid for all nb contexts (the union of their centers), for one summation over all of them.
void acb_theta_ctx_exp_inv(acb_t exp_inv, const acb_t exp, const acb_t x, int is_real, slong prec)void acb_theta_ctx_sqr_inv(acb_t sqr_inv, const acb_t inv, const acb_t sqr, int is_real, slong prec)Given e = \exp(\pi i x), acb_theta_ctx_exp_inv sets exp_inv to \exp(-\pi i x): by conjugation if is_real is nonzero, else by inversion, recomputing from x if the inverse is not finite. Given \exp(-\pi i x) and \exp(2\pi i x), acb_theta_ctx_sqr_inv sets sqr_inv to \exp(-2\pi i x), by conjugation if is_real is nonzero and by squaring otherwise.
int acb_theta_ctx_tau_overlaps(const acb_theta_ctx_tau_t ctx1, const acb_theta_ctx_tau_t ctx2)int acb_theta_ctx_z_overlaps(const acb_theta_ctx_z_t ctx1, const acb_theta_ctx_z_t ctx2)Return whether the data of the two contexts overlap in the sense of acb_overlaps. Used for testing.
Duplication steps#
The quasi-linear algorithm uses the duplication formula \theta_{a,0}(z,\tau) \theta_{a,0}(z',\tau) = \sum_{a'} \theta_{a',0}(z+z',2\tau) \theta_{a+a',0}(z-z',2\tau), which also holds for the normalised functions; see Duplication formulas.
void acb_theta_agm_sqrt(acb_ptr res, acb_srcptr a, acb_srcptr roots, slong nb, slong prec)Sets each of the nb entries of res to the square root of the entry of a that overlaps the corresponding entry of roots (a low-precision approximation) and whose opposite does not. If both square roots overlap roots, the entry is their union; if neither does, it is indeterminate.
void acb_theta_agm_mul(acb_ptr res, acb_srcptr a1, acb_srcptr a2, slong g, int all, slong prec)For 0 \le k < 2^g, sets entry k of res to \sum_{b \in \{0,1\}^g} a_{1,b}\, a_{2, b + k}, where b + k is the bitwise exclusive or. If all is nonzero, res has length 2^{2g} and also contains, for 1 \le a < 2^g, the vectors with entries \sum_{b} (-1)^{a^T b} a_{1,b}\, a_{2, b+k}. This is computed with two Hadamard transforms and 2^g products [LT2016], which loses precision when the entries have different orders of magnitude; it is faster when a1 and a2 are the same pointer (squarings).
void acb_theta_agm_mul_tight(acb_ptr res, acb_srcptr a0, acb_srcptr a, arb_srcptr d0, arb_srcptr d, slong g, int all, slong prec)The same as acb_theta_agm_mul on a0 and a, but with error bounds that are much tighter when |a_k| \approx e^{-d_k} and |a_{0,k}| \approx e^{-d_{0,k}}, where d0 and d are the output of acb_theta_eld_distances at (0, \tau) and (z, \tau), as for normalised theta values.
Quasi-linear algorithms on reduced input#
These functions implement the algorithm of [EK2025] described in Quasi-linear evaluation of theta functions. The inputs are assumed to be reduced.
int acb_theta_ql_nb_steps(slong * pattern, const acb_mat_t tau, int cst, slong prec)Decides how many duplication steps to perform at precision prec and when to switch to lower dimensions, and stores the decision in pattern (of length g): roughly, entry j is the number m of steps such that 2^m \gamma_j^2 is of the order of prec, where \gamma_j is the j-th diagonal entry of the Cholesky matrix of \pi Y. The flag cst should be nonzero when only theta constants (z = 0) are needed. Returns 0 if the Cholesky matrix is indeterminate or too extreme, and 1 otherwise.
int acb_theta_ql_lower_dim(acb_ptr * new_zs, acb_ptr * cofactors, slong ** pts, slong * nb, arf_t err, slong * fullprec, acb_srcptr z, const acb_mat_t tau, arb_srcptr distances, slong s, ulong a, slong prec)Implements the dimension-lowering step: writes the normalised theta values \widetilde{\theta}_{a',0}(z, \tau) whose last g - s bits of a' equal a as short linear combinations of theta values in dimension s (1 \le s < g). The pair (z,\tau) should be exact (and ideally reduced), and distances its output of acb_theta_eld_distances.
void acb_theta_ql_recombine(acb_ptr th, acb_srcptr th0, acb_srcptr cofactors, const slong * pts, slong nb, const arf_t err, slong fullprec, slong s, ulong a, int all, slong g, slong prec)The converse of acb_theta_ql_lower_dim: recovers the normalised theta values at (z, \tau) from the values in dimension s at the vectors new_zs and \tau_0. If all is nonzero, th0 holds nb vectors of the 2^{2s} values \widetilde{\theta}_{a_0,b_0} and th receives all 2^{2g} values \widetilde{\theta}_{a,b}(z,\tau); otherwise th0 holds nb vectors of the 2^s values \widetilde{\theta}_{a_0,0} and th receives the 2^g values \widetilde{\theta}_{a,0}(z,\tau). The other arguments are the outputs of acb_theta_ql_lower_dim.
int acb_theta_ql_setup(acb_ptr rts, acb_ptr rts_all, acb_ptr t, slong * guard, slong * easy_steps, acb_srcptr zs, slong nb, const acb_mat_t tau, arb_srcptr distances, slong nb_steps, int all, slong prec)Prepares nb_steps \ge 1 duplication steps for the nb \ge 1 exact, reduced pairs (z, \tau) given by zs, whose first vector must be zero: it computes low-precision approximations of all the square roots to be taken, chooses an auxiliary real vector t if needed, and returns 1 on success. It returns 0 if no suitable t is found, which should happen only with negligible probability. Inexact input gives correct but possibly useless results.
void acb_theta_ql_exact(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, const slong * pattern, int all, int shifted_prec, slong prec)Runs the quasi-linear algorithm for the nb exact, reduced pairs (z, \tau), with the duplication and dimension-lowering pattern pattern, and sets th to the normalised values \widetilde{\theta}_{a,b}(z,\tau) for all characteristics (all nonzero) or \widetilde{\theta}_{a,0}(z,\tau). With shifted_prec nonzero, the precision of each value takes the distances into account, as in acb_theta_sum. Inexact input gives correct but possibly useless results.
void acb_theta_ql_local_bound(arb_t c, arb_t rho, acb_srcptr z, const acb_mat_t tau, slong ord)Sets c \ge 1 and 0 < \rho \le 1 such that |\theta_{a,b}(\cdot,\tau)| \le c for all characteristics on every ball of radius \rho (for the \infty-norm) centered at a point of z, with \rho chosen to make the Cauchy bounds for derivatives up to order ord small.
void acb_theta_ql_jet_error(arb_ptr err, acb_srcptr z, const acb_mat_t tau, acb_srcptr dth, slong ord, slong prec)Given approximations dth of the derivatives of some \theta_{a,b} up to total order \mathit{ord} + 2 at (z, \tau), sets err to a vector such that the derivatives up to order ord at the midpoint of (z,\tau) and at any point of the balls differ by at most err entrywise. This uses the heat equation and a Lipschitz-type bound.
void acb_theta_ql_jet_fd(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong ord, int all, slong prec)void acb_theta_ql_jet(acb_ptr th, acb_srcptr zs, slong nb, const acb_mat_t tau, slong ord, int all, slong prec)Set th to the derivatives up to order ord of \theta_{a,b} at the nb pairs (z, \tau), for all a and for all b (all nonzero) or b = 0; the output is the concatenation of nb times 2^{2g} (or 2^g) vectors of derivatives. acb_theta_ql_jet_fd uses finite differences on the output of acb_theta_ql_exact, in time quasi-linear in \mathit{prec} \cdot \mathit{ord}^g for fixed g; acb_theta_ql_jet uses direct summation instead when ord is positive and the precision is low (few duplication steps would be needed).
Siegel modular forms in genus 2#
For g = 2, many Siegel modular forms can be computed from theta values, in analogy with acb_modular_delta and acb_modular_eisenstein for g = 1. A Siegel modular form of weight \det^k\otimes \mathrm{Sym}^j is a holomorphic function f : \mathcal{H}_2 \to \mathbb{C}_j[X] (polynomials of degree at most j) with
for all m \in \mathrm{Sp}_4(\mathbb{Z}), where for r = \begin{pmatrix} a & b \\ c & d \end{pmatrix}, \mathrm{Sym}^j(r) maps P(X) to (bX + d)^j P\bigl(\tfrac{aX + c}{bX + d}\bigr). A nonzero f exists only for even j. If poles along the diagonal \{\operatorname{diag}(\tau_1, \tau_2)\} are allowed, the ring of such forms is finitely generated, and corresponds to the ring of covariants of binary sextics: a covariant of degree k and index j corresponds to a Siegel modular function of weight \det^{k - j/2}\otimes \mathrm{Sym}^j [CFG2017]. Writing \tau = \begin{pmatrix} \tau_1 & \tau_2 \\ \tau_2 & \tau_3\end{pmatrix}, q_j = e^{2\pi i \tau_j}.
void acb_theta_g2_detk_symj(acb_poly_t res, const acb_mat_t m, const acb_poly_t f, slong k, slong j, slong prec)Sets res to \det(m)^k \mathrm{Sym}^j(m)(f) for a 2 \times 2 matrix m and a polynomial f of degree at most j (higher coefficients are ignored).
void acb_theta_g2_transvectant(acb_poly_t res, const acb_poly_t g, const acb_poly_t h, slong m, slong n, slong k, int lead, slong prec)Sets res to the k-th transvectant of the polynomials g and h, seen as binary forms of degrees m and n (higher coefficients are ignored), or to its leading coefficient (as a constant polynomial) if lead is nonzero.
slong acb_theta_g2_character(const fmpz_mat_t mat)Returns the value (0 or 1, in \mathbb{Z}/2\mathbb{Z}) at mat of the unique nontrivial character of \mathrm{Sp}_4(\mathbb{Z}) [CFG2019, §12].
void acb_theta_g2_even_weight(acb_t psi4, acb_t psi6, acb_t chi10, acb_t chi12, acb_srcptr th2, slong prec)Sets the outputs to the Eisenstein series \psi_4, \psi_6 and the cusp forms \chi_{10}, \chi_{12}, given the vector th2 of the 16 squared theta constants \theta_{a,b}(0, \tau)^2.
void acb_theta_g2_chi5(acb_t res, acb_srcptr th, slong prec)Sets res to \chi_5 = - 2^{-6} \prod_{(a,b)\text{ even}} \theta_{a,b}(0, \tau), given the 16 theta constants th. \chi_5 is a Siegel cusp form with character [CFG2019], and \chi_5^2 = \chi_{10}.
void acb_theta_g2_chi35(acb_t res, acb_srcptr th, slong prec)Sets res to the cusp form \chi_{35}, the unique scalar Siegel modular form of weight 35 up to scalars, normalised as \chi_{35}(\tau) = q_1^2 q_3^2 (q_1 - q_3 )(q_2 - q_2^{-1}) + \cdots, given the 16 theta constants th, by the formula of Bolza [Bol1887] (see [Mum1984, Prop. 6.2, p. 98] for Bolza's notation in terms of characteristics).
void acb_theta_g2_chi3_6(acb_poly_t res, acb_srcptr dth, slong prec)Sets res to the vector-valued cusp form \chi_{3,6} of weight \det^3\otimes \mathrm{Sym}^6 with character, given the first derivatives dth of all 16 theta functions at z = 0 (as computed by acb_theta_jet with ord = 1 and all set) [CFG2017]: \chi_{3,6}(\tau) = \frac{1}{64\pi^6} \prod_{(a,b) \text{ odd}} \left(\frac{\partial \theta_{a,b}}{\partial z_1}(0,\tau) x_1 + \frac{\partial\theta_{a,b}}{\partial z_2}(0,\tau) x_2\right).
void acb_theta_g2_sextic_chi5(acb_poly_t res, acb_t chi5, const acb_mat_t tau, slong prec)Sets chi5 to \chi_5(\tau) and res to \chi_{-2,6}(\tau) = \chi_{3,6}/\chi_5, the meromorphic form that corresponds to the binary sextic itself under the correspondence with covariants. The matrix \tau is reduced, the theta values are computed with acb_theta_jet_notransform, and the transformation law of Siegel modular forms is applied.
void acb_theta_g2_covariants(acb_poly_struct * res, const acb_poly_t f, int lead, slong prec)Sets the 26 entries of res to the generators of the ring of covariants of binary sextics evaluated at f (terms of degree above 6 are ignored), or to their leading coefficients if lead is nonzero.
References#
- [EK2025] N. D. Elkies and J. Kieffer, "A uniform quasi-linear time algorithm for evaluating theta functions in any dimension", in preparation.
- [Got1959] E. Gottschling, "Explizite Bestimmung der Randflächen es Fundamentalbereiches der Modulgruppe zweiten Grades'', Math. Annalen 138 (1959), 103–124. https://doi.org/10.1007/BF01342938
- [DHBHS2004] B. Deconinck, M. Heil, A. Bobenko, M. van Hoeij, and M. Schmies, "Computing Riemann theta functions", Math. Comp. 73:247 (2004), 1417–1442. https://arxiv.org/abs/nlin/0206009
- [LT2016] H. Labrande and E. Thomé, "Computing theta functions in quasi-linear time in genus 2 and above", ANTS XII, Kaiserslautern, LMS J. Comp. Math 19 (2016), 163–177. https://doi.org/10.1112/S1461157016000309
- [CFG2017] F. Cléry, C. Faber, and G. van der Geer. "Covariants of binary sextics and vector-valued Siegel modular forms of genus two", Math. Ann. 369 (2017), 1649–1669. https://doi.org/10.1007/s00208-016-1510-2
- [CFG2019] F. Cléry, C. Faber, and G. van der Geer. "Covariants of binary sextics and modular forms of degree 2 with character", Math. Comp. 88 (2019), 2423–2441. https://doi.org/10.1090/mcom/3412
- [Bol1887] O. Bolza, "Darstellung der rationalen ganzen Invarianten der Binärform sechsten Grades durch die Nullwerthe der zugehörigen Theta-Functionen", Math. Ann. 30:4 (1887), 478–495. https://doi.org/10.1007/BF01444091
- [Mum1984] D. Mumford, Tata Lectures on Theta II, Birkhäuser, 1984. https://doi.org/10.1007/978-0-8176-4578-6
The FLINT team, “acb_theta.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/acb_theta/index.html (generated 2026-10-20).
@misc{flint-doc-acb-theta-index,
author = {{The FLINT team}},
title = {{acb\_theta.h (module overview)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/acb_theta/index.html},
note = {Generated 2026-10-20}
}