FLINT3.7.0-dev
Algorithm

Elementary functions in mp_real

Cost
O(M(n))O(M(n)) times a small constant for the table-based kernels at fixed nn; O(M(n)log⁡2n)O(M(n) \log^2 n) for the bit-burst and diophantine kernels; O(M(n)log⁡n)O(M(n) \log n) for the AGM logarithm and O(M(n)log⁡q)O(M(n) \log q) for sin⁡(πp/q)\sin(\pi p/q) by the Chebyshev iteration.

The elementary functions of mp_real cover precisions from one limb, where an evaluation takes a few dozen nanoseconds, to hundreds of millions of bits, where it takes minutes. No single algorithm is good over that range, and the module combines several: table lookups with short polynomials at a few limbs, argument reduction against precomputed tables of logarithms and arctangents up to a few hundred limbs, multi-prime reduction and binary splitting beyond, and table-free methods for single evaluations at huge precision. The design follows [Joh2014c] (medium precision) and [HJ2024] (high precision with precomputation), with the classical algorithms of Brent [Bre1976agm] [Bre1976b]; [Mul2016] and [BZ2011] are general references.

Throughout, B=2FLINT_BITSB = 2^{\mathtt{FLINT\_BITS}}, nn is a number of limbs and pp a number of bits.

Layers#

Every function is evaluated in three layers.

  1. The ball layer (mp_real_exp_bits and so on) evaluates the function at the exact midpoint mm of the argument and adds the effect of the radius ρ\rho through a bound on the derivative over the ball. It reduces mm to a fixed-point argument v∈[0,1)v \in [0, 1) and chooses the number of limbs of the kernel from the target precision, the leading zero bits of vv (to keep relative accuracy near zeros of the function) and the kernel's error bound.
  2. The kernel computes f(v)f(v) for v∈[0,1)v \in [0, 1) with an error bound in ulps (see Fixed-point kernels for the contract). The kernel is chosen by size:

    Limbsexp, sin, coslogatan
    1–3table-driventable-driventable-driven
    4–32dense tablesdense tablesdense tables
    33–600bitwisebitwisebitwise
    601–65536diophantineNewton–TaylorNewton–Taylor
    abovetable-freeNewton–TaylorNewton–Taylor
  3. The reduced series evaluate the function at a small argument t<2−rt < 2^{-r} left by a reduction: rectangular splitting for moderate rr and bit-burst evaluation at high precision. They are also called directly when the argument itself is small enough, since their cost falls with rr while that of a table-based reduction does not.

Argument reduction of the ball functions#

Exponential. For ∣m∣≥log⁡2|m| \ge \log 2, write ∣m∣=qlog⁡2+t|m| = q\log 2 + t with t∈[0,log⁡2)t \in [0, \log 2). The quotient qq is computed from the top limbs of mm and two limbs of 1/log⁡21/\log 2 (stored as the fraction 1/log⁡2−11/\log 2 - 1), which gives qq or q−1q - 1; one multiply-subtract by the cached floor of log⁡2\log 2 and a correction give tt. For m<0m < 0 the quotient is rounded up and the remainder complemented, so that exp⁡(m)=2−qexp⁡(t′)\exp(m) = 2^{-q}\exp(t') with t′∈[0,log⁡2)t' \in [0, \log 2) and no division. The bound ∣m∣<2FLINT_BITS−5|m| < 2^{\mathtt{FLINT\_BITS} - 5} keeps the exponent of the result in the safe range of Ball arithmetic with limb-granular radii.

Logarithm. For m=2Eum = 2^E u with u∈[1/2,1)u \in [1/2, 1), log⁡m=(E−1)log⁡2+log1p⁡(2u−1)\log m = (E - 1)\log 2 + \operatorname{log1p}(2u - 1) (up to 600 limbs) or Elog⁡2−(−log⁡u)E\log 2 - (-\log u) (beyond). Near m=1m = 1 both forms cancel up to z+1z + 1 bits for ∣m−1∣<2−z|m - 1| < 2^{-z}, and the working precision is raised by that much; for larger zz the function uses log⁡(1±s)=±2atanh⁡(s/(2±s))\log(1 \pm s) = \pm 2\operatorname{atanh}(s/(2 \pm s)) with s=∣m−1∣s = |m - 1| and the reduced atanh series.

Sine and cosine. For ∣m∣≥1|m| \ge 1, the quotient qq approximating 2∣m∣/π2|m|/\pi from below makes t=∣m∣−qπ/2≥0t = |m| - q\pi/2 \ge 0; a fold v=π/2−tv = \pi/2 - t for t>π/4t > \pi/4 brings the argument into [0,π/4][0, \pi/4], and the outputs are permuted and negated according to q mod 4q \bmod 4. The constant 2/π2/\pi for the quotient and π/4\pi/4 for the remainder come from the caches. The reduction is absolute: near a nonzero multiple of π\pi the sine loses relative accuracy, which shows in the radius.

Tangent. The tangent is reduced the same way and finished as ±tan⁡v\pm\tan v or ∓1/tan⁡v\mp 1/\tan v. Near a zero or a pole, vv is small and an absolute error is a relative error of the result, so the kernel runs with the leading zero bits of vv as extra precision, repeating the reduction at the higher precision when needed. This terminates because π\pi has finite irrationality measure, at most 7.117.11 [ZZ2020]: a bb-bit dyadic mm satisfies ∣m−kπ/2∣≳2−7.2b|m - k\pi/2| \gtrsim 2^{-7.2b} for large bb, so a repetition beyond 8b+10248b + 1024 extra bits is never needed (and is not made; the status is then 0).

Functions of πx\pi x. For sin⁡(πm)\sin(\pi m), cos⁡(πm)\cos(\pi m) and tan⁡(πm)\tan(\pi m) the reduction is exact: the units bit and the fraction bits of the dyadic midpoint give ∣m∣=a/2+st|m| = a/2 + st with a∈{0,1,2,3}a \in \{0, 1, 2, 3\}, s=±1s = \pm 1 and t∈[0,1/4]t \in [0, 1/4], and v=πtv = \pi t goes to the kernel with the leading zero bits of tt as extra precision. The results therefore keep their relative accuracy near every zero and pole, and multiples of 1/21/2 (and odd multiples of 1/41/4 for the tangent) give exact results.

Inverse functions. atan⁡\operatorname{atan} reduces ∣m∣≥1|m| \ge 1 by atan⁡(m)=π/2−atan⁡(1/m)\operatorname{atan}(m) = \pi/2 - \operatorname{atan}(1/m) (or π/4+atan⁡((m−1)/(m+1))\pi/4 + \operatorname{atan}((m - 1)/(m + 1)) for 1<m<21 < m < 2). The other inverse and hyperbolic functions are compositions without cancellation, listed under mp_real_log1p_bits; for example acosh⁡(m)=log1p⁡(d+d(m+1))\operatorname{acosh}(m) = \operatorname{log1p}(d + \sqrt{d(m + 1)}) with d=m−1d = m - 1 computed exactly.

Series and rectangular splitting#

A Taylor series ∑k<Nakvk\sum_{k<N} a_k v^k with rational coefficients is evaluated at a fixed-point vv by rectangular splitting [Smi1989] [PS1973]: with blocks of mm terms,

Sb=∑i<mamb+i vi+vmSb+1,S_b = \sum_{i<m} a_{mb+i}\, v^i + v^m S_{b+1},

the powers v,…,vmv, \ldots, v^m are computed once (mm full products), every term is one scalar multiply-add of a precomputed power by a one-limb coefficient, and each block boundary costs one full product. The coefficients 1/k!1/k! are generated as ratios of consecutive integers, chained downwards so that one mpn_divrem_1 closes each run of factors that fills a limb; for 1/(2k+1)1/(2k + 1) the integers D/(2k+1)D/(2k+1) for a group of odd numbers with product DD are used, with one rescaling per group.

Tapering. Block bb is multiplied by vmb<2−rmbv^{mb} < 2^{-rmb} when it enters the sum, so only its top ⌈(FLINT_BITSn+g−rmb)/FLINT_BITS⌉\lceil(\mathtt{FLINT\_BITS} n + g - rmb)/\mathtt{FLINT\_BITS}\rceil limbs matter. Computing each block in its shortened window reduces the total cost to about mm products for the powers and N/(3m)N/(3m) for the block boundaries; with m≈N/1.5m \approx \sqrt{N/1.5} this is about 2N/32\sqrt{N/3} full products, against N/3N/3 for the tapered Horner scheme (_mp_real_series_tapered), which is faster only below about a dozen limbs. Errors committed in block b≥1b \ge 1 are damped by 2−min⁡(g,rm)2^{-\min(g, rm)}, and the final multiplication by vv (for the odd functions) by 2−r2^{-r}, which is why the series is accurate to 2 ulps except for exp, whose sum is the result.

The tangent has coefficients Tk+2/(2k+3)!T_{k+2}/(2k+3)! involving the tangent numbers, which are not ratios of small integers. Their leading denominators are small, though: in _mp_real_series_rs_tan, the terms are grouped into chunks whose common denominator QjQ_j fits j+1j + 1 limbs, and the sum is carried as QjQ_j times the partial sum, so that a term costs j+1j + 1 scalar passes and moving to the next chunk one division by Qj/Qj−1Q_j/Q_{j-1}.

For the sizes on the hot paths (arguments below 2−322^{-32} or 2−642^{-64} after a reduction, up to a few dozen limbs), the series are generated straight-line code; a generic engine making the same calls in the same order serves the other sizes with identical results.

Table-driven kernels#

At one to three limbs on 64-bit machines, the kernels are short table-driven evaluations in registers [Tan1989]:

  • exp: v=j12−7+j22−14(+j32−21)+rv = j_1 2^{-7} + j_2 2^{-14} (+ j_3 2^{-21}) + r with tables of exp⁡(j2−7)\exp(j 2^{-7}), exp⁡(j2−14)−1\exp(j 2^{-14}) - 1 and exp⁡(j2−21)−1\exp(j 2^{-21}) - 1 (128 entries each) and a Taylor polynomial in rr;
  • log1p: a multiplicative reduction by short factors 1−Dk[j]1 - D_k[j] over three or four levels of 7 bits, with tables of −log⁡(1−Dk[j])-\log(1 - D_k[j]), then the Taylor polynomial of log⁡(1+u)\log(1 + u);
  • sin and cos: the pairs (sin⁡c,1−cos⁡c)(\sin c, 1 - \cos c) for c=j2−7c = j 2^{-7} and j2−14j 2^{-14} combined with the polynomials of the remainder by the addition formulas;
  • atan: atan⁡(v)=atan⁡(c)+atan⁡((v−c)/(1+vc))\operatorname{atan}(v) = \operatorname{atan}(c) + \operatorname{atan}((v - c)/(1 + vc)) with c=j2−9c = j 2^{-9} (513 entries) and the odd series of the quotient; for a ratio v=Y/Xv = Y/X the quotient is (512Y−jX)/(512X+jY)(512Y - jX)/(512X + jY) with an exact numerator and denominator, so atan⁡(Y/X)\operatorname{atan}(Y/X) costs one division.

The polynomials taper their precision (one limb for the innermost terms, then two, then three) and keep only the high parts of products. The tables hold three limbs per entry, read at their top limbs at smaller sizes.

Dense tables#

From four to 32 limbs, the kernels reduce the argument seven bits per level against tables, with multipliers that are exact single limbs, so that applying a level costs one row of one-limb products. For exp, t←v−log⁡(2s(1+C1[j1]))t \gets v - \log(2^s(1 + C_1[j_1])) with j1j_1 the top seven bits, then t←t−log⁡(1+jk2−7k)t \gets t - \log(1 + j_k 2^{-7k}) with jk=⌊t27k⌋j_k = \lfloor t 2^{7k} \rfloor for the following levels (the tables hold floors, so tt stays nonnegative), the series of exp⁡(t)\exp(t), and the product of the factors 1+jk2−7k1 + j_k 2^{-7k}. Logarithms use the dual multiplicative reduction, arctangents rotate the vector (1,v)(1, v) by factors 1−ick1 - i c_k, and the sine and cosine rotate the pair (cos⁡t,sin⁡t)(\cos t, \sin t) by 1+ick1 + i c_k and absorb the scale ∏(1+ck2)\prod (1 + c_k^2) by the double-angle formulas cos⁡v=(X2−Y2)/N\cos v = (X^2 - Y^2)/N, sin⁡v=2XY/N\sin v = 2XY/N with N=X2+Y2N = X^2 + Y^2, so that no square root is needed.

At four to ten limbs the code is generated straight-line code with static tables, at 11 to 32 limbs a generic loop (unrolled to add-with-carry chains at 11 to 16 limbs, with an mulx/adcx/adox row in assembly where available). The deeper table levels at those sizes are computed at run time when first needed, entry by entry, and published in a process-wide cache by a compare-and-swap on a state byte, so that no reader waits. The dense kernels are about 1.5 to 4 times faster than the bitwise kernels at the same sizes.

Bitwise reduction#

Up to 600 limbs, the argument is reduced by subtracting tabulated values Li=log⁡(1+2−i)L_i = \log(1 + 2^{-i}) or Ai=atan⁡(2−i)A_i = \operatorname{atan}(2^{-i}), in the manner of the BKM and CORDIC algorithms [BKM1994] [Mul2016], but at multiple precision and with a series for the remainder. The tables are computed once at the precision and index range in use and cached.

Lemma 1. Let c0>c1>⋯>cr>0c_0 > c_1 > \cdots > c_r > 0 with ci−1<2cic_{i-1} < 2c_i, and 0≤x<2c00 \le x < 2c_0. The greedy reduction, which for i=0,…,ri = 0, \ldots, r subtracts cic_i from xx if x≥cix \ge c_i, leaves 0≤x<cr0 \le x < c_r, using each cic_i at most once.

Proof. Before step ii we have 0≤x<2ci0 \le x < 2c_i: this holds for i=0i = 0, and if x≥cix \ge c_i the step leaves x−ci<cix - c_i < c_i, otherwise x<cix < c_i; in both cases x<ci<2ci+1x < c_i < 2c_{i+1}. After step rr the same argument gives x<crx < c_r.

The logarithms satisfy the hypothesis, since 2Li+1=log⁡(1+2−i+2−2i−2)>Li2L_{i+1} = \log(1 + 2^{-i} + 2^{-2i-2}) > L_i, and so do the arctangents, by concavity of atan⁡\operatorname{atan}.

Exponential. After the reduction x=∑i∈ULi+tx = \sum_{i \in U} L_i + t with t<Lr<2−rt < L_r < 2^{-r},

exp⁡(x)=exp⁡(t)∏i∈U(1+2−i),\exp(x) = \exp(t) \prod_{i \in U} (1 + 2^{-i}),

and each factor is one shift-and-add. When the series for exp⁡(t)\exp(t) is long, sinh⁡t\sinh t is computed instead (half the terms) and exp⁡(t)=sinh⁡t+1+sinh⁡2t\exp(t) = \sinh t + \sqrt{1 + \sinh^2 t}.

Logarithm. Dually, a product P=∏i∈U(1+2−i)P = \prod_{i \in U}(1 + 2^{-i}) is built greedily below X=1+xX = 1 + x, each accepted factor one shift-and-add, and

log⁡X=∑i∈ULi+2atanh⁡X−PX+P.\log X = \sum_{i \in U} L_i + 2\operatorname{atanh}\frac{X - P}{X + P}.

The numerator is the exact deficit maintained through the reduction, and the single division both normalises by PP and produces the atanh argument, whose series has half the terms of that of log⁡(1+u)\log(1 + u).

Arctangent. The vector (X,Y)=(1,x)(X, Y) = (1, x) is rotated by the factors 1−i2−i1 - i 2^{-i} whenever Y≥2−iXY \ge 2^{-i} X, that is whenever the angle atan⁡(Y/X)≥Ai\operatorname{atan}(Y/X) \ge A_i. This is the greedy reduction of the angle with steps AiA_i, so atan⁡(Y/X)<2−r\operatorname{atan}(Y/X) < 2^{-r} at the end, and atan⁡x=∑i∈UAi+atan⁡(Y/X)\operatorname{atan} x = \sum_{i \in U} A_i + \operatorname{atan}(Y/X) with one division. The decisions compare YY with a shift of XX and never read the table; the growth of ∣X+iY∣|X + iY| needs no compensation because angles are scale invariant.

Half-angle reconstruction#

For the sine and cosine, the angle x/2x/2 is reduced greedily by the AiA_i, i≥1i \ge 1 (by Lemma 1, since x/2<1/2<2A1x/2 < 1/2 < 2A_1), and the used indices define W=wx+iwy=∏i∈U(1+i2−i)W = w_x + i w_y = \prod_{i \in U} (1 + i 2^{-i}), whose argument is ∑i∈UAi\sum_{i \in U} A_i. Halving is needed because the decisions are taken on a short model of the remainder that requires table entries below 2−i2^{-i}; the doubled angles 2Ai2A_i would not qualify.

Theorem 2. Let x/2=arg⁡W+t′x/2 = \arg W + t' and u=tan⁡t′u = \tan t'. With T=wy+wxuT = w_y + w_x u and D=wx−wyuD = w_x - w_y u,

sin⁡x=2TDD2+T2,cos⁡x=1−2T2D2+T2,tan⁡x=2TDD2−T2.\sin x = \frac{2TD}{D^2 + T^2}, \qquad \cos x = 1 - \frac{2T^2}{D^2 + T^2}, \qquad \tan x = \frac{2TD}{D^2 - T^2}.

Proof. By the addition formula, tan⁡(x/2)=tan⁡(arg⁡W+t′)=(wy/wx+u)/(1−uwy/wx)=T/D\tan(x/2) = \tan(\arg W + t') = (w_y/w_x + u)/(1 - u w_y/w_x) = T/D. The formulas follow from sin⁡x=2τ/(1+τ2)\sin x = 2\tau/(1 + \tau^2), cos⁡x=(1−τ2)/(1+τ2)\cos x = (1 - \tau^2)/(1 + \tau^2) and tan⁡x=2τ/(1−τ2)\tan x = 2\tau/(1 - \tau^2) with τ=T/D\tau = T/D, after multiplying numerator and denominator by D2D^2.

The quotient T/DT/D is never formed: each output costs one reciprocal and one high product. The modulus ∣W∣|W| cancels, so no scale factor ∏(1+2−2i)1/2\prod(1 + 2^{-2i})^{1/2} is needed, and in the limb version the residual enters through sin⁡t′\sin t' and g=1−cos⁡t′g = 1 - \cos t' as T=wy+wxsin⁡t′−wygT = w_y + w_x \sin t' - w_y g and D=wx−wxg−wysin⁡t′D = w_x - w_x g - w_y \sin t', the common factor cos⁡t′\cos t' cancelling as well.

Signed digits on vector lanes#

From a few limbs on 64-bit machines, the bitwise reductions use signed digits di∈{−1,0,1}d_i \in \{-1, 0, 1\}: for the exponential, x=∑di=1ai−∑di=−1bi+tx = \sum_{d_i = 1} a_i - \sum_{d_i = -1} b_i + t with ai=Lia_i = L_i and bi=−log⁡(1−2−i)b_i = -\log(1 - 2^{-i}), the digit did_i chosen by comparing xx with ±0.75⋅2−i\pm 0.75 \cdot 2^{-i}. Since ai≈bi≈2−ia_i \approx b_i \approx 2^{-i}, the remainder satisfies ∣x∣≲2−i|x| \lesssim 2^{-i} before step ii for any decision taken on an approximation of xx within about 0.2⋅2−i0.2 \cdot 2^{-i} (to first order, a remainder below 0.75⋅2−i0.75 \cdot 2^{-i} is kept, and one above it drops by about 2−i2^{-i}; the tolerance of 0.25⋅2−i0.25 \cdot 2^{-i} shrinks by the second-order terms). The decisions therefore run on a 64-bit model of the remainder, refreshed every 52 indices from a short head, and never branch on the full-precision operand; about r/3r/3 digits are nonzero, against r/2r/2 for the unsigned greedy reduction.

The full-precision operands are held in radix 2562^{56} in the 64-bit lanes of vec4n vectors (see machine_vectors.h) in carry-save form: every addition of a table entry and every shift-and-add of the reconstruction is a lanewise vector operation, and the eight bits of headroom per lane admit about 60 operations between carry normalisations. The same scheme serves the logarithm (driving 1+x1 + x multiplicatively to 1), the arctangent (signed rotations) and the half-angle reconstruction. Measured on x86-64 with AVX2, this is 1.05 to 1.5 times faster than the limb version, and the cheaper reduction moves the optimal rr up (to 768 at several hundred limbs).

The reduction parameter rr trades the table and reduction work against the length of the remainder's series. Its default is tuned per function and size: per size at four to ten limbs, where the candidates are the table depths 7L−17L - 1, and from a ladder of values beyond (from 64 at a dozen limbs to 768).

Bit-burst evaluation#

At high precision the Taylor series of the reduced argument has many terms, and evaluating it with full-precision arithmetic costs O(N)O(\sqrt{N}) full products at best. Brent's bit-burst algorithm [Bre1976b] instead splits the argument into slices of increasing length,

t=t0+t1+⋯+tK,tk=bits 2k…2k+1 of t (roughly),t = t_0 + t_1 + \cdots + t_K, \qquad t_k = \text{bits } 2^k\ldots 2^{k+1} \text{ of } t \text{ (roughly)},

and computes exp⁡(t)=∏kexp⁡(tk)\exp(t) = \prod_k \exp(t_k), where each exp⁡(tk)\exp(t_k) is the sum of a series with a short rational argument, evaluated exactly by binary splitting (Binary splitting of hypergeometric series in mp_real). A slice of 2k2^k bits starting at bit 2k2^k needs about p/2kp/2^k terms whose integers grow by 2k2^k bits per term, so each slice costs O(M(p)log⁡p)O(M(p)\log p) and the whole O(M(p)log⁡2p)O(M(p)\log^2 p).

For the exponential the splitting computes T/(QBQE)=∑kxk/(k! BDk)T/(QB^{QE}) = \sum_k x^k/(k!\,B^{Dk}) for a slice xB−Dx B^{-D}. For the sine and cosine, both are obtained from one tree over the series in y=x2y = x^2:

sin⁡x′=x′ Q−B′Q,1−cos⁡x′=AQ,−B′Q=∑k≥1(−y)k(2k+1)!,−AQ=∑k≥1(2k+1)(−y)k(2k+1)!,\sin x' = x'\,\frac{Q - B'}{Q}, \qquad 1 - \cos x' = \frac{A}{Q}, \qquad -\frac{B'}{Q} = \sum_{k \ge 1}\frac{(-y)^k}{(2k+1)!}, \quad -\frac{A}{Q} = \sum_{k \ge 1}\frac{(2k+1)(-y)^k}{(2k+1)!},

using 1/(2k)!=(2k+1)/(2k+1)!1/(2k)! = (2k+1)/(2k+1)! so that both share the denominator Q=∏(2i)(2i+1)Q = \prod (2i)(2i+1); the second track costs two extra products per merge, half the work of a splitting of exp⁡(ix)\exp(ix) over all 2N2N terms. Past a term threshold the cosine track is dropped and recovered from the slice's denominator by one square root. The slice factors exp⁡(ixk)\exp(ix_k) are multiplied by mp_real_mul_complex.

These splittings have fixed midpoints, so every merge at a given level multiplies by the same power xsx^s of the argument; the powers are tabulated, and their fft_small transforms are computed once per tree for the entries used by at least two merges (Power tables with precomputed transforms).

_mp_real_exp_reduced and _mp_real_sin_cos_reduced choose between the series, one bit-burst step (the leading slice by binary splitting and the rest by the series at the reduced size) and the full cascade, by tuned thresholds that depend on the number of threads (a slice parallelises where the series does not). The slices of a cascade run as tasks on the available threads.

Table-free evaluation#

A single evaluation at huge precision cannot amortise tables. The table-free kernels halve the argument hh times, so that the reduced argument is below 2−r2^{-r} for a tuned depth rr, evaluate the reduced function by bit-burst, and undo the halving: the exponential by hh squarings, the sine and cosine by hh angle doublings on g=1−cos⁡g = 1 - \cos alone,

g(2θ)=2g(2−g),sin⁡x=2g−g2,g(2\theta) = 2g(2 - g), \qquad \sin x = \sqrt{2g - g^2},

with every intermediate a pure fraction and one square root at the end.

Proposition 3. Squaring a value with relative error ε\varepsilon gives relative error at most 2ε+ε22\varepsilon + \varepsilon^2; a doubling of gg with absolute error δ\delta, for g<1/2g < 1/2, gives an absolute error at most 4δ+2δ24\delta + 2\delta^2; and 2g−g2\sqrt{2g - g^2} divides an absolute error of gg by 2sin⁡x⋅2\sin x \cdot (to first order) 1/(1−g)1/(1 - g).

Proof. (y(1+ε))2=y2(1+2ε+ε2)(y(1 + \varepsilon))^2 = y^2(1 + 2\varepsilon + \varepsilon^2). For the doubling, ddg2g(2−g)=4−4g∈(2,4]\frac{d}{dg} 2g(2 - g) = 4 - 4g \in (2, 4] and the second derivative is −4-4. For the square root, ddg2g−g2=(1−g)/2g−g2=cos⁡x/sin⁡x\frac{d}{dg}\sqrt{2g - g^2} = (1 - g)/\sqrt{2g - g^2} = \cos x/\sin x, and cos⁡x≤1\cos x \le 1.

Hence hh squarings amplify the relative error by 2h2^h, and hh doublings followed by the square root amplify the absolute error by at most 22h/sin⁡x2^{2h}/\sin x; since any path that doubles at all has x≥2−z−1x \ge 2^{-z-1} for an argument with zz leading zero bits, h+log⁡2n+8h + \log_2 n + 8 resp. 2h+z+log⁡2n+82h + z + \log_2 n + 8 guard bits keep the amplified error below one output ulp, and the bound written is 128 ulps.

mp_real_exp_notab_squaring applies the same idea to balls, with ss ball squarings, and mp_real_exp_agm improves a starting value computed this way by one Newton–Taylor step on the AGM logarithm.

Diophantine reduction#

From 600 to 65536 limbs, the exponential and the trigonometric functions subtract integer combinations of logarithms of small primes (resp. arguments of Gaussian primes) and multiply by a rational (resp. Gaussian rational) number, which needs far cheaper tables than the bitwise reduction at these sizes.

AlgorithmMulti-prime argument reductionReduction of exp and sin/cos arguments by integer combinations of logarithms of primes (or arguments of Gaussian primes) found from precomputed integer relations, with the logarithms computed by Machin-type formulas whose terms are summed by Zuniga's fast series.

Newton–Taylor inversion#

Above 600 limbs the logarithm and the arctangent are computed from the forward functions. If tt is any real number,

−log⁡x=t−log⁡(1+w),w=xet−1,atan⁡x=t+atan⁡w,w=xcos⁡t−sin⁡txsin⁡t+cos⁡t,-\log x = t - \log(1 + w), \quad w = x e^t - 1, \qquad \operatorname{atan} x = t + \operatorname{atan} w, \quad w = \frac{x\cos t - \sin t}{x\sin t + \cos t},

exactly (the second for ∣atan⁡x−t∣<π/2|{\operatorname{atan} x - t}| < \pi/2). If tt is correct to p0p_0 bits, then ∣w∣<2−p0|w| < 2^{-p_0}, and p/p0p/p_0 terms of the Taylor series of log⁡(1+w)\log(1 + w) or atan⁡w\operatorname{atan} w give pp bits; since the kk-th term has kp0kp_0 leading zero bits, the series costs a fraction of one multiplication. The starting value is computed at p0≈p/(N+1)p_0 \approx p/(N + 1) bits (for the arctangent, whose series is in w2w^2, p/(2N)p/(2N)) by the bitwise kernel or recursively, so the whole costs one forward evaluation plus about a tenth of one. Everything around the forward function is ball arithmetic: the cancellation in ww, the forward function's error, the series and its tail are carried by the radii. This is a single Newton step of high order in the sense of [BZ2011].

The AGM logarithm#

The logarithm also has an O(M(n)log⁡n)O(M(n)\log n) algorithm, from the arithmetic-geometric mean [Sal1976] [Bre1976agm]. _mp_real_neglog_agm uses the formula of Sasaki and Kanada [SK1982],

log⁡1q=πagm⁡(θ2(q)2, θ3(q)2),0<q<1,\log\frac{1}{q} = \frac{\pi}{\operatorname{agm}(\theta_2(q)^2,\, \theta_3(q)^2)}, \qquad 0 < q < 1,

with θ2(q)=2q1/4∑k≥0qk(k+1)\theta_2(q) = 2q^{1/4}\sum_{k \ge 0} q^{k(k+1)} and θ3(q)=1+2∑k≥1qk2\theta_3(q) = 1 + 2\sum_{k \ge 1} q^{k^2}. For x∈[1/2,1)x \in [1/2, 1) it sets r=x2−er = x 2^{-e} and q=r4q = r^4, so that q1/4=rq^{1/4} = r needs no root:

−log⁡x=π/4agm⁡(4r2S22, θ32)−elog⁡2,S2=∑k≥0qk(k+1).-\log x = \frac{\pi/4}{\operatorname{agm}(4r^2 S_2^2,\, \theta_3^2)} - e\log 2, \qquad S_2 = \sum_{k \ge 0} q^{k(k+1)}.

The shift ee makes qq small enough that NN terms of the theta series suffice (e=⌈p/(4(N+1)2)⌉e = \lceil p/(4(N + 1)^2)\rceil); the merged exponents of the two series are ⌊j2/4⌋\lfloor j^2/4 \rfloor, consecutive ones differing by ⌊j/2⌋\lfloor j/2 \rfloor, so the series cost about one product per term. The first AGM step needs no square root, since θ22θ32=(2rS2θ3)2\theta_2^2\theta_3^2 = (2rS_2\theta_3)^2. The AGM itself runs about log⁡2e\log_2 e iterations in its slow phase and is finished by the series of mp_real_agm.

With warm caches the Newton–Taylor logarithm over the diophantine exponential is faster up to about 7⋅1057 \cdot 10^5 limbs; without tables, the AGM logarithm wins from about 20000 limbs, which is why mp_real_exp_agm uses it.

Sines of rational multiples of π#

The values cos⁡(πR/Q)\cos(\pi R/Q) are algebraic of degree at most QQ, and at high precision it is cheaper to refine one as a root of a polynomial than to evaluate the cosine.

Theorem 4 (Chebyshev step). Let φ∗=πR/Q∈(0,π/2)\varphi^* = \pi R/Q \in (0, \pi/2) in lowest terms, x∗=cos⁡φ∗x^* = \cos\varphi^*, ε=(−1)R\varepsilon = (-1)^R, and let x0=cos⁡φ0x_0 = \cos\varphi_0 with φ0=φ∗+δ\varphi_0 = \varphi^* + \delta, ∣Qδ∣<π/2|Q\delta| < \pi/2. Put C=TQ(x0)C = T_Q(x_0), A=x0TQ(x0)−TQ+1(x0)A = x_0 T_Q(x_0) - T_{Q+1}(x_0), a=εAa = \varepsilon A, y=1−C2y = 1 - C^2 and b=1/Qb = 1/Q. Then

x∗=x0+x0 G(y)+aQF(y),x^* = x_0 + x_0\, G(y) + \frac{a}{Q} F(y),
G(y)=2F1(−b2,b2;12;y)−1,F(y)=2F1(1−b2,1+b2;32;y).G(y) = {}_2F_1\bigl(-\tfrac b2, \tfrac b2; \tfrac12; y\bigr) - 1, \qquad F(y) = {}_2F_1\bigl(\tfrac{1-b}{2}, \tfrac{1+b}{2}; \tfrac32; y\bigr).

Proof. Since Tk(cos⁡φ)=cos⁡(kφ)T_k(\cos\varphi) = \cos(k\varphi), C=cos⁡(Qφ∗+Qδ)=εcos⁡(Qδ)C = \cos(Q\varphi^* + Q\delta) = \varepsilon\cos(Q\delta), and x0TQ(x0)−TQ+1(x0)=cos⁡φ0cos⁡(Qφ0)−cos⁡((Q+1)φ0)=sin⁡φ0sin⁡(Qφ0)x_0 T_Q(x_0) - T_{Q+1}(x_0) = \cos\varphi_0\cos(Q\varphi_0) - \cos((Q+1)\varphi_0) = \sin\varphi_0 \sin(Q\varphi_0), so a=s0σa = s_0\sigma with s0=sin⁡φ0s_0 = \sin\varphi_0 and σ=sin⁡(Qδ)\sigma = \sin(Q\delta), and y=σ2y = \sigma^2. Then x∗=cos⁡(φ0−δ)=x0cos⁡δ+s0sin⁡δx^* = \cos(\varphi_0 - \delta) = x_0\cos\delta + s_0\sin\delta, and with δ=basin⁡σ\delta = b\operatorname{asin}\sigma (valid on the principal branch, ∣Qδ∣<π/2|Q\delta| < \pi/2) the classical expansions cos⁡(basin⁡σ)=2F1(−b2,b2;12;σ2)\cos(b\operatorname{asin}\sigma) = {}_2F_1(-\frac b2, \frac b2; \frac12; \sigma^2) and sin⁡(basin⁡σ)=bσ 2F1(1−b2,1+b2;32;σ2)\sin(b\operatorname{asin}\sigma) = b\sigma\,{}_2F_1(\frac{1-b}2, \frac{1+b}2; \frac32; \sigma^2) give the claim, s0sin⁡δs_0\sin\delta becoming s0σ bF(y)=(a/Q)F(y)s_0\sigma\, b F(y) = (a/Q)F(y).

No division or square root enters: s0s_0 appears only through aa and yy. The pair (Tk(x0),Tk+1(x0))(T_k(x_0), T_{k+1}(x_0)) is computed by a Montgomery ladder on Vk=2TkV_k = 2T_k, V2k=Vk2−2V_{2k} = V_k^2 - 2, V2k+1=VkVk+1−V1V_{2k+1} = V_kV_{k+1} - V_1, one squaring and one product per bit of QQ. The coefficients of GG and FF decrease in magnitude from 1/(2Q2)1/(2Q^2) resp. 1, so for ∣y∣≤1/2|y| \le 1/2 the tails after yJy^J are below ∣y∣J/Q2|y|^J/Q^2 resp. 2∣y∣J2|y|^J; in y/(4Q2)y/(4Q^2) both have integer coefficients over common denominators, so the series cost a few products and one division by a word each. With x0x_0 correct to ee bits, σ≈Q2−e\sigma \approx Q2^{-e}, and summing to the target precision makes a step of any order rr from x0x_0 at about (p+(r−1)log⁡2Q)/r(p + (r-1)\log_2 Q)/r bits; the order used is 12. The recursion runs in ball arithmetic and checks the branch condition ∣Qδ∣<π/2|Q\delta| < \pi/2 from the rigorous radius of the previous level. The cost is O(M(n)log⁡Q)O(M(n)\log Q), against the O(M(n)log⁡2n)O(M(n)\log^2 n) of the general kernel; the iteration is used for denominators up to a bit length that grows with the precision (none below 48 limbs, 12 bits at 512 limbs, 48 at 65536 limbs, and all denominators beyond). Of cos⁡(πt/q)\cos(\pi t/q) and sin⁡(πt/q)=cos⁡(π(q−2t)/(2q))\sin(\pi t/q) = \cos(\pi(q - 2t)/(2q)) the one with the smaller denominator is iterated and the other is 1−x∗2\sqrt{1 - x^{*2}}.

Use in FLINT#

Referenced from#

References#

  • [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
  • [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
  • [Bre1976agm] R. P. Brent. Fast multiple-precision evaluation of elementary functions. Journal of the ACM 23:2 (1976), 242–251. https://doi.org/10.1145/321941.321944
  • [Bre1976b] R. P. Brent. The complexity of multiple-precision evaluation of elementary functions. In J. F. Traub (ed.), Analytic Computational Complexity, Academic Press, 1976, 151–176.
  • [Mul2016] J.-M. Muller. Elementary Functions: Algorithms and Implementation, third edition. Birkhäuser, 2016. https://doi.org/10.1007/978-1-4899-7983-4
  • [BZ2011] R. P. Brent and P. Zimmermann, Modern Computer Arithmetic, Cambridge University Press (2011), http://www.loria.fr/~zimmerma/mca/pub226.html
  • [ZZ2020] D. Zeilberger and W. Zudilin. The irrationality measure of π is at most 7.103205334137... Moscow Journal of Combinatorics and Number Theory 9:4 (2020), 407–419. https://doi.org/10.2140/moscow.2020.9.407
  • [Smi1989] D. M. Smith. Efficient multiple-precision evaluation of elementary functions. Mathematics of Computation 52 (1989), 131–134. https://doi.org/10.1090/S0025-5718-1989-0971406-0
  • [PS1973] M. S. Paterson and L. J. Stockmeyer, "On the number of nonscalar multiplications necessary to evaluate polynomials", SIAM J. Comput (1973)
  • [Tan1989] P. T. P. Tang. Table-driven implementation of the exponential function in IEEE floating-point arithmetic. ACM Transactions on Mathematical Software 15:2 (1989), 144–157. https://doi.org/10.1145/63522.214389
  • [BKM1994] J.-C. Bajard, S. Kla and J.-M. Muller. BKM: a new hardware algorithm for complex elementary functions. IEEE Transactions on Computers 43:8 (1994), 955–963. https://doi.org/10.1109/12.295857
  • [Sal1976] E. Salamin. Computation of π using arithmetic-geometric mean. Mathematics of Computation 30:135 (1976), 565–570. https://doi.org/10.2307/2005327
  • [SK1982] T. Sasaki and Y. Kanada. Practically fast multiple-precision evaluation of log(x). Journal of Information Processing 5:4 (1982), 247–250.
Cite this page

The FLINT team, “Elementary functions in mp_real,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/floating-point/elementary-functions.html (generated 2026-11-02).