Binary splitting of hypergeometric series in mp_real
- Cost
- for bits of a geometrically convergent series with polynomial coefficients.
Binary splitting evaluates a sum of terms of a hypergeometric series exactly as a ratio of two integers, organised as a balanced tree so that the products at each level have similar sizes (Binary splitting and product trees) [Bre1976] [HP1998]. It is the method of choice for constants such as , , and , and for the Taylor series of elementary functions at a rational point (the bit-burst algorithm).
The recursion#
(or its reciprocal) for integer polynomials , , , in the format of y-cruncher's formula files [Yee2025]. Over a range of terms let
so that the partial sum over , relative to the product of the ratios before , is .
Proposition 1. For , with the left values over and the right values over ,
Proof. The terms with of are those of multiplied by ; the terms with are those of multiplied by .
is needed only by left children, so the right spine of the tree skips it. The result is followed by one division and the scalar factors.
Leaves#
The tree splits at leaf boundaries, and a leaf of terms (24 to 32, or about 24 limbs of ) is evaluated exactly in one scratch buffer by the backward recurrence
for from the end of the leaf down. When divides , (as for , and most formulas), the step becomes , where is typically a single word even when is not. The polynomial values are computed by Horner's rule in two's complement with a word count fixed by a bound on the values up to the last term: whole leaves at a time for single-word values, then mpn_mul_1 and mpn_addmul_1 passes with the signs folded in.
Common factors#
Content powers. When (or ) has a large constant content , such as in the series of , the products are carried without it, , and the merges use with the pure powers taken from a table built by squarings over a perfectly balanced tree of leaves. This replaces a full-size product by a short one but adds a product by a power, so it pays only when the content dominates: the table is used when the content has at least eight times the bits per term of the rest of .
Content removal. A node only represents the ratios and , and divides , and of the merge, so and can be divided by before the products [CHTZZ2007]. The cancellation is large: the final shrinks from 230 to 50 bits per term for , from 64 to 19 for Catalan's constant, from 34 to 14 for and from 91 to 58 for . The gcd is not computed by an integer gcd but read off partial factorisations of and over the primes below , kept with every node: and are factored over , the values of their linear factors are factored by a segmented sieve in memory, and a node's lists are merged from its children's. A prime shared by (left) and (right) divides a fixed linear combination of for each pair of linear factors, so only primes below a bound linear in the node's size need to be compared, and larger ones wait until the level at which they can cancel. The removal costs exact divisions, so it is done only where it pays (not near the root, and not at small precisions).
Truncation near the root#
All values are mp_real_t balls, and exact ones stay exact as long as they fit the working precision ; near the root the products exceed limbs and are rounded, so the top levels of the tree are floating-point computations with rigorous radii. Content removal stops there, since it needs exact values.
Lemma 2. Let and be the sums of the limb exponents of the factors, , and let be rounded to limbs. Then at most limbs of lie above the last limb of the rounded .
Proof. A product of balls with limb exponents and has its top limb at position or (in units of ), so the rounded ends at or above position , and starts at or below position . The number of limb positions from to is .
The sum takes nothing below the last limb of an inexact operand (Sums), so is formed at limbs. For a convergent series, is the right partial sum times the product of the left ratios, which is small: at the root is about half the working precision. Computing at limbs cuts that product by a third at digits of .
Tail bound#
The number of terms is the least for which a rigorous bound on the tail is below the target. The product is accumulated exactly (with bounded double rounding) for small and bounded in closed form beyond the point where every polynomial is dominated by its leading term; the terms beyond are bounded by a geometric series from leading-term bounds. The bound is added to the radius of the result, which therefore encloses the exact . A series whose ratio does not tend to a limit below 1 in absolute value, or whose bound cannot be established, throws.
Transform reuse in the merges#
At large sizes the products of a merge are FFT products, each costing two forward transforms, a pointwise product and an inverse transform. The four products of Proposition 1 come in two pairs with a common operand:
Each pair is formed by _fft_small_mpn_mul_shared (Integer products with a common operand; see also multiplication with several primes), which computes the transform of the common operand once: three forward and two inverse transforms instead of four and two. The pairs are those that the two threads of a parallel merge take, so the sharing combines with parallelism.
A pair is shared when all three operands are exact and nonzero, both products are kept whole (at most limbs), and _flint_mpn_mul_shared_use_fft accepts the sizes (the longer product in the FFT range of flint_mpn_mul, the shorter in half of it). Near the root, where the products are truncated to middle products, separate products are used. The second product of each pair is written over its operand (resp. ), and a shared pair needs no more memory than one product, so the peak memory is unchanged. Measured on Emerald Rapids for , this makes the whole computation 6 to 10% faster at and digits, 4 to 5% at and 3% at on one thread, and 3 to 7% on two threads.
Summing in transform space, which would save one more inverse transform, is not done: lacks the low zero limbs stripped from its mantissa (the 2-adic part of , for a third of its length), so the two products are aligned differently, and padding them to a common bottom lengthens every transform by more than the inverse transform saves.
Power tables with precomputed transforms#
The bit-burst splittings of the exponential and of the sine and cosine (Bit-burst evaluation) have (resp. ), a constant, so of a merge over with midpoint is the power . The tree splits at fixed midpoints , so only distinct steps occur, and the powers are tabulated once (a power table, as in arb). Every merge with step multiplies by its right child, so the fft_small transform of can be computed once per tree, and each such product saves the conversion and forward transform of the table entry, about 30% of a two-prime product (_fft_small_mpn_mul_precomp, Integer products with a common operand).
Lemma 3. In a binary splitting of terms with fixed midpoints, the ranges of any level have at most two distinct lengths, differing by one. Consequently the number of merges using each step , and the longest right child among them, can be computed in operations from alone.
Proof. By induction on the level: if all ranges of a level have length or , their halves have lengths , , and , which take at most two consecutive values. Tracking the (at most two) lengths and their multiplicities level by level gives the counts.
_mp_real_bs_step_uses computes these counts, and _mp_real_powtab_pre_init transforms the entries used by at least two merges, for partners up to the longest right child; the root's entry, the largest, is used once and is not transformed, since that would only add the storage of its transform. The transforms are made before the recursion and only read during it, so the two halves of a merge can use them on two threads. Their storage is one block, about four times the transform of the largest entry kept; entries whose products exceed limbs are not transformed, which bounds the extra memory to about 50 MB per tree. Measured on Emerald Rapids, the exponential becomes 8% faster at digits and 5% at , the sine and cosine 4% and 3%; at digits the gain is about 3%, with 17% (exp) and 8% (sine and cosine) more peak memory.
Parallelism#
A splitting with a thread budget gives each half of a node half the threads, as flint_parallel_binary_splitting does, but only while the exact values of the node (estimated from the bits per term) stay within four times the working precision (MP_REAL_PAR_CAP). Above that, two concurrent halves would each hold full-size numbers, so they run one after the other with the whole budget, and the merge runs its two pairs of products on two threads, each pair's FFT using its half of the threads. The result does not depend on the number of threads.
Use in FLINT#
mp_real_hypgeom_seriesandmp_real_hypgeom_series_int64implement the general engine, with transform reuse in the merges; the constants of Constants in mp_real and Zuniga's series for logarithms and arctangents (Zuniga's series) are computed with it._mp_real_exp_sum_bs_powtaband_mp_real_sin_cos_sum_bs_powtabimplement the bit-burst splittings with transformed power tables (_mp_real_bs_step_uses,_mp_real_powtab_pre_init,_mp_real_powtab_pre_mul)._mp_real_atan_frac_bsplitand_mp_real_atanh_frac_bsplitare a dedicated splitting of the Taylor series of , using the content-power table for .- The shared and precomputed transforms are
_fft_small_mpn_mul_sharedand_fft_small_mpn_mul_precompoffft_small;flint_mpn_mul_sharedinmpn_extrasis the user-level form of the first.
void mp_real_hypgeom_series(mp_real_t res, const mp_real_hypgeom_series_struct * s, slong n)void _mp_real_exp_sum_bs_powtab(nn_ptr T, slong * tn, nn_ptr Q, slong * qn, slong * QE, nn_srcptr xp, slong xn, slong D, slong N)void _mp_real_powtab_pre_init(mp_real_powtab_pre_struct * T, nn_srcptr * xpow, const slong * xlen, const slong * uses, const slong * ymax, slong len)void _fft_small_mpn_mul_shared(nn_ptr z1, nn_srcptr a, ulong an, nn_ptr z2, nn_srcptr b, ulong bn, nn_srcptr x, ulong xn)void _fft_small_mpn_mul_precomp(nn_ptr z, const fft_small_mpn_mul_precomp_t P, nn_srcptr y, ulong yn)Referenced from#
References#
- [Bre1976] R. P. Brent. The complexity of multiple-precision arithmetic. In R. S. Anderssen and R. P. Brent (eds.), The Complexity of Computational Problem Solving, University of Queensland Press, 1976, 126–165.
- [HP1998] B. Haible and T. Papanikolaou, "Fast multiprecision evaluation of series of rational numbers", Algorithmic Number Theory (ANTS-III), LNCS 1423 (1998), 338–350
- [Yee2025] A. J. Yee. y-cruncher: a multi-threaded pi-program, and its formula collection. http://www.numberworld.org/y-cruncher/ and https://github.com/Mysticial/y-cruncher-Formulas
- [CHTZZ2007] H. Cheng, G. Hanrot, E. Thomé, E. Zima and P. Zimmermann. Time- and space-efficient evaluation of some hypergeometric constants. ISSAC 2007, 85–91. https://doi.org/10.1145/1277548.1277561
The FLINT team, “Binary splitting of hypergeometric series in mp_real,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/floating-point/hypergeometric-series.html (generated 2026-11-02).
@misc{flint-doc-algorithms-floating-point-hypergeometric-series,
author = {{The FLINT team}},
title = {{Binary splitting of hypergeometric series in mp\_real}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/floating-point/hypergeometric-series.html},
note = {Generated 2026-11-02}
}