5. Numerical algorithms II: elementary functions


5.1 Powers

There are two computational tasks: to compute the power x^n where n is an integer (but x may be a real or a complex number), and compute x^y for arbitrary (real or complex) x, y. We assume that x, y, n are "big" numbers with P significant digits.

We also assume that the power is positive, or else we need to perform an additional division to obtain x^(-y)=1/x^y.

If x!=0 is known to a relative precision epsilon, then x^y has the relative precision epsilon*y. This means a loss of precision if Abs(y)>1 and an improvement of precision otherwise.


Integer powers

Integer powers x^n with integer n are computed by a fast algorithm of "repeated squaring". This algorithm is well known (see, for example, the famous book, The art of computer programming [Knuth 1973]).

The algorithm is based on the following trick: if n is even, say n=2*k, then x^n=x^k^2; and if n is odd, n=2*k+1, then x^n=x*x^k^2. Thus we can reduce the calculation of x^n to the calculation of x^k with k<=n/2, using at most two long multiplications. This reduction is one step of the algorithm; at each step n is reduced to at most half. This algorithm stops when n becomes 1, which happens after m steps where m is the number of bits in n. So the total number of long multiplications is at most 2*m=(2*Ln(n))/Ln(2). More precisely, it is equal to m plus the number of nonzero bits in the binary representation of n. On the average, we shall have 3/2*Ln(n)/Ln(2) long multiplications. The computational cost of the algorithm is therefore O(M(P)*Ln(n)). This should be compared with e.g. the cost of the best method for Ln(x) which is O(P*M(P)).

The outlined procedure is most easily implemented using recursive calls. The depth of recursion is of order Ln(n) and should be manageable for most real-life applications. The Yacas code would look like this:
10# power(_x,1)<--x;
20# power(_x,n_IsEven)<-- power(x,n>>1)^2;
30# power(_x,n_IsOdd)<--x*power(x,n>>1)^2;
The function power(m,n) calculates the result of m^n for n>0, m>0, integer n and integer m. The bit shifts and the check for an odd number are very fast operations if the internal representation of big numbers uses base 2.

If we wanted to avoid recursion with its overhead, we would have to obtain the bits of the number n in reverse order. This is possible but is somewhat cumbersome unless we store the bits in an array.

It is easier to implement the non-recursive version of the squaring algorithm in a slightly different form. Suppose we obtain the bits b[i] of the number n in the usual order, so that n=b[0]+2*b[1]+...+b[m]*2^m. Then we can express the power x^n as

x^n=x^b[0]*x^2^b[1]*...*x^2^m^b[m].

In other words, we evaluate x^2, x^4, ... by repeated squaring, select those x^2^k for which the k-th bit b[k] of the number n is nonzero, and multiply all selected powers together.

In the Yacas script form, the algorithm looks like this:

power(x_IsPositiveInteger,n_IsPositiveInteger)<--
[
  Local(result, p);
  result:=1;
  p := x;
  While(n != 0)
  [ // at step k, p = x^(2^k)
    if (IsOdd(n))
      result := result*p;
    p := p*p;
    n := n>>1;
  ];
  result;
];

The same algorithm can be used to obtain a power of an integer modulo another integer, Mod(x^n,M), if we replace the multiplication p*p by a modular multiplication, such as p:=Mod(p*p,M). Since the remainder modulo m would be computed at each step, the results do not grow beyond M. This allows to efficiently compute even extremely large modular powers of integers.

Matrix multiplication, or, more generally, multiplication in any given ring, can be substituted into the algorithm instead of the normal multiplication. The function IntPowerNum encapsulates the computation of the n-th power of an expression using the binary squaring algorithm.

The squaring algorithm can be improved a little bit if we are willing to use recursion or to obtain the bits of n in the reverse order. (This was suggested in the exercise 4.21 in the book [von zur Gathen et al. 1999].) Let us represent the power n in base 4 instead of base 2. If q[k] are the digits of n in base 4, then we can express

x^n=x^q[0]*x^4^q[1]*...*x^4^m^q[m].

We shall compute this expression from right to left: first we compute x^q[m]. This is a small power because q[m] is a digit in base 4, an integer between 0 and 3. Then we raise it to the 4th power and multiply by x^q[m-1]. We repeat this process until we reach the 0th digit of n. At each step we would need to multiply at most three times. Since each of the q[k] is between 0 and 3, we would need to precompute x^2 and x^3 which requires one extra multiplication ( x^2 would be computed anyway). Therefore the total number of long multiplications is in the worst case 3*Ln(n)/Ln(4)+1. This is about 25% better than the previous worst-case result, 2*Ln(n)/Ln(2). However, the average-case improvement is only about 8% because the average number of multiplications in the base-4 method is 11/4*Ln(n)/Ln(4).

We might then use the base 8 instead of 4 and obtain a further small improvement. (Using bases other than powers of 2 is less efficient.) But the small gain in speed probably does not justify the increased complexity of the algorithm.


Real powers

The squaring algorithm can be used to obtain integer powers x^n in any ring---as long as n is an integer, x can be anything from a complex number to a matrix. But for a general real number n, there is no such trick and the power x^n has to be computed through the logarithm and the exponential function, x^n=Exp(n*Ln(x)). (This also covers the case when x is negative and the result is a complex number.)

An exceptional case is when n is a rational number with a very small numerator and denominator, for example, n=2/3. In this case it is faster to take the square of the cubic root of x. (See the section on the computation of roots below.) Then the case of negative x should be handled separately. This speedup is not implemented in Yacas.

Note that the relative precision changes when taking powers. If x is known to relative precision epsilon, i.e. x represents a real number that could be x*(1+epsilon), then x^2<=>x*(1+2*epsilon) has relative precision 2*epsilon, while Sqrt(x) has relative precision epsilon/2. So if we square a number x, we lose one significant bit of x, and when we take a square root of x, we gain one significant bit.


5.2 Roots

Computation of roots r=x^(1/n) is efficient when n is a small integer. The basic approach is to numerically solve the equation r^n=x.

Note that the relative precision is improved after taking a root with n>1.


Method 1: bisection

The square root can be computed by using the bisection method, which works well for integers (if only the integer part of the square root is needed). The algorithm is described in [Johnson 1987]. The general approach is to scan each bit of the input number and to see if a certain bit should be set in the resulting integer. The time is linear in the number of decimals, or logarithmic in the input number. The method is very similar in approach to the repeated squaring method described above for raising numbers to a power.

For integer N, the following steps are performed:

The intermediate results, u^2, v^2 and 2*u*v can be maintained easily too, due to the nature of the numbers involved ( v having only one bit set, and it being known which bit that is).

For floating point numbers, first the required number of decimals p after the decimal point is determined. Then the input number N is multiplied by a power of 10 until it has 2*p decimal. Then the integer square root calculation is performed, and the resulting number has p digits of precision.

Below is some Yacas script code to perform the calculation for integers.

//sqrt(1) = 1, sqrt(0) = 0
10 # BisectSqrt(0) <-- 0;
10 # BisectSqrt(1) <-- 1;

20 # BisectSqrt(N_IsPositiveInteger) <--
[
  Local(l2,u,v,u2,v2,uv2,n);

  // Find highest set bit, l2
  u  := N;
  l2 := 0;
  While (u!=0)
  [
    u:=u>>1;
    l2++;
  ];
  l2--;

  // 1<<(l2/2) now would be a good under estimate 
  // for the square root. 1<<(l2/2) is definitely 
  // set in the result. Also it is the highest
  // set bit.
  l2 := l2>>1;

  // initialize u and u2 (u2==u^2).
  u  := 1 << l2;
  u2 := u << l2;

  // Now for each lower bit:
  While( l2 != 0 )
  [
	l2--;
     // Get that bit in v, and v2 == v^2.
      v  := 1<<l2;
      v2 := v<<l2;

      // uv2 == 2*u*v, where 2==1<<1, and 
      // v==1<<l2, thus 2*u*v == 
      // (1<<1)*u*(1<<l2) == u<<(l2+1)
      uv2 := u<<(l2 + 1);

      // n = (u+v)^2  = u^2 + 2*u*v + v^2 
      //   = u2+uv2+v2
      n := u2 + uv2 + v2;

      // if n (possible new best estimate for 
      // sqrt(N)^2 is smaller than N, then the 
      // bit l2 is set in the result, and 
      // add v to u.
      if( n <= N )
      [
        u  := u+v;  // u <- u+v
        u2 := n;    // u^2 <- u^2 + 2*u*v + v^2
      ];
      l2--;
    ];
    u; // return result, accumulated in u.
];
BisectSqrt(N) computes the integer part of Sqrt(N) for integer N. (If we need to obtain more digits, we should first multiply N by a suitable power of 2.) The algorithm works for floats as well as for integers.

The bisection algorithm uses only additions and bit shifting operations. Suppose the integer N has P decimal digits, then it has n=P*Ln(10)/Ln(2) bits. For each bit, the number of additions is about 4. Since the cost of an addition is linear in the number of bits, the total complexity of the bisection method is roughly 4*n^2=O(P^2).


Method 2: Newton's iteration

An efficient method for computing the square root is found by using Newton's iteration for the equation r^2-x=0. The initial value of r can be obtained by bit counting and shifting, as in the bisection method. The iteration formula is

r'=r/2+x/(2*r).

The convergence is quadratic, so we double the number of correct digits at each step. Therefore, if the initial guess is accurate to one bit, the number of steps n needed to obtain P decimal digits is

n=Ln(P*Ln(10)/Ln(2))/Ln(2)=O(Ln(P)).

We need to perform one long division at each step; a long division costs O(M(P)). Therefore the total complexity of this algorithm is O(M(P)*Ln(P)). This is better than the O(P^2) algorithm if the cost of multiplication is below O(P^2).

In most implementations of arbitrary-precision arithmetic, the time to perform a long division is several times that of a long multiplication. Therefore it makes sense to use a method that avoids divisions. One variant of Newton's method is to solve the equation 1/r^2=x. The solution of this equation r=1/Sqrt(x) is the limit of the iteration

r'=r+r*(1-r^2*x)/2

that does not require any divisions (but instead requires three multiplications). The final multiplication r*x completes the calculation of the square root.

As usual with Newton's method, all errors are automatically corrected, so the working precision can be gradually increased until the last iteration. The full precision of P digits is used only at the last iteration; the last-but-one iteration uses P/2 digits and so on.

An optimization trick is to combine the multiplication by x with the last iteration. Then computations can be organized in a special way to avoid the last full-precision multiplication. (This is described in [Karp et al. 1997] where the same trick is also applied to Newton's iteration for division.)

The idea is the following: let r be the P-digit approximation to 1/Sqrt(x) at the beginning of the last iteration. (In this notation, 2*P is the precision of the final result, so x is also known to about 2*P digits.) The unmodified procedure would have run as follows:

r'=r+r*(1-r^2*x)/2,

s=x*r'.

Then s would have been the final result, Sqrt(x) to 2*P digits. We would need one multiplication M(P) with 2*P-digit result to compute r^2, then one M(2*P) to compute r^2*x (the product of a P-digit r^2 and a 2*P-digit x). Then we subtract this from 1 and lose P digits since r was already a P-digit approximation to 1/Sqrt(x). The value y:=1-r^2*x is of order 10^(-P) and has P significant digits. So the third multiplication, r*y, is only M(P). The fourth multiplication s*x is again M(2*P). The total cost is then 2*M(P)+2*M(2*P).

Now consider Newton's iteration for s<=>Sqrt(x),

s'=s+1/s*(1-s^2*x)/2.

The only reason we are trying to avoid it is the division by s. However, after all but the last iterations for r we already have a P-digit approximation for 1/s, which is r. Therefore we can simply define s=r*x and perform the last iteration for s, taking 1/s<=>r. This is slightly inexact, but the error is higher-order than the precision of the final result, because Newton's method erases any accumulated errors. So this will give us 2*P digits of s without divisions, and lower the total computational cost.

Consider the cost of the last iteration of this combined method. First, we compute s=x*r, but since we only need P correct digits of s, we can use only P digits of x, so this costs us M(P). Then we compute s^2*x which, as before, costs M(P)+M(2*P), and then we compute r*(1-s^2*x) which costs only M(P). The total cost is therefore 3*M(P)+M(2*P), so we have traded one multiplication with 2*P digits for one multiplication with P digits. Since the time of the last iteration dominates the total computing time, this is a significant cost savings. For example, if the multiplication is quadratic, M(P)=O(P^2), then this saves about 30% of total execution time; for linear multiplication, the savings is about 16.67%.

These optimizations do not change the asymptotic complexity of the method, although they do reduce the constant in front of O().


Method 3: argument reduction and interpolation

Before using the bisection or Newton's method, we might apply some argument reduction to speed up the convergence of the iterations and to simplify finding the first approximation.

Suppose we need to find Sqrt(x). Choose an integer n such that 1/4<x':=4^(-n)*x<=1. The value of n is easily found from bit counting: if b is the bit count of x, then

n=Floor((b+1)/2).

We find

Sqrt(x)=2^n*Sqrt(x').

The precision of x' is the same as that of x since 2^n is an exact number.

To compute Sqrt(x'), we use Newton's method with the initial value x'[0] obtained by interpolation of the function Sqrt(x) on the interval [1/4, 1]. A suitable interpolation function might be taken as simply (2*x+1)/3 or more precisely

Sqrt(x)<=>1/90*(-28*x^2+95*x+23).

By using a particular interpolation function, we can guarantee a certain number of precise bits at every iteration.

This may save a few iterations, at the small expense of evaluating the interpolation function once at the beginning. However, in computing with high precision the initial iterations are very fast and this argument reduction does not give a significant speed gain. But the gain may be important at low precisions, and this technique is sometimes used in microprocessors.


Method 4: Halley's iteration

A separate function IntNthRoot is provided to compute the integer part of n^(1/s) for integer n and s. For a given s, it evaluates the integer part of n^(1/s) using only integer arithmetic with integers of size n^(1+1/s). This can be done by Halley's iteration method, solving the equation x^s=n. For this function, the Halley iteration sequence is monotonic. The initial guess is x[0]=2^(b(n)/s) where b(n) is the number of bits in n obtained by bit counting or using the integer logarithm function. It is clear that the initial guess is accurate to within a factor of 2. Since the relative error is squared at every iteration, we need as many iteration steps as bits in n^(1/s).

Since we only need the integer part of the root, it is enough to use integer division in the Halley iteration. The sequence x[k] will monotonically approximate the number n^(1/s) from below if we start from an initial guess that is less than the exact value. (We start from below so that we have to deal with smaller integers rather than with larger integers.) If n=p^s, then after enough iterations the floating-point value of x[k] would be slightly less than p; our value is the integer part of x[k]. Therefore, at each step we check whether 1+x[k] is a solution of x^s=n, in which case we are done; and we also check whether (1+x[k])^s>n, in which case the integer part of the root is x[k]. To speed up the Halley iteration in the worst case when s^s>n, it is combined with bisection. The root bracket interval x1<x<x2 is maintained and the next iteration x[k+1] is assigned to the midpoint of the interval if Halley's formula does not give sufficiently rapid convergence. The initial root bracket interval can be taken as x[0], 2*x[0].

If s is very large ( s^s>n), the convergence of both Newton's and Halley's iterations is almost linear until the final few iterations. Therefore it is faster to evaluate the floating-point power for large b using the exponential and the logarithm.


Method 5: higher-order iterations

A higher-order generalization of Newton's iteration for inverse square root 1/Sqrt(x) is:

r'=r+r/2*(1-r^2*x)+3*r/8*(1-r^2*x)^2+...

The more terms of the series we add, the higher is the convergence rate. This is the Taylor series for (1-y)^(-1/2) where y:=1-r^2*x. If we take the terms up to y^(n-1), the precision at the next iteration will be multiplied by n. The usual second-order iteration (our "method 2") corresponds to n=2.

The trick of combining the last iteration with the final multiplication by x can be also used with all higher-order schemes.

Consider the cost of one iteration of n-th order. Let the initial precision of r be P; then the final precision is k*P and we use up to n*P digits of x. First we compute y:=1-r^2*x to P*(n-1) digits, this costs M(P) for r^2 and then M(P*n) for r^2*x. The value of y is of order 10^(-P) and it has P*(n-1) digits, so we only need to use that many digits to multiply it by r, and r*y now costs us M(P*(n-1)). To compute y^k (here 2<=k<=n-1), we need M(P*(n-k)) digits of y; since we need all consecutive powers of y, it is best to compute the powers one after another, lowering the precision on the way. The cost of computing r*y^k*y after having computed r*y^k is therefore M(P*(n-k-1)). The total cost of the iteration comes to

2*M(P)+M(2*P)+...+M((n-1)*P)+M(n*P).

From the general considerations in the previous chapter (see the section on Newton's method) it follows that the optimal order is n=2 and that higher-order schemes are slower in this case.


Which method to use

The bisection method (1) for square roots is probably the fastest for small integers or low-precision floats. Argument reduction and/or interpolation (3) can be used to simplify the iterative algorithm or to make it more robust.

Newton's method (2) is best for all other cases: large precision and/or roots other than square roots.


5.3 Logarithm

The basic computational task is to obtain the logarithm of a real number. However, sometimes only the integer part of the logarithm is needed and the logarithm is taken with respect to an integer base. For example, we might need to evaluate the integer part of Ln(n)/Ln(2) where n is a large integer, to find how many bits are needed to hold n. Computing this "integer logarithm" is a much easier task than computing the logarithm in floating-point.

Logarithms of complex numbers can be reduced to elementary functions of real numbers, for example:

Ln(a+I*b)=1/2*Ln(a^2+b^2)+I*ArcTan(b/a).

For a negative real number x<0, we have

Ln(x)=Ln(Abs(x))+I*Pi.

This assumes, of course, an appropriate branch cut for the complex logarithm. A natural choice is to cut along the negative real semiaxis, Im(z)=0, Re(z)<0.


Integer logarithm

The "integer logarithm", defined as the integer part of Ln(x)/Ln(b), where x and b are integers, is computed using a special routine IntLog(x,b) with purely integer math. When both arguments are integers and only the integer part of the logarithm is needed, the integer logarithm is much faster than evaluating the full floating-point logarithm and truncating the result.

The basic algorithm consists of (integer-) dividing x by b repeatedly until x becomes 0 and counting the necessary number of divisions. If x has P digits and b and P are small numbers, then division is linear in P and the total number of divisions is O(P). Therefore this algorithm costs O(P^2) operations.

A speed-up for large x is achieved by first comparing x with b, then with b^2, b^4, etc., without performing any divisions. We perform n such steps until the factor b^2^n is larger than x. At this point, x is divided by the previous power of b and the remaining value is iteratively compared with and divided by successively smaller powers of b. The number of squarings needed to compute b^2^n is logarithmic in P. However, the last few of these multiplications are long multiplications with numbers of length P/4, P/2, P digits. These multiplications take the time O(M(P)). Then we need to perform another long division and a series of progressively shorter divisions. The total cost is still O(M(P)). For large P, the cost of multiplication M(P) is less than O(P^2) and therefore this method is preferable.

There is one special case, the binary (base 2) logarithm. Since the internal representation of floating-point numbers is usually in binary, the integer part of the binary logarithm can be usually implemented as a constant-time operation.


Real logarithms

There are many methods to compute the logarithm of a real number. Here we collect these methods and analyze them.

The logarithm satisfies Ln(1/x)= -Ln(x). Therefore we need to consider only x>1, or alternatively, only 0<x<1.

Note that the relative precision for x translates into absolute precision for Ln(x). This is because Ln(x*(1+epsilon))<=>Ln(x)+epsilon for small epsilon. Therefore, the relative precision of the result is at best epsilon/Ln(x). So to obtain P decimal digits of Ln(x), we need to know P-Ln(Abs(Ln(x)))/Ln(10) digits of x. This is better than the relative precision of x if x>e but worse if x<=>1.


Method 1: Taylor series

The logarithm function Ln(x) for general (real or complex) x such that Abs(x-1)<1 can be computed using the Taylor series,

Ln(1+z)=z-z^2/2+z^3/3-...

The series converges quite slowly unless Abs(x) is small. For real x<1, the series is monotonic,

Ln(1-z)= -z-z^2/2-z^3/3-...,

and the round-off error is somewhat smaller in that case (but not very much smaller, because the Taylor series method is normally used only for very small x).

If x>1, then we can compute -Ln(1/x) instead of Ln(x). However, the series converges very slowly if x is close to 0 or to 2.

Here is an estimate of the necessary number of terms to achieve a (relative) precision of P decimal digits when computing Ln(1+x) for small real x. Suppose that x is of order 10^(-N), where N>=1. The error after keeping n terms is not greater than the first discarded term, x^(n+1)/(n+1). The magnitude of the sum is approximately x, so the relative error is x^n/(n+1) and this should be smaller than 10^(-P). We obtain a sufficient condition n>P/N.

All calculations need to be performed with P digits of precision. The "rectangular" scheme for evaluating n terms of the Taylor series needs about 2*Sqrt(n) long multiplications. Therefore the cost of this calculation is 2*Sqrt(P/N)*M(P).

When P is very large (so that a fast multiplication can be used) and x is a small rational number, then the binary splitting technique can be used to compute the Taylor series. In this case the cost is O(M(P)*Ln(P)).

Note that we need to know P+N digits of 1+x to be able to extract P digits of Ln(1+x). The N extra digits will be lost when we subtract 1 from 1+x.


Method 2: square roots + Taylor series

The method of the Taylor series allows to compute Ln(x) efficiently when x-1=10^(-N) is very close to 1 (i.e. for large N). For other values of x the series converges very slowly. We can transform the argument to improve the performance of the Taylor series.

One way is to take several square roots, reducing x to x^2^(-k) until x becomes close to 1. Then we can compute Ln(x^2^(-k)) using the Taylor series and use the identity Ln(x)=2^k*Ln(x^2^(-k)).

The number of times to take the square root can be chosen to minimize the total computational cost. Each square root operation takes the time equivalent to a fixed number c of long multiplications. (According to the estimate of [Brent 1975], c<=>13/2.) Suppose x is initially of order 10^L where L>0. Then we can take the square root k[1] times and reduce x to about 1.33. Here we can take k[1]<=>Ln(L)/Ln(2)+3. After that, we can take the square root k[2] times and reduce x to 1+10^(-N) with N>=1. For this we need k[2]<=>1+N*Ln(10)/Ln(2) square roots. The cost of all square roots is c*(k[1]+k[2]) long multiplications. Now we can use the Taylor series and obtain Ln(x^2^(-k[1]-k[2])) in 2*Sqrt(P/N) multiplications. We can choose N to minimize the total cost for a given L.


Method 3: inverse exponential

The method is to solve the equation Exp(x)-a=0 to find x=Ln(a). We can use either the quadratically convergent Newton iteration,

x'=x-1+a/Exp(x),

or the cubically convergent Halley iteration,

x'=x-2*(Exp(x)-a)/(Exp(x)+a).

Each iteration requires one evaluation of Exp(x) and one long division. Newton's iteration can be rewritten through Exp(-x) but this does not really avoid a long division: Exp(-x) for positive x is usually computed as 1/Exp(x) because other methods are much less efficient. Therefore the Halley iteration is preferable.

The initial value for x can be found by bit counting on the number a. If m is the "bit count" of a, i.e. m is an integer such that 1/2<=a*2^(-m)<1, then the first approximation to Ln(a) is m*Ln(2). (Here we can use a very rough approximation to Ln(2), for example, 2/3.)

The initial value found in this fashion will be correct to about one bit. The number of digits triples at each Halley iteration, so the result will have about 3*k correct bits after k iterations (this disregards round-off error). Therefore the required number of iterations for P decimal digits is 1/Ln(3)*Ln(P*Ln(2)/Ln(10)).

This method is currently faster than other methods (with internal math) and so it is implemented in the routine Internal'LnNum.

This method can be generalized to higher orders. Let y:=1-a*Exp(-x[0]), where x[0] is a good approximation to Ln(a) so y is small. Then Ln(a)=x[0]+Ln(1-y) and we can expand in y to obtain

Ln(a)=x[0]-y-y^2/2-y^3/3-...

By truncating this sum after k-th term we obtain a ( k-1)-th order method that multiplies the number of correct digits by k+1 after each iteration.

The optimal number of terms to take depends on the speed of the implementation of Exp(x).


Method 4: AGM

A fast algorithm based on the AGM sequence was given by Salamin (see [Brent 1975]). The formula is based on an asymptotic relation,

Ln(x)=Pi*x*(1+4*x^(-2)*(1-1/Ln(x))+O(x^(-4)))/(2*AGM(x,4)).

If x is large enough, the numerator can be replaced by 1. "Large enough" for a desired precision of P decimal digits means that 4*x^(-2)<10^(-P). The AGM algorithm gives P digits only for such large values of x, unlike the Taylor series which is only good for x close to 1.

The required number of AGM iterations is approximately 2*Ln(P)/Ln(2). For smaller values of x (but x>1), one can either raise x to a large integer power r and then compute 1/r*Ln(x^r) (this is quick only if x is itself an integer or a rational), or multiply x by a large integer power of 2 and compute Ln(2^s*x)-s*Ln(2) (this is better for floating-point x). Here the required powers are

r=Ln(10^P*4)/(2*Ln(x)),

s=P*Ln(10)/(2*Ln(2))+1-Ln(x)/Ln(2).

The values of these parameters can be found quickly by using the integer logarithm procedure IntLog, while constant values such as Ln(10)/Ln(2) can be simply approximated by rational numbers because r and s do not need to be very precise (but they do need to be large enough). For the second calculation, Ln(2^s*x)-s*Ln(2), we must precompute Ln(2) to the same precision of P digits. Also, the subtraction of a large number s*Ln(2) leads to a certain loss of precision, namely, about Ln(s)/Ln(10) decimal digits are lost, therefore the operating precision must be increased by this number of digits. (The quantity Ln(s)/Ln(10) is computed, of course, by the integer logarithm procedure.)

If x<1, then (-Ln(1/x)) is computed.

Finally, there is a special case when x is very close to 1, where the Taylor series converges quickly but the AGM algorithm requires to multiply x by a large power of 2 and then subtract two almost equal numbers, leading to a great waste of precision. Suppose 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because the exponential Exp(-f) is taken at a rational arguments f and can be computed using the binary splitting technique. (Toward the end of the loop, the number of significant digits of f grows, but the number of digits we need to obtain is decreased. At the last iteration, f contains about half of the digits of x but computing Exp(-f) requires only one term of the Taylor series.) Therefore the total cost is O(M(P)*Ln(P)^2).

Essentially the same method can be used to evaluate a complex logarithm, Ln(a+I*b). It is slower but the asymptotic cost is the same.


Method 8: continued fraction

There is a continued fraction representation of the logarithm:

Ln(1+x)=x/(1+x/(2+x/(3+(4*x)/(4+(4*x)/(5+(9*x)/(6+... 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because the exponential Exp(-f) is taken at a rational arguments f and can be computed using the binary splitting technique. (Toward the end of the loop, the number of significant digits of f grows, but the number of digits we need to obtain is decreased. At the last iteration, f contains about half of the digits of x but computing Exp(-f) requires only one term of the Taylor series.) Therefore the total cost is O(M(P)*Ln(P)^2).

Essentially the same method can be used to evaluate a complex logarithm, Ln(a+I*b). It is slower but the asymptotic cost is the same.


Method 8: continued fraction

There is a continued fraction representation of the logarithm:

Ln(1+x)=x/(1+x/(2+x/(3+(4*x)/(4+(4*x)/(5+(9*x)/(6+... 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because the exponential Exp(-f) is taken at a rational arguments f and can be computed using the binary splitting technique. (Toward the end of the loop, the number of significant digits of f grows, but the number of digits we need to obtain is decreased. At the last iteration, f contains about half of the digits of x but computing Exp(-f) requires only one term of the Taylor series.) Therefore the total cost is O(M(P)*Ln(P)^2).

Essentially the same method can be used to evaluate a complex logarithm, Ln(a+I*b). It is slower but the asymptotic cost is the same.


Method 8: continued fraction

There is a continued fraction representation of the logarithm:

Ln(1+x)=x/(1+x/(2+x/(3+(4*x)/(4+(4*x)/(5+(9*x)/(6+... 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

  • Separate the first
  • k significant digits of z:

    f=2^(-2*k)*Floor(2^(2*k)*z).

    Now f is a good approximation for Ln(1+z).
  • Compute
  • Exp(-f) using the binary splitting technique (f is a rational number with the denominator 2^(2*k) and numerator at most 2^k). It is in fact sufficient to compute 1-Exp(-f) which does not need all digits.
  • Set
  • y=y+f and z=(1+z)*Exp(-f)-1.

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because the exponential Exp(-f) is taken at a rational arguments f and can be computed using the binary splitting technique. (Toward the end of the loop, the number of significant digits of f grows, but the number of digits we need to obtain is decreased. At the last iteration, f contains about half of the digits of x but computing Exp(-f) requires only one term of the Taylor series.) Therefore the total cost is O(M(P)*Ln(P)^2).

Essentially the same method can be used to evaluate a complex logarithm, Ln(a+I*b). It is slower but the asymptotic cost is the same.


Method 8: continued fraction

There is a continued fraction representation of the logarithm:

Ln(1+x)=x/(1+x/(2+x/(3+(4*x)/(4+(4*x)/(5+(9*x)/(6+... 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

  • Separate the first
  • k significant digits of z:

    f=2^(-2*k)*Floor(2^(2*k)*z).

    Now f is a good approximation for Ln(1+z).
  • Compute
  • Exp(-f) using the binary splitting technique (f is a rational number with the denominator 2^(2*k) and numerator at most 2^k). It is in fact sufficient to compute 1-Exp(-f) which does not need all digits.
  • Set
  • y=y+f and z=(1+z)*Exp(-f)-1.

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because the exponential Exp(-f) is taken at a rational arguments f and can be computed using the binary splitting technique. (Toward the end of the loop, the number of significant digits of f grows, but the number of digits we need to obtain is decreased. At the last iteration, f contains about half of the digits of x but computing Exp(-f) requires only one term of the Taylor series.) Therefore the total cost is O(M(P)*Ln(P)^2).

Essentially the same method can be used to evaluate a complex logarithm, Ln(a+I*b). It is slower but the asymptotic cost is the same.


Method 8: continued fraction

There is a continued fraction representation of the logarithm:

Ln(1+x)=x/(1+x/(2+x/(3+(4*x)/(4+(4*x)/(5+(9*x)/(6+... 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

  • Separate the first
  • k significant digits of z:

    f=2^(-2*k)*Floor(2^(2*k)*z).

    Now f is a good approximation for Ln(1+z).
  • Compute
  • Exp(-f) using the binary splitting technique (f is a rational number with the denominator 2^(2*k) and numerator at most 2^k). It is in fact sufficient to compute 1-Exp(-f) which does not need all digits.
  • Set
  • y=y+f and z=(1+z)*Exp(-f)-1.

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because the exponential Exp(-f) is taken at a rational arguments f and can be computed using the binary splitting technique. (Toward the end of the loop, the number of significant digits of f grows, but the number of digits we need to obtain is decreased. At the last iteration, f contains about half of the digits of x but computing Exp(-f) requires only one term of the Taylor series.) Therefore the total cost is O(M(P)*Ln(P)^2).

Essentially the same method can be used to evaluate a complex logarithm, Ln(a+I*b). It is slower but the asymptotic cost is the same.


Method 8: continued fraction

There is a continued fraction representation of the logarithm:

Ln(1+x)=x/(1+x/(2+x/(3+(4*x)/(4+(4*x)/(5+(9*x)/(6+... 1<x<1+10^(-M), where M is large (say of order P). The Taylor series for Ln(1+epsilon) needs about N= -P*Ln(10)/Ln(epsilon)=P/M terms. If we evaluate the Taylor series using the rectangular scheme, we need 2*Sqrt(N) multiplications and Sqrt(N) units of storage. On the other hand, the main slow operation for the AGM sequence is the geometric mean Sqrt(a*b). If Sqrt(a*b) takes an equivalent of c multiplications (Brent's estimate is c=13/2 but it may be more in practice), then the AGM sequence requires 2*c*Ln(P)/Ln(2) multiplications. Therefore the Taylor series method is more efficient for

M>1/c^2*P*(Ln(2)/Ln(P))^2.

In this case it requires at most c*Ln(P)/Ln(2) units of storage and 2*c*Ln(P)/Ln(2) multiplications.

For larger x>1+10^(-M), the AGM method is more efficient. It is necessary to increase the working precision to P+M*Ln(2)/Ln(10) but this does not decrease the asymptotic speed of the algorithm. To compute Ln(x) with P digits of precision for any x, only O(Ln(P)) long multiplications are required.


Method 5: argument reduction + Taylor series

Here is a straightforward method that reduces Ln(x) for large x>2 to Ln(1+delta) with a small delta; now the logarithm can be quickly computed using the Taylor series.

The simplest version is this: for integer m, we have the identity Ln(x)=m+Ln(x*e^(-m)). Assuming that e:=Exp(1) is precomputed, we can find the smallest integer m for which x<=e^m by computing the integer powers of e and comparing with x. (If x is large, we do not really have to go through all integer m: instead we can estimate m by bit counting on x and start from e^m.) Once we found m, we can use the Taylor series on 1-delta:=x*e^(-m) since we have found the smallest possible m, so 0<=delta<1-1/e.

A refinement of this method requires to precompute b=Exp(2^(-k)) for some fixed integer k>=1. (This can be done efficiently using the squaring trick for the exponentials.) First we find the smallest power m of b which is above x. To do this, we compute successive powers of b and find the first integer m such that x<=b^m=Exp(m*2^(-k)). When we find such m, we define 1-delta:=x*b^(-m) and then delta will be small, because 0<delta<1-1/b<=>2^(-k) (the latter approximation is good if k is large). We compute Ln(1-delta) using the Taylor series and finally find Ln(x)=m*2^k+Ln(1-delta).

For smaller delta, the Taylor series of Ln(1-delta) is more efficient. Therefore, we have a trade-off between having to perform more multiplications to find m, and having a faster convergence of the Taylor series.


Method 6: transformed Taylor series

We can use an alternative Taylor series for the logarithm that converges for all x,

Ln(a+z)=Ln(a)+2*Sum(k,0,Infinity,1/(2*k+1)*(z/(2*a+z))^(2*k+1)).

This series is obtained from the series for ArcTanh(x) and the identity

2*ArcTanh(x)=Ln((1+x)/(1-x)).

This series converges for all z such that Re(a+z)>0 if a>0. The convergence rate is, however, the same as for the original Taylor series. In other words, it converges slowly unless z/(2*a+z) is small. The parameter a can be chosen to optimize the convergence; however, Ln(a) should be either precomputed or easily computable for this method to be efficient.

For instance, if x>1, we can choose a=2^k for an integer k>=1, such that 2^(k-1)<=x<2^k=a. (In other words, k is the bit count of x.) In that case, we represent x=a-z and we find that the expansion parameter z/(2*a-z)<1/3. So a certain rate of convergence is guaranteed, and it is enough to take a fixed number of terms, about P*Ln(10)/Ln(3), to obtain P decimal digits of Ln(x) for any x. (We should also precompute Ln(2) for this scheme to work.)

If 0<x<1, we can compute -Ln(1/x).

This method works robustly but is slower than the Taylor series with some kind of argument reduction. With the "rectangular" method of summation, the total cost is O(Sqrt(P)*M(P)).


Method 7: binary reduction

This method is based on the binary splitting technique and is described in [Haible et al. 1998] with a reference to [Brent 1976].

The method shall compute Ln(1+x) for real x such that Abs(x)<1/2. For other x, some sort of argument reduction needs to be applied. (So this method is a replacement for the Taylor series that is asymptotically faster at very high precision.)

The main idea is to use the property

Ln(1+z*2^(-k))=z*2^(-k)+O(2^(-2*k))

for integer k>=1 and real z such that Abs(z)<=1. This property allows to find the first 2*k binary digits of Ln(1+z*2^(-k)) by inspection: these digits are the first k nonzero digits of z. Then we can perform a very quick computation of Exp(-m*2^(-k)) for integer k, m (evaluated using the binary splitting of the Taylor series) and reduce z by at least the factor 2^k.

More formally, we can write the method as a loop over k, starting with k=1 and stopping when 2^(-k)<10^(-P) is below the required precision. At the beginning of the loop we have y=0, z=x, k=1 and Abs(z)<1/2. The loop invariants are (1+z)*Exp(y) which is always equal to the original number 1+x, and the condition Abs(z)<2^(-k). If we construct this loop, then it is clear that at the end of the loop 1+z will become 1 to required precision and therefore y will be equal to Ln(1+x).

The body of the loop consists of the following steps:

  • Separate the first
  • k significant digits of z:

    f=2^(-2*k)*Floor(2^(2*k)*z).

    Now f is a good approximation for Ln(1+z).
  • Compute
  • Exp(-f) using the binary splitting technique (f is a rational number with the denominator 2^(2*k) and numerator at most 2^k). It is in fact sufficient to compute 1-Exp(-f) which does not need all digits.
  • Set
  • y=y+f and z=(1+z)*Exp(-f)-1.

The total number of steps in the loop is at most Ln(P*Ln(10)/Ln(2))/Ln(2). Each step requires O(M(P)*Ln(P)) operations because th