FLINT3.7.0-dev
Module · 270 functions

mp_real.h

#include <flint/mp_real.h>

This module provides multiple-precision real arithmetic in the radix B = 2^{\mathtt{FLINT\_BITS}}, with limb granularity throughout and as little overhead per operation as possible. It is the engine behind the high-precision constants of arb (arb_const_pi, arb_const_euler, ...), the elementary functions of nfloat, the partition function and the Newton divisions of mpn_extras, and it can be used directly as a backend for numerical algorithms: binary splitting, AGM iterations, Newton iterations and evaluation of elementary functions. It works at two levels.

  • mp_real_t is a ball: a midpoint with a limb mantissa and a radix-B exponent, and a rigorous radius counted in units of the mantissa's last limb. The functions mp_real_* provide arithmetic, roots, the arithmetic-geometric mean, the elementary functions, constants and hypergeometric series on balls.
  • Fixed-point numbers in limb arrays represent values in [0, 1) (or with one or two integral limbs). The functions _mp_real_* on them provide the kernels of the elementary functions with explicit error bounds in ulps, Newton inverses and square roots, and exact floors of constants. A leading underscore also marks ball functions with unchecked preconditions.

The module is tuned for 64-bit machines; with 32-bit limbs the generated straight-line kernels are disabled and generic code paths are used.

The guides below explain the two levels: Computing with mp_real balls describes the ball type, precision and radius, and Fixed-point kernels the fixed-point kernels and their error contract. The algorithms are described in Ball arithmetic with limb-granular radii, Elementary functions in mp_real, Multi-prime argument reduction, Binary splitting of hypergeometric series in mp_real and Constants in mp_real.

Guides#

Types and conventions#

A ball

(-1)^{\mathit{negative}}\, (d, \mathit{size})\, B^{\mathit{exp} - \mathit{size}} \;\pm\; \mathit{err}\, B^{\mathit{exp} - \mathit{size}}

with fields d (the mantissa limbs, least significant first), alloc, size, negative, exp (an slong exponent in limbs) and err (a ulong radius in ulps of the mantissa's last limb). A nonzero mantissa has a nonzero top limb, so that B^{\mathit{exp}-1} \le |\mathrm{mid}| < B^{\mathit{exp}}; size = 0 encodes a zero midpoint, whose radius is counted in units of B^{\mathit{exp}}. An mp_real_t is an array of one mp_real_struct, so that it is passed by reference.

More

Pointers to mp_real_struct and const mp_real_struct, used for vectors of balls.

A fixed-point number (x, n) is an array of n limbs x_0, \ldots, x_{n-1} representing the fraction \sum_i x_i B^{i-n} \in [0, 1), with unit in the last place (ulp) B^{-n}. An output written to n + 1 limbs has an additional integral (units) limb at index n, and one written to n + 2 limbs two integral limbs. The fixed-point functions with an ulp-accurate contract take an argument ulong * err immediately after their outputs; they write there a bound for |\mathrm{res} - f(x)| in ulps of the output (B^{-n}), valid for each output of a function with two outputs, and err may be NULL. Each function documents the largest value it can write, so that callers can size their guard limbs. Unless stated otherwise the bounds are two-sided. The guide Fixed-point kernels gives more detail.

All precisions n are numbers of limbs, except that the elementary functions on balls take a precision in bits (_bits suffix).

AlgorithmBall arithmetic with limb-granular radiiThe representation of mp_real balls, with the radius counted in ulps of the last limb and the mantissa length following the accuracy; how errors are bounded and installed, and what this costs compared with arb.

Exponent safety and working precision#

The ball arithmetic is rigorous except that exponents are not checked for overflow; a caller that can produce huge exponents checks its operands against a safe range instead.

The largest safe limb exponent, WORD_MAX / (4 * FLINT_BITS). Since several functions form the bit exponent FLINT_BITS * exp, this keeps bit exponents below WORD_MAX / 4, which is 2^{61} on 64-bit machines.

Return whether |e| \le MP_REAL_EXP_MAX, respectively whether the exponent of x is safe.

More

The number of guard limbs added by mp_real_prec_limbs and mp_real_prec_bits, currently 1.

Return the working precision n in limbs for a target relative accuracy \varepsilon = B^{-\mathit{prec\_limbs}} resp. 2^{-\mathit{prec\_bits}}: prec_limbs resp. \lceil \mathit{prec\_bits} / \mathtt{FLINT\_BITS} \rceil plus MP_REAL_PREC_GUARD.

More

Memory management and assignment#

Initialise x to exact zero, respectively free its memory.

Ensure that x has room for len mantissa limbs. The inline function calls _mp_real_grow when it has to reallocate; the contents of the mantissa are preserved.

Swap x and y efficiently.

void mp_real_set(mp_real_t res, const mp_real_t x)

Set the ball to exact zero, to a copy of x, or to the exact integer c resp. f.

More

Set res to x rounded to its top n \ge 1 limbs (a copy if x has at most n limbs). res may alias x.

More

Set x exactly to (p, \mathit{len})\, 2^e for the unsigned integer (p, \mathit{len}), which may have zero top limbs. The bit part of e costs one limb shift.

void mp_real_neg(mp_real_t res, const mp_real_t x)

Set res to -x; in place this flips the sign bit.

Set res to x \cdot 2^e exactly (an exponent change and at most one limb shift of the mantissa).

Predicates, magnitudes and the radius#

Return whether x is exactly zero (zero midpoint and zero radius).

Return an e with |t| < 2^e for every t in the ball x.

Return an e such that the radius of x is below 2^e times the absolute value of its midpoint: -WORD_MAX / 2 for an exact x and WORD_MAX / 2 for a zero midpoint with a nonzero radius.

Add 2^e to the radius of x, respectively enlarge x to contain x(1 + t) for every |t| \le 2^e.

void _mp_real_add_error_ulps_at(mp_real_t x, double v, slong anchor)

Add v ulps of the mantissa's last limb, respectively v B^{\mathit{anchor}}, to the radius of x, for v \ge 0.

More

Arithmetic#

These functions round their outputs to about n limbs, or fewer when an operand is accurate to fewer, and add all rounding errors to the radius. Outputs may alias inputs. The guide Computing with mp_real balls explains how to choose n.

void mp_real_add(mp_real_t res, const mp_real_t a, const mp_real_t b, slong n)
void mp_real_sub(mp_real_t res, const mp_real_t a, const mp_real_t b, slong n)

Set res to a + b resp. a - b.

More
void mp_real_addmul_ui(mp_real_t res, const mp_real_t x, const mp_real_t y, ulong c, slong n)
void mp_real_submul_ui(mp_real_t res, const mp_real_t x, const mp_real_t y, ulong c, slong n)

Set res to x + yc resp. x - yc for a word c.

More
void mp_real_mul(mp_real_t res, const mp_real_t a, const mp_real_t b, slong n)
void mp_real_mul_ui(mp_real_t res, const mp_real_t a, ulong c, slong n)

Set res to ab resp. ac.

More
void mp_real_mul_complex(mp_real_t rr, mp_real_t ri, const mp_real_t ar, const mp_real_t ai, const mp_real_t br, const mp_real_t bi, slong n)

Set r_r + i r_i to (a_r + i a_i)(b_r + i b_i), to about n limbs relative to the larger part of the result. The outputs may alias the inputs but not each other.

More
void _mp_real_submul_bounded(mp_real_t res, const mp_real_t a, const mp_real_t b, const mp_real_t c, slong E, slong n)

Set res to a - bc, given that |a - bc| < B^E. Only the window of the product that reaches the result is computed, and the result is wrong if the bound does not hold.

More
void mp_real_div(mp_real_t res, const mp_real_t a, const mp_real_t b, slong n)
void mp_real_div_ui(mp_real_t res, const mp_real_t a, ulong c, slong n)

Set res to a / b resp. a / c. The divisor ball must have a relative radius below 2^{-30}; mp_real_div throws for a wider or zero divisor, and mp_real_div_ui for c = 0.

More

Roots and the arithmetic-geometric mean#

void mp_real_sqrt(mp_real_t res, const mp_real_t x, slong n)
void mp_real_rsqrt(mp_real_t res, const mp_real_t x, slong n)

Set res to \sqrt{x} resp. 1/\sqrt{x} for a positive ball x of relative radius below 2^{-30}. A wider ball, or a ball with a negative or zero midpoint, throws, except that mp_real_sqrt of an exact zero gives zero. res may alias x.

More

Set res to 1/\sqrt{c} for a word c \ge 1, by _mp_real_rsqrt_ui_newton; throws for c = 0.

The bound on k for mp_real_root_ui and mp_real_rroot_ui: 2^{40} on 64-bit machines and 2^{27} on 32-bit machines.

void mp_real_root_ui(mp_real_t res, const mp_real_t x, ulong k, slong n)
void _mp_real_root_ui_order(mp_real_t res, const mp_real_t x, ulong k, slong n, int r, int recip)

Set res to x^{1/k} resp. x^{-1/k} for x > 0 and 1 \le k < MP_REAL_ROOT_K_MAX. They throw for k = 0, for x not positive (the third function for k < 2 as well). The third function takes the order r of the iteration (2 \le r \le 15, or 0 for the default) and recip = 1 for the reciprocal root.

More
void mp_real_agm(mp_real_t res, const mp_real_t x, const mp_real_t y, slong n)
void _mp_real_agm_order(mp_real_t res, const mp_real_t x, const mp_real_t y, slong n, int m)

Set res to the arithmetic-geometric mean \operatorname{agm}(x, y) of x, y \ge 0 to about n limbs; throws for a negative midpoint. The second function takes the order m of the final series (at most 16, 10 on 32-bit machines; 0 for the default).

More

Conversions and output#

void mp_real_get_arb(arb_t res, const mp_real_t x)

Set res to the ball x without loss: the midpoint exactly and the radius rounded up.

If the ball x contains exactly one integer, set res to that integer (exactly) and return 1; otherwise return 0 and leave res unchanged. res may alias x, in which case no reallocation takes place.

More
void mp_real_set_dfloat(mp_real_t res, const double * x, slong n, double rad)
void mp_real_get_dfloat(double * res, double * rad, slong n, const mp_real_t x)

Convert from and to the double expansions of dfloat: arrays of n \le 8 doubles (the midpoint components) and a double radius. mp_real_set_dfloat sets res to the ball \sum_i x_i \pm \mathit{rad} and throws for nonfinite components or radius. mp_real_get_dfloat rounds x greedily to n doubles and sets rad (if not NULL) to a bound for the error and the radius of x.

More
void mp_real_print(const mp_real_t x)

Print the fields size, exp and err of x and its value to about twenty digits.

void _mp_real_get_fixed(nn_ptr y, ulong * err, const mp_real_t x, slong n)

Write a ball known to lie in [0, 1) as the fixed-point number (y, n), truncating, and set err (if not NULL) to a bound for the error in ulps B^{-n}, rounded up; UWORD_MAX means that no bound below B - 1 is known. A negative midpoint within the radius is clamped to zero and absorbed into the bound.

Write y = \lfloor x B^n \rfloor for a ball known to lie in [0, 1) and return 1 if the radius determines that floor; otherwise return 0, so that the caller can retry at a higher precision.

Constants#

The constants are computed by binary splitting of hypergeometric series (Constants in mp_real) and can be cached process-wide. Mathematical constants describes the functions in detail.

void mp_real_const_pi4(mp_real_t res, slong n, int cache)
void mp_real_const_log2(mp_real_t res, slong n, int cache)
void mp_real_const_euler(mp_real_t res, slong n, int cache)
void mp_real_const_e(mp_real_t res, slong n, int cache)
void mp_real_const_log10(mp_real_t res, slong n, int cache)
void mp_real_const_catalan(mp_real_t res, slong n, int cache)
void mp_real_const_zeta3(mp_real_t res, slong n, int cache)
void mp_real_const_zeta5(mp_real_t res, slong n, int cache)
void mp_real_const_gamma_1_3(mp_real_t res, slong n, int cache)
void mp_real_const_gamma_1_4(mp_real_t res, slong n, int cache)
void mp_real_const_2_div_pi(mp_real_t res, slong n, int cache)

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.

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

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.

Full documentation

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

Full documentation

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

Full documentation

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.

Full documentation

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.

Full documentation

Elementary functions#

These functions evaluate the elementary functions on balls to a relative accuracy of about 2^{-\mathit{prec}}, or less as the radius of the argument allows. The midpoint is evaluated exactly as given, the working precision is chosen internally, and the outputs may alias the argument. Elementary functions of balls explains the common behaviour, and Elementary functions in mp_real the algorithms.

void mp_real_sin_cos_bits(mp_real_t res1, mp_real_t res2, const mp_real_t x, slong prec)

Set res1 and res2 to balls containing \sin y and \cos y for every y in x. Either output may be NULL. The sine keeps its relative accuracy for small |x|; near the other zeros the loss of significance shows in the radius. Arguments with |x| \ge 2^{\max(65536, 4\,\mathit{prec})} give [0 \pm 1].

Full documentation
int mp_real_tan_bits(mp_real_t res, const mp_real_t x, slong prec)

Set res to a ball containing \tan y for every y in x and return 1, or return 0 with res set to zero when the ball may contain a pole (or |x| \ge 2^{\max(65536, 4\,\mathit{prec})}). The result keeps its relative accuracy near the zeros and poles of the tangent.

Full documentation

The same as mp_real_sin_cos_bits and mp_real_tan_bits for \sin(\pi y), \cos(\pi y) and \tan(\pi y). The argument reduction is exact, so the outputs keep their relative accuracy near every zero (and the tangent near every pole) at any magnitude of x, and the values at multiples of 1/2 (and of the tangent at odd multiples of 1/4) are exact.

Full documentation

Set res1 and res2 to balls containing \sin(\pi p/q) and \cos(\pi p/q), respectively res to \tan(\pi p/q), for words p \ge 0 and q \ge 1, to a relative accuracy of about B^{-n}. Either output of the first function may be NULL; the two must be distinct. The tangent returns 0 with res set to zero at a pole, else 1. The rational values 0, \pm 1, \pm 1/2 are exact. Both throw for q = 0.

Full documentation
void mp_real_exp_bits(mp_real_t res, const mp_real_t x, slong prec)
int mp_real_log_bits(mp_real_t res, const mp_real_t x, slong prec)
void mp_real_atan_bits(mp_real_t res, const mp_real_t x, slong prec)

Set res to a ball containing \exp(y), \log(y) resp. \operatorname{atan}(y) for every y in x. The results keep their relative accuracy near \exp(y) = 1, \log(y) = 0 and \operatorname{atan}(y) = 0. mp_real_exp_bits throws for |y| \ge 2^{\mathtt{FLINT\_BITS} - 5}, where the exponent of the result would leave the safe range. mp_real_log_bits returns 0 with res set to zero unless the ball is strictly positive, and 1 otherwise.

Full documentation
void mp_real_expm1_bits(mp_real_t res, const mp_real_t x, slong prec)
void mp_real_tanh_bits(mp_real_t res, const mp_real_t x, slong prec)
int mp_real_asin_bits(mp_real_t res, const mp_real_t x, slong prec)
int mp_real_acos_bits(mp_real_t res, const mp_real_t x, slong prec)
void mp_real_asinh_bits(mp_real_t res, const mp_real_t x, slong prec)

Set res (rs to \sinh and rc to \cosh, either may be NULL) to a ball containing \log(1 + y), e^y - 1, \sinh y, \cosh y, \tanh y, \operatorname{asin} y, \operatorname{acos} y, \operatorname{asinh} y, \operatorname{acosh} y resp. \operatorname{atanh} y for every y in x. The results keep their relative accuracy at the zeros of the functions, and tiny and huge arguments are handled without squaring them. The functions returning int return 0 with res set to zero when the ball is not certified to lie in the domain, and 1 otherwise.

Full documentation

Set res to a ball containing \exp(y) for every y in x, to a relative accuracy of about B^{-n}, without the precomputed tables of mp_real_exp_bits. These are meant for a single exponential at huge precision, where building the tables does not pay. The ball handling and the range |y| < 2^{\mathtt{FLINT\_BITS} - 5} are those of mp_real_exp_bits.

Full documentation

The partition function#

void _mp_real_partitions_hrr(mp_real_t res, const fmpz_t n, int flags)

Set res to the exact number of partitions p(n) of n = n_{\mathit{hi}} B + n_{\mathit{lo}} (first function) or of any fmpz n (second function), as an exact mp_real_t. The size of the result is not limited by that of an fmpz_t.

More

Hypergeometric series#

The general binary splitting engine of the module, used for all the constants. Hypergeometric series gives examples, and Binary splitting of hypergeometric series in mp_real the algorithm.

A signed integer (-1)^{\mathit{neg}} (d, n) given by a limb array d of length n (n = 0 for zero) and a sign neg.

Full documentation

A series

S = \left(\frac{c_Q + c_P \sum_{k \ge 1} \frac{P(k)}{Q(k)} \prod_{j=1}^{k-1} \frac{R(j)}{Q(j)}}{c_D}\right)^{\pm 1},

given by the fields power (\pm 1), coefP, coefQ, coefD (the integers c_P, c_Q, c_D) and the integer polynomials P, Q, R as arrays of coefficients (of degree 0 first) with lengths Plen, Qlen, Rlen. This is the format of the SeriesHypergeometric formula files of y-cruncher [Yee2025].

Full documentation
void mp_real_hypgeom_series_int64(mp_real_t res, int power, int64_t coefP, int64_t coefQ, int64_t coefD, const int64_t * P, slong Plen, const int64_t * Q, slong Qlen, const int64_t * R, slong Rlen, slong n)

Set res to a ball containing S with about \mathtt{FLINT\_BITS}(n - 1) accurate bits. The second function takes the coefficients as int64_t, as they appear in y-cruncher's formula files. Both throw if the series is not geometrically convergent, if Q(k) = 0 for some k \ge 1, if c_D = 0, or if the tail cannot be bounded.

Full documentation

Set res to \operatorname{atan}(p/q) resp. \operatorname{atanh}(p/q) for the integers 0 \le p < q given as limb arrays, to about n limbs. The quotient p/q must be bounded away from 1 (at most about 0.99); p \ge q throws.

Full documentation

Progress reports#

void mp_real_set_verbose(int level)

Set or read the level of progress reports on stderr for huge computations: 0 is silent, 1 prints at most one line every two seconds from the long loops and the end of every phase that took that long, and 2 prints the start and end of every phase above a few thousand limbs with its size, thread budget, time and (on Linux) memory use.

More

Fixed-point elementary functions#

The kernels on fixed-point numbers that the ball functions are built on, following [HJ2024] and [Joh2014c]. They take an argument in [0, 1) (or a reduced argument below 2^{-r}) at n fraction limbs and write a bound for the error in ulps to err, as described under Types and conventions. The guide Fixed-point kernels explains how to use them and which kernel serves which precision; the algorithms are described in Elementary functions in mp_real.

Series for small arguments#

void _mp_real_exp_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n)
void _mp_real_sin_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n)
void _mp_real_cos_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n)
void _mp_real_sin_cos_rs(nn_ptr ysin, nn_ptr ycos, ulong * err, nn_srcptr x, slong n)
void _mp_real_sinh_cosh_rs(nn_ptr ysinh, nn_ptr ycosh, ulong * err, nn_srcptr x, slong n)

Evaluate the Taylor series of the function at (x, n) with x < 2^{-32} by rectangular splitting. The outputs have n + 1 limbs for exp, sin, cos, sinh and cosh and n limbs for atan and atanh; the combined versions allow either output to be NULL. err is at most 10 for exp and 15 for the others, and the bound is one-sided (the result never exceeds the true value) for exp, sinh, cosh and atanh.

More

Bitwise argument reduction#

void _mp_real_exp_bitwise_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n, int r)
void _mp_real_log1p_bitwise_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n, int r)
void _mp_real_sin_cos_bitwise_rs(nn_ptr ysin, nn_ptr ycos, ulong * err, nn_srcptr x, slong n, int r)
void _mp_real_tan_bitwise_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n, int r)
void _mp_real_atan_bitwise_rs(nn_ptr res, ulong * err, nn_srcptr x, slong n, int r)

Evaluate \exp(x), \log(1 + x), \sin x and \cos x, \tan x resp. \operatorname{atan} x for any x \in [0, 1) by bitwise (BKM-type) argument reduction below 2^{-r} with cached tables of \log(1 + 2^{-i}) resp. \operatorname{atan}(2^{-i}), followed by a series and a reconstruction. The outputs have n + 1 limbs for exp, sin, cos and tan (either of ysin, ycos may be NULL) and n limbs for log1p and atan. err is at most 9r + 100 (exp), 3r + 64 (log1p), 6r + 128 (sin and cos), 8r + 256 (tan) resp. 4r + 64 (atan), for the r used. r = 0 selects the tuned default, at most 768; explicit values require r \ge 32. On 32-bit machines n \ge 2 is required.

More

Return the reduction parameter that r = 0 selects at n limbs: the depth of the per-size kernel where one exists, and the tuned value beyond (from 64 at a dozen limbs up to 768). The last one serves _mp_real_sin_cos_bitwise_rs and _mp_real_tan_bitwise_rs.

Reduced arguments#

void _mp_real_sin_cos_reduced(nn_ptr ysin, nn_ptr yg, ulong * err, nn_srcptr t, slong n, flint_bitcnt_t r, int alg)

Evaluate \exp(t), respectively \sin t and g = 1 - \cos t, for a reduced argument (t, n) with t < 2^{-r}, r \ge 16 (r \ge 32 for alg = 1, 2). The exponential is written to n + 1 limbs; the sine and g are pure fractions written to n limbs, but both buffers need room for n + 1 limbs. err is the rigorous bound computed at run time, at most 96.

More

Table-free evaluation#

void _mp_real_exp_notab_r(nn_ptr y, ulong * err, nn_srcptr x, slong n, int r)
void _mp_real_sin_cos_notab_r(nn_ptr ysin, nn_ptr ycos, ulong * err, nn_srcptr x, slong n, int r)

Evaluate \exp(x), respectively \sin x and \cos x, for any (x, n) in [0, 1) without precomputed tables: the argument is halved down to the depth r, the reduced function evaluated by _mp_real_exp_reduced resp. _mp_real_sin_cos_reduced, and the result squared resp. the angle doubled back. Outputs have n + 1 limbs; err is at most 128. The _r versions take the depth r explicitly, for tuning.

More

Diophantine argument reduction#

void _mp_real_exp_diophantine_tune(nn_ptr y, ulong * err, nn_srcptr x, slong n, slong num_primes, double max_weight)
void _mp_real_sin_cos_diophantine_tune(nn_ptr ysin, nn_ptr ycos, ulong * err, nn_srcptr x, slong n, slong num_primes, double max_weight)
void _mp_real_tan_diophantine_tune(nn_ptr res, ulong * err, nn_srcptr x, slong n, slong num_primes, double max_weight)

Evaluate \exp(x), \sin x and \cos x (either may be NULL), resp. \tan x for (x, n) in [0, 1) by multi-prime argument reduction [HJ2024]: x minus an integer combination of \log p_j (resp. of \pi/2 and the arguments of Gaussian primes), the reduced function by _mp_real_exp_reduced resp. _mp_real_sin_cos_reduced, and a product by a rational (resp. Gaussian rational) number. Outputs have n + 1 limbs; err is at most 3 for exp and 4 for the others. The _tune versions take the number of primes (2 to 64) and the weight budget of the reduction.

More

Newton–Taylor inverses and the AGM logarithm#

void _mp_real_neglog_newton_tune(nn_ptr y, ulong * err, nn_srcptr x, slong n, int forward, slong N)
void _mp_real_atan_newton_tune(nn_ptr y, ulong * err, nn_srcptr x, slong n, int forward, slong N)

Set (y, n) to -\log x for (x, n) in [1/2, 1), respectively to \operatorname{atan} x for (x, n) in [0, 1), by one Newton–Taylor step over the forward function: -\log x = t - \log(1 + w) with w = x e^t - 1, resp. \operatorname{atan} x = t + \operatorname{atan} w with w = (x\cos t - \sin t)/(x \sin t + \cos t), from a starting value t correct to a fraction of the precision. err is computed at run time and at most 2.

More

Set (y, n) to -\log x for (x, n) in [1/2, 1) by the Sasaki–Kanada AGM formula [SK1982]; err is computed at run time and at most 2. The second function takes the number N of terms of the theta series (0 for the default, 4).

More

Rational multiples of pi#

void _mp_real_sin_cos_pi_ui_div_ui_tune(nn_ptr ys, nn_ptr yc, ulong * err, ulong p, ulong q, slong n, int alg, int r)

Set (y_s, n + 1) and (y_c, n + 1) (either may be NULL) to \sin(\pi p/q) and \cos(\pi p/q) for q \ge 1 and 0 \le p \le q/2. err is at most 4 for the closed forms and the Chebyshev iteration and the kernel's bound plus 2 (at most 6r + 130, r \le 768) when the sine and cosine kernel is used.

More

Fixed-point Newton inverses and roots#

The newton suffix marks functions whose results are not ulp-accurate: their error bounds are relative to the output. Inputs are fixed-point numbers (a, a_n) with a_n fraction limbs, and outputs written to n + 2 limbs have n fraction limbs and two integral limbs (the top one possibly zero). mpn_extras, arf and the ball functions of this module build their divisions and square roots on these functions.

For a \in [1/B, 1) with a_{a_n - 1} \ne 0, set (q, n + 2) to an approximation of 1/a \in (1, B] with absolute error at most 4 B^{-n}/a.

More

For b \in [0, 1) with b_n \ge 1 fraction limbs and a as for _mp_real_inv_newton, set (q, n + 2) to an approximation of b/a with absolute error at most 4 B^{-n}/a. The first function multiplies b by _mp_real_inv_newton; the second performs a Karp–Markstein iteration [KM1997].

Set (\mathit{res}, n) to the fraction limbs of an approximation of 1/\sqrt{a} for a word 2 \le a < B, with error at most 2B^{-n}. The main function uses the third-order steps of _mp_real_rsqrt_newton, with the residual a y^2 - 1 exact and short.

For a \in [B^{-2}, 1) with one of its top two limbs nonzero, set (q, n + 2) to an approximation of 1/\sqrt{a} \in (1, B] with absolute error at most 4 B^{-n}/\sqrt{a}.

More

For a as for _mp_real_rsqrt_newton, set (q, n + 2) to an approximation of \sqrt{a} \in [1/B, 1) (the computed value can round up to 1) with absolute error at most 4 B^{-n}/\sqrt{a}, which is proportional to 1/\sqrt{a}, not to the output. The first function multiplies by the reciprocal square root; the second performs a Karp–Markstein iteration.

Reduction tables#

The integer relations and Machin-type formulas behind the diophantine argument reduction. arb uses the same tables (arb_exp_arf_log_reduction, arb_sin_cos_arf_atan_reduction, arb_log_primes_vec_bsplit, arb_atan_gauss_primes_vec_bsplit). See Multi-prime argument reduction.

The largest number of primes of a relation table (64), the same bound for the cached logarithms of primes, and the value -32768 that starts the row ending a relation table.

A table of integer relations \sum_j d_{ij}\alpha_j = \epsilon_i among \alpha_j = \log p_j for the first num primes (gaussian = 0), or among \alpha_0 = \pi/2 and \alpha_j = 2\arg \pi_j for the first nonreal Gaussian primes \pi_j (gaussian = 1), with |\epsilon_i| decreasing. The fields are num, rows, gaussian, is_static, primes (NULL for Gaussian primes), weights (\log_2 p_j resp. \log N(\pi_j)), d (the rows \times num coefficients followed by a row starting with MP_REAL_REL_TERMINATOR), epsilon, epsilon_inv and epsilon_min.

const mp_real_rel_struct * _mp_real_rel_table(int gaussian, slong num)
int _mp_real_rel_table_is_cached(int gaussian, slong num)

Return the relation table for the first num primes or Gaussian primes, 2 \le \mathit{num} \le MP_REAL_REL_MAX, respectively whether a call would find it ready.

More

The number of limbs storing each argument of a Machin-type set (128/\mathtt{FLINT\_BITS}), the largest number of terms of a set (64), and the largest number of word-size primes used to reconstruct its coefficient matrix by modular inversion (8).

A Machin-type set

\log p_i = \frac{1}{\mathit{den}} \sum_j c_{ij}\operatorname{atanh}\frac{1}{x_j}, \qquad \arg \pi_i = \frac{1}{\mathit{den}} \sum_j c_{ij}\operatorname{atan}\frac{1}{x_j},

with fields num, x (the arguments, MP_REAL_MACHIN_X_LIMBS limbs each), den, cbits (one more than the largest bit length of a coefficient) and gaussian. The coefficient matrix is not stored but reconstructed on first use.

nn_srcptr _mp_real_machin_c_row_raw(const mp_real_machin_struct * tab, slong i, slong * climbs, const unsigned char ** csign)

_mp_real_machin_table returns the best set for num values and _mp_real_machin_table_max the size of the largest set. The accessors return the argument x_i, the coefficient c_{ij}, or a row of coefficients, the last one as the cached limbs (climbs limbs per coefficient) and sign bytes.

More

The number of Gaussian primes in _mp_real_gaussian_primes, 64.

const signed char _mp_real_gaussian_primes[2 * MP_REAL_ATAN_GAUSS_MAX]

The real and imaginary parts, consecutively, of the first 64 nonreal Gaussian primes in order of norm: 1 + i, 1 + 2i, 2 + 3i, ...

Set res to the angles \pi/2 and 2\arg \pi_j, j < \mathit{num}, as arb balls of prec bits.

Multithreading#

The constants, the sets of logarithms and Gaussian-prime arguments, mp_real_hypgeom_series and the bit-burst evaluations behind the elementary functions at large precision (hence the diophantine and table-free kernels and everything built on them) use the threads of flint_set_num_threads.

  • A set of independent series (the terms of a Machin-type formula, the logarithms of Euler's constant, the parts of \zeta(5) and of the \Gamma values) runs on up to one thread per series, costliest first.
  • A binary splitting splits its thread budget between the halves of a node, as flint_parallel_binary_splitting does, while the exact values of the node stay within four times the working precision (MP_REAL_PAR_CAP); above, the halves run one after the other with the whole budget and the products of a merge run in two groups on two threads.
  • The slices of a bit-burst evaluation run as tasks, dealt in advance to one lane per thread, each lane folding its factors into its own running product. The assignment depends only on the thread setting, so the result is the same on every run with the same setting.

The constants and series give identical results for any number of threads. The elementary functions at large precision choose between a burst step and a series by the thread count, so their rounding may depend on it, as in arb.

The run-time tables of the module (the bitwise tables, the run-time levels of the dense tables, the logarithms and angles of the diophantine reductions, and the constants) are process-wide shared caches (flint_shared_cache_struct, see thread_support.h): one read-only version at a time, built at the largest precision requested so far, which every thread reads; a request beyond it builds a larger version (at least 1.5 times as long) under the cache's lock. Since the entries are exact floors, which nest, results do not depend on which version served them. Superseded versions stay allocated until flint_cleanup_master. With the tuned defaults, the elementary functions up to 8 limbs and the four static constants up to 64 limbs touch no run-time table at all.

Internal functions#

The functions below are declared in src/mp_real/impl.h (or defined inline in src/mp_real/small.h), which the tests, tuning and profiling programs include as "mp_real/impl.h". They are not part of the stable interface; they are listed because the algorithm pages refer to them and because they are useful when tuning.

Per-size kernels#

The table-driven kernels at one, two and three fraction limbs (64-bit only): for v \in [0, 1), \exp(v) (n + 1 limbs), \log(1 + v) (n limbs), \sin v and \cos v (n + 1 limbs each) resp. \operatorname{atan} v (n limbs), with err between 8 and 64.

More
void _mp_real_small_exp_pm_2(ulong * y2, ulong * y1, ulong * y0, ulong * z2, ulong * z1, ulong * z0, ulong v1, ulong v0)
void _mp_real_small_exp_pm_3(ulong * y3, ulong * y2, ulong * y1, ulong * y0, ulong * z3, ulong * z2, ulong * z1, ulong * z0, ulong v2, ulong v1, ulong v0)

For v \in [0, 1) at two resp. three fraction limbs (most significant limb first), set y = \exp(v) and z = \exp(-v), each with an integral limb, at about 1.5 times the cost of one exponential. 64-bit only.

void _mp_real_small_divq_3(ulong * w2, ulong * w1, ulong * w0, ulong n2, ulong n1, ulong n0, ulong d2, ulong d1, ulong d0)

For three-limb fractions N < D with D normalised (top bit set), set w = \lfloor N B^3/D \rfloor by three 3-by-2 divisions in registers. 64-bit only.

void _mp_real_small_atan_ratio_2(ulong * r1, ulong * r0, ulong y1, ulong y0, ulong x1, ulong x0)
void _mp_real_small_atan_ratio_3(ulong * r2, ulong * r1, ulong * r0, ulong y2, ulong y1, ulong y0, ulong x2, ulong x1, ulong x0)

For fractions X \ge 1/2 and Y \le X at two resp. three limbs (most significant limb first), set the result to \operatorname{atan}(Y/X) at the same number of fraction limbs, with one division instead of a division followed by the arctangent kernel. 64-bit only.

The dense-table kernels at n = 4, \ldots, 10 fraction limbs (64-bit only): for x \in [0, 1), \exp(x) (n + 1 limbs), \log(1 + x) and \operatorname{atan}(x) (n limbs), and \sin x and \cos x (n + 1 limbs each), within the bounds of the bitwise kernels for the reduction depths MP_REAL_*_OPT_R of impl.h.

More

The dense-table kernels as generic loops, for 2 \le n \le MP_REAL_DENSE_RT_MAX = 32 fraction limbs (64-bit only), with the deeper table levels computed at run time as they are needed and shared by all threads. Outputs as for the per-size kernels. The dispatchers call them from eleven limbs on.

Fill every entry not yet computed of the run-time dense tables of a family (MP_REAL_DENSE_RT_EXP, MP_REAL_DENSE_RT_LOG1P or MP_REAL_DENSE_RT_ATAN, the last shared with sine and cosine) in the tier serving n limbs, and return the width of that tier: 21 for n \le 21, else MP_REAL_DENSE_RT_MAX. 64-bit only.

Set (y, n + 1) to \tan v for v \in [0, 1) and n \le 32 from the sine and cosine kernels and one division (64-bit only). With both kernel outputs within E ulps, err is \lfloor 19E/4 \rfloor + 2. The tangent kernel uses it up to 22 limbs.

Series#

void _mp_real_series_rs_sin_cos(nn_ptr ysin, nn_ptr yg, nn_srcptr x, slong n, flint_bitcnt_t r, int hyperbolic)

Tapered rectangular splitting for a fraction 0 \le x < 2^{-r}, r \ge 8, of n limbs. The first function computes \exp(\pm x) (n + 1 limbs, within 5 ulps) or \sin x, \sinh x, \operatorname{atan} x, \operatorname{atanh} x, 1 - \cos x, \cosh x - 1 (n limbs, within 2 ulps) as selected by func. The second computes the sine and 1 - \cos (or \sinh and \cosh - 1 when hyperbolic is set) sharing the powers; either output may be NULL. Outputs may alias x.

More

Set (\mathit{res}, n) to \tan x, \operatorname{atan} x, \operatorname{atanh} x, \sin x or 1 - \cos x (selected by func) for 0 \le x < 2^{-r}, within 6 ulps, by Horner's rule in x^2 over tapered widths with static coefficient tables. The supported ranges are n \le 80, r \ge 32 for the tangent, n \le 13, r \ge 10 for atan and atanh, and n \le 16, r \ge 18 for the sine and cosine.

Set (\mathit{res}, n) to \tan x for 0 \le x < 2^{-r}, r \ge 32, within 3 ulps, for n \le 80 and beyond as long as _mp_real_series_rs_tan_ok returns nonzero. res may alias x.

More

Vector reductions#

void _mp_real_tan_halfangle_vec(nn_ptr ysin, nn_ptr ycos, nn_ptr ytan, nn_srcptr x, slong n, int r)

The bitwise reductions of _mp_real_exp_bitwise_rs, _mp_real_log1p_bitwise_rs, _mp_real_atan_bitwise_rs and of the sine, cosine and tangent, with signed digits and the full-precision arithmetic in radix 2^{56} on vec4n lanes, for x \in [0, 1) and 32 \le r \le 64n - 16, within the bounds of the corresponding _bitwise_rs functions (64-bit only). Outputs: (\mathit{res}, n + 1) for exp, (\mathit{res}, n) for log1p and atan, and n + 1 limbs for each of \sin, \cos, \tan (each may be NULL).

More

Tables and series of the reductions#

Set (\mathit{res}, n) to the floor of \log(1 + 2^{-i}) resp. \operatorname{atan}(2^{-i}) scaled by B^n, or one less, for i \ge 1, by binary splitting in ball arithmetic. These compute entries of the bitwise tables.

Set res to the balls \log p_j, resp. \pi/2 followed by 2\arg \pi_j, j < \mathit{num}, to about n limbs, by the Machin-type sets of _mp_real_machin_table and followup series, the series running on the available threads.

void _mp_real_log_ratio_zuniga(mp_real_t res, const fmpz_t u, const fmpz_t v, slong n)
void _mp_real_atan_ratio_zuniga(mp_real_t res, const fmpz_t d, const fmpz_t t, slong n)

Set res to \log(u/v) for integers u > v > 0, resp. to \operatorname{atan}(d/t) for integers 0 < d < t, by Zuniga's Ramanujan-type series [Zun2025] [Zun2025b], to about n limbs. See Zuniga's series.

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_sin_cos_sum_bs_powtab(nn_ptr A, slong * an, slong * ae, nn_ptr B, slong * bn, slong * be, nn_ptr Q, slong * qn, slong * QE, nn_srcptr xp, slong xn, slong D, slong N, slong lmax)

The exact binary splittings of the bit-burst steps. The first computes T/(Q B^{QE}) = \sum_{k=1}^N x^k/(k!\,B^{Dk}) for the integer x given by (x_p, x_n), x_n \le D; the second the sine and 1 - \cos of x B^{-D} over one common denominator, 1 - \cos = A B^{ae}/(Q B^{QE}) and \sin = x B^{-D}(Q B^{QE} - B B^{be})/(Q B^{QE}), with A and B truncated to lmax limbs. The third returns the number of terms for a reduced argument below 2^{-r} and prec bits.

More

Transformed entries of a power table: the fields pre (an array of fft_small_mpn_mul_precomp_struct, or NULL when no entry is transformed), storage (one block holding all the transforms) and len (the number of entries).

void _mp_real_bs_step_uses(slong * uses, slong * rmax, const slong * xexp, slong len, slong N)

For a binary splitting of N terms with fixed midpoints (ranges of one or two terms being leaves) whose split steps are the len entries of xexp, set uses[i] to the number of merges using the step xexp[i] and rmax[i] to the longest right child of those merges.

More
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)

Prepare, free, and use the transforms of the power-table entries xpow[i] of xlen[i] limbs for products by partners of up to ymax[i] limbs. _mp_real_powtab_pre_mul sets z to \mathit{xpow}[i] \cdot y (\mathit{xlen}[i] + y_n limbs, z may overlap y) through the transform of entry i and returns 1, or returns 0 without writing anything when the entry has no transform or the product is outside its range.

More

The FFT-range threshold (150 limbs) and the size limit (2^{20} limbs per product) of the transformed power tables. Both can be overridden at compile time.

References#

  • [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
  • [HJ2024] J. van der Hoeven and F. Johansson, "Fast multiple precision exp(x) with precomputations", 2024 IEEE 31st Symposium on Computer Arithmetic (ARITH) (2024), https://hal.science/hal-04454093
  • [Joh2014c] F. Johansson, "Efficient implementation of elementary functions in the medium-precision range", 22nd IEEE Symposium on Computer Arithmetic (ARITH 22), 83-89 (2015), https://arxiv.org/abs/1410.7176
  • [SK1982] T. Sasaki and Y. Kanada. Practically fast multiple-precision evaluation of log(x). Journal of Information Processing 5:4 (1982), 247–250.
  • [KM1997] A. H. Karp and P. Markstein, "High-precision division and square root", ACM Transactions on Mathematical Software 23:4 (1997), 561–589
  • [Zun2025] J. Zuniga, "Fast Ramanujan-type Series for Logarithms. Part I", 2025, https://arxiv.org/abs/2506.08245
  • [Zun2025b] J. Zuniga, "Fast Ramanujan-type Series for Logarithms. Part II", 2025, https://arxiv.org/abs/2506.10321
Cite this page

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