FLINT3.7.0-dev

Mathematical constants

Synopsis#include <flint/mp_real.h>
void mp_real_const_pi4(mp_real_t res, slong n, int cache)source
void mp_real_const_log2(mp_real_t res, slong n, int cache)source
void mp_real_const_euler(mp_real_t res, slong n, int cache)source
void mp_real_const_e(mp_real_t res, slong n, int cache)source
void mp_real_const_log10(mp_real_t res, slong n, int cache)source
void mp_real_const_catalan(mp_real_t res, slong n, int cache)source
void mp_real_const_zeta3(mp_real_t res, slong n, int cache)source
void mp_real_const_zeta5(mp_real_t res, slong n, int cache)source
void mp_real_const_gamma_1_3(mp_real_t res, slong n, int cache)source
void mp_real_const_gamma_1_4(mp_real_t res, slong n, int cache)source
void mp_real_const_2_div_pi(mp_real_t res, slong n, int cache)source
void mp_real_const_inv_log2_frac(mp_real_t res, slong n, int cache)source

Set res to a ball containing c = \pi/4, \log 2, Euler's constant \gamma, e, \log 10, Catalan's constant G, \zeta(3), \zeta(5), \Gamma(1/3), \Gamma(1/4), 2/\pi resp. 1/\log 2 - 1, accurate to about n limbs. With cache = 0 the value is computed from scratch; with cache = 1 it is read from (and if necessary added to) a process-wide cache of floors, and the ball is the cached floor with a radius of one ulp.

The cache holds, per constant, \lfloor c B^N \rfloor for the largest N computed so far by any thread. Floors nest (the top limbs of \lfloor c B^N \rfloor are \lfloor c B^n \rfloor for n \le N), so a shorter request is a copy, and a longer one recomputes the entry at \max(n + 5, 1.5 N) limbs, so that a sequence of growing requests costs a constant factor more than the last one. \pi/4, \log 2, 2/\pi and 1/\log 2 - 1 are read from static tables up to 64 limbs. The last two serve the argument reductions modulo \pi/2 and \log 2.

void _mp_real_const_pi4(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_log2(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_euler(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_e(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_log10(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_catalan(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_zeta3(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_zeta5(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_gamma_1_3(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_gamma_1_4(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_2_div_pi(nn_ptr res, ulong * err, slong n, int cache)source
void _mp_real_const_inv_log2_frac(nn_ptr res, ulong * err, slong n, int cache)source

Set res to exactly \lfloor c B^n \rfloor for the constants c of mp_real_const_pi4 and its siblings, and err (if not NULL) to 1. The output has n limbs for the constants below 1 (\pi/4, \log 2, \gamma, G, 2/\pi, 1/\log 2 - 1) and n + 1 limbs, with a units limb, for the others. cache is as for the ball versions.

The floor is read off a ball computed with a few guard limbs, which is recomputed with more guard limbs until its radius determines the floor. The value 1 written to err bounds c - \lfloor c B^n \rfloor B^{-n} in ulps; the error is one-sided.

void _mp_real_const_clear_cache(void)source

Free the shared caches of the constants. No other thread may be using them. flint_cleanup_master also frees them.

mp_real_const_func

The type void (*)(mp_real_t, slong, int) of the ball constant functions (mp_real_const_pi4 and so on).

void _mp_real_const_arb(arb_t res, mp_real_const_func f, slong prec)source

Set res to the constant computed by f with cache = 0, as an arb ball of prec bits. This is the entry point of the arb constants (arb_const_pi, arb_const_log2, arb_const_euler, ...), which keep their own caches.

void _mp_real_const_euler_tune(mp_real_t res, slong n, int set)source

Euler's constant with a forced choice of the logarithms used in the Brent–McMillan formula: set = 0, 1, 2, 3 selects the primes \{2\}, \{2, 3\}, \{2, 3, 5\}, \{2, 3, 5, 7\}, and -1 the automatic choice. For tuning.

mp_real computes twelve constants: \pi/4, \log 2, Euler's constant \gamma, e, \log 10, Catalan's constant G, \zeta(3), \zeta(5), \Gamma(1/3), \Gamma(1/4), 2/\pi and 1/\log 2 - 1. They are the implementations behind arb_const_pi, arb_const_log2, arb_const_euler, arb_const_e, arb_const_log10, arb_const_catalan, arb_const_apery, arb_const_zeta5 and the \Gamma values of arb_hypgeom_gamma_fmpq, and they are used inside the module by the argument reductions of the elementary functions.

Two forms#

The ball functions mp_real_const_* return a ball for the constant accurate to about n limbs. The limb functions _mp_real_const_* return the exact floor \lfloor c B^n \rfloor as a fixed-point number with n fraction limbs, plus a units limb for the constants above 1, and set err to 1: the true value lies in [y, y + 1) ulps. An exact floor is a canonical value, independent of how it was computed. It is determined from a ball computed with a few guard limbs, recomputed with more guard limbs in the rare case that the ball contains a multiple of B^{-n}.

Caching#

With cache = 0 the constant is computed from scratch and nothing is kept. With cache = 1 the value comes from a process-wide cache that holds the floor at the largest precision requested so far. Floors nest: the top limbs of \lfloor cB^N \rfloor are \lfloor cB^n \rfloor for n \le N, so a shorter request is a copy of the top limbs. A longer request recomputes the entry at \max(n + 5, 1.5N) limbs, so that a sequence of growing requests costs a bounded factor more than the largest. All threads read the same entry; one that needs a longer entry builds it under the cache's lock, and readers never wait. The ball version with cache = 1 returns the cached floor with a radius of one ulp. \pi/4, \log 2, 2/\pi and 1/\log 2 - 1 also come from static tables of 64 limbs, so that the elementary functions at small precision touch no cache at all. _mp_real_const_clear_cache (or flint_cleanup_master) frees the caches.

The arb constants call _mp_real_const_arb, which computes with cache = 0 and leaves caching to arb's own caches.

Algorithms#

All constants except \log 10 are hypergeometric series summed by mp_real_hypgeom_series, with formulas chosen from y-cruncher's formula collection as the fastest in this implementation:

ConstantFormula
\piChudnovsky's series [CC1988], 47 bits per term
\log 2Zuniga's series [Zun2025], 11.9 bits per term
e\sum 1/k!
\gammaBrent–McMillan [BM1980] with the bound of [BJ2013], two splittings in dual numbers
\log 10\log 2 + \log 5 from a three-term Machin-type formula
GPilehrood's series [PP2010]
\zeta(3)a series of Zuniga (2023), 2.05 bits per term
\zeta(5)Sun's identity \zeta(5) = (3S + 56\pi^2\zeta(3))/540
\Gamma(1/3)(810^{1/4}\pi/X)^{1/3} with Guillera's series X
\Gamma(1/4)Ebisu's series, or \sqrt{(2\pi)^{3/2}/\operatorname{agm}(1, \sqrt 2)} from 2^{16} limbs

The independent parts (the series and \pi in \zeta(5) and the \Gamma values, the three logarithms of \log 10, the logarithms needed by \gamma) run on separate threads. The details, including the dual-number splitting for \gamma, are in Constants in mp_real.

AlgorithmConstants in mp_realThe series and formulas behind the mp_real constants (π, log 2, e, Euler's constant, log 10, Catalan's constant, ζ(3), ζ(5), Γ(1/3), Γ(1/4)), the dual-number binary splitting for Euler's constant, and the cache of exact floors.

Example#

Examplemp_real_constants.cchecked by make checkdoc
#include <flint/flint.h>
#include <flint/mp_real.h>
#include <flint/arb.h>

int main(void)
{
    mp_real_t c;
    arb_t a;
    ulong f[3], err;
    slong n = mp_real_prec_bits(200);

    mp_real_init(c);
    arb_init(a);

    /* zeta(3) as a ball, computed from scratch */
    mp_real_const_zeta3(c, n, 0);
    mp_real_get_arb(a, c);
    flint_printf("zeta(3) = ");
    arb_printn(a, 50, 0);
    flint_printf("\n");

    /* the cached floor of e B^2: two fraction limbs and a units limb */
    _mp_real_const_e(f, &err, 2, 1);
    flint_printf("floor(e B^2) = %wu %016wx %016wx, err = %wu\n",
        f[2], f[1], f[0], err);

    /* Catalan's constant through the arb entry point */
    _mp_real_const_arb(a, mp_real_const_catalan, 128);
    flint_printf("G = ");
    arb_printn(a, 30, 0);
    flint_printf("\n");

    mp_real_clear(c);
    arb_clear(a);
    flint_cleanup_master();
    return 0;
}
Output
zeta(3) = [1.2020569031595942853997381615114499907649862923405 +/- 1.12e-51]
floor(e B^2) = 2 b7e151628aed2a6a bf7158809cf4f3c7, err = 1
G = [0.915965594177219015054603514932 +/- 3.85e-31]

The example assumes 64-bit limbs; the hexadecimal digits of e are 2.\mathrm{B7E151628AED2A6ABF7158809CF4F3C7}\ldots

Guides#

References#

  • [CC1988] D. V. Chudnovsky and G. V. Chudnovsky. Approximations and complex multiplication according to Ramanujan. In Ramanujan Revisited, Academic Press, 1988, 375–472.
  • [Zun2025] J. Zuniga, "Fast Ramanujan-type Series for Logarithms. Part I", 2025, https://arxiv.org/abs/2506.08245
  • [BM1980] R. P. Brent and E. M. McMillan, "Some new algorithms for high-precision computation of Euler's constant", Mathematics of Computation 34 (1980) 305-312.
  • [BJ2013] R. P. Brent and F. Johansson, "A bound for the error term in the Brent-McMillan algorithm", preprint (2013), https://arxiv.org/abs/1312.0039
  • [PP2010] K. H. Pilehrood and T. H. Pilehrood. "Series acceleration formulas for beta values", Discrete Mathematics and Theoretical Computer Science, DMTCS, 12 (2) (2010), 223-236, https://hal.inria.fr/hal-00990465/
Cite this page

The FLINT team, “Mathematical constants (mp_real.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/mp_real/constants.html (generated 2026-10-20).