This article may be confusing or unclear to readers.(May 2022) |
This article needs additional citations for verification .(February 2018) |
In mathematics and computer programming, exponentiating by squaring is a general method for fast computation of large positive integer powers of a number, or more generally of an element of a semigroup, like a polynomial or a square matrix. Some variants are commonly referred to as square-and-multiply algorithms or binary exponentiation. These can be of quite general use, for example in modular arithmetic or powering of matrices. For semigroups for which additive notation is commonly used, like elliptic curves used in cryptography, this method is also referred to as double-and-add.
The method is based on the observation that, for any integer , one has:
If the exponent n is zero then the answer is 1. If the exponent is negative then we can reuse the previous formula by rewriting the value using a positive exponent. That is,
Together, these may be implemented directly as the following recursive algorithm:
In: an integer x; an integer n Out: xn exp_by_squaring(x, n) if n < 0 then return exp_by_squaring(1 / x, -n); else if n = 0 then return 1; else if n is even then return exp_by_squaring(x * x, n / 2); else if n is odd then return x * exp_by_squaring(x * x, (n - 1) / 2); end function
In each recursive call, the least significant digits of the binary representation of n is removed. It follows that the number of recursive calls is the number of bits of the binary representation of n. So this algorithm computes this number of squares and a lower number of multiplication, which is equal to the number of 1 in the binary representation of n. This logarithmic number of operations is to be compared with the trivial algorithm which requires n − 1 multiplications.
This algorithm is not tail-recursive. This implies that it requires an amount of auxiliary memory that is roughly proportional to the number of recursive calls -- or perhaps higher if the amount of data per iteration is increasing.
The algorithms of the next section use a different approach, and the resulting algorithms needs the same number of operations, but use an auxiliary memory that is roughly the same as the memory required to store the result.
The variants described in this section are based on the formula
If one applies recursively this formula, by starting with y = 1, one gets eventually an exponent equal to 0, and the desired result is then the left factor.
This may be implemented as a tail-recursive function:
Functionexp_by_squaring(x,n)returnexp_by_squaring2(1,x,n)Functionexp_by_squaring2(y,x,n)ifn<0thenreturnexp_by_squaring2(y,1/x,-n);elseifn=0thenreturny;elseifniseventhenreturnexp_by_squaring2(y,x*x,n/2);elseifnisoddthenreturnexp_by_squaring2(x*y,x*x,(n-1)/2).
The iterative version of the algorithm also uses a bounded auxiliary space, and is given by
Functionexp_by_squaring_iterative(x,n)ifn<0thenx:=1/x;n:=-n;ifn=0thenreturn1y:=1;whilen>1doifnisoddtheny:=x*y;n:=n-1;x:=x*x;n:=n/2;returnx*y
The correctness of the algorithm results from the fact that is invariant during the computation; it is at the beginning; and it is at the end.
These algorithms use exactly the same number of operations as the algorithm of the preceding section, but the multiplications are done in a different order.
A brief analysis shows that such an algorithm uses squarings and at most multiplications, where denotes the floor function. More precisely, the number of multiplications is one less than the number of ones present in the binary expansion of n. For n greater than about 4 this is computationally more efficient than naively multiplying the base with itself repeatedly.
Each squaring results in approximately double the number of digits of the previous, and so, if multiplication of two d-digit numbers is implemented in O(dk) operations for some fixed k, then the complexity of computing xn is given by
This algorithm calculates the value of xn after expanding the exponent in base 2k. It was first proposed by Brauer in 1939. In the algorithm below we make use of the following function f(0) = (k, 0) and f(m) = (s, u), where m = u·2s with u odd.
Algorithm:
y := 1; i := l - 1 while i ≥ 0 do (s, u) := f(ni) for j := 1 to k - s do y := y2 y := y * xufor j := 1 to s do y := y2 i := i - 1 return y
For optimal efficiency, k should be the smallest integer satisfying [1]
This method is an efficient variant of the 2k-ary method. For example, to calculate the exponent 398, which has binary expansion (110 001 110)2, we take a window of length 3 using the 2k-ary method algorithm and calculate 1, x3, x6, x12, x24, x48, x49, x98, x99, x198, x199, x398. But, we can also compute 1, x3, x6, x12, x24, x48, x96, x192, x199, x398, which saves one multiplication and amounts to evaluating (110 001 110)2
Here is the general algorithm:
Algorithm:
Algorithm:
y := 1; i := l - 1 while i > -1 doif ni = 0 then y := y2' i := i - 1 else s := max{i - k + 1, 0} while ns = 0 do s := s + 1 [notes 1] for h := 1 to i - s + 1 do y := y2 u := (ni, ni-1, ..., ns)2 y := y * xu i := s - 1 return y
Many algorithms for exponentiation do not provide defence against side-channel attacks. Namely, an attacker observing the sequence of squarings and multiplications can (partially) recover the exponent involved in the computation. This is a problem if the exponent should remain secret, as with many public-key cryptosystems. A technique called "Montgomery's ladder" [2] addresses this concern.
Given the binary expansion of a positive, non-zero integer n = (nk−1...n0)2 with nk−1 = 1, we can compute xn as follows:
x1 = x; x2 = x2for i = k - 2 to 0 doif ni = 0 then x2 = x1 * x2; x1 = x12else x1 = x1 * x2; x2 = x22return x1
The algorithm performs a fixed sequence of operations (up to log n): a multiplication and squaring takes place for each bit in the exponent, regardless of the bit's specific value. A similar algorithm for multiplication by doubling exists.
This specific implementation of Montgomery's ladder is not yet protected against cache timing attacks: memory access latencies might still be observable to an attacker, as different variables are accessed depending on the value of bits of the secret exponent. Modern cryptographic implementations use a "scatter" technique to make sure the processor always misses the faster cache. [3]
There are several methods which can be employed to calculate xn when the base is fixed and the exponent varies. As one can see, precomputations play a key role in these algorithms.
Yao's method is orthogonal to the 2k-ary method where the exponent is expanded in radix b = 2k and the computation is as performed in the algorithm above. Let n, ni, b, and bi be integers.
Let the exponent n be written as
where for all .
Let xi = xbi.
Then the algorithm uses the equality
Given the element x of G, and the exponent n written in the above form, along with the precomputed values xb0...xbw−1, the element xn is calculated using the algorithm below:
y = 1, u = 1, j = h - 1 while j > 0 dofor i = 0 to w - 1 doif ni = j then u = u × xbi y = y × u j = j - 1 return y
If we set h = 2k and bi = hi, then the ni values are simply the digits of n in base h. Yao's method collects in u first those xi that appear to the highest power ; in the next round those with power are collected in u as well etc. The variable y is multiplied times with the initial u, times with the next highest powers, and so on. The algorithm uses multiplications, and elements must be stored to compute xn. [1]
The Euclidean method was first introduced in Efficient exponentiation using precomputation and vector addition chains by P.D Rooij.
This method for computing in group G, where n is a natural integer, whose algorithm is given below, is using the following equality recursively:
where . In other words, a Euclidean division of the exponent n1 by n0 is used to return a quotient q and a rest n1 mod n0.
Given the base element x in group G, and the exponent written as in Yao's method, the element is calculated using precomputed values and then the algorithm below.
Begin loopFind ,such that .Find ,such that .Break loopif .Let,and then let.Compute recursively ,and then let.End loop; Return.
The algorithm first finds the largest value among the ni and then the supremum within the set of { ni \ i ≠ M }. Then it raises xM to the power q, multiplies this value with xN, and then assigns xN the result of this computation and nM the value nM modulo nN.
The approach also works with semigroups that are not of characteristic zero, for example allowing fast computation of large exponents modulo a number. Especially in cryptography, it is useful to compute powers in a ring of integers modulo q. For example, the evaluation of
would take a very long time and much storage space if the naïve method of computing 13789722341 and then taking the remainder when divided by 2345 were used. Even using a more effective method will take a long time: square 13789, take the remainder when divided by 2345, multiply the result by 13789, and so on.
Applying above exp-by-squaring algorithm, with "*" interpreted as x * y = xy mod 2345 (that is, a multiplication followed by a division with remainder) leads to only 27 multiplications and divisions of integers, which may all be stored in a single machine word. Generally, any of these approaches will take fewer than 2log2(722340) ≤ 40 modular multiplications.
The approach can also be used to compute integer powers in a group, using either of the rules
The approach also works in non-commutative semigroups and is often used to compute powers of matrices.
More generally, the approach works with positive integer exponents in every magma for which the binary operation is power associative.
In certain computations it may be more efficient to allow negative coefficients and hence use the inverse of the base, provided inversion in G is "fast" or has been precomputed. For example, when computing x2k−1, the binary method requires k−1 multiplications and k−1 squarings. However, one could perform k squarings to get x2k and then multiply by x−1 to obtain x2k−1.
To this end we define the signed-digit representation of an integer n in radix b as
Signed binary representation corresponds to the particular choice b = 2 and . It is denoted by . There are several methods for computing this representation. The representation is not unique. For example, take n = 478: two distinct signed-binary representations are given by and , where is used to denote −1. Since the binary method computes a multiplication for every non-zero entry in the base-2 representation of n, we are interested in finding the signed-binary representation with the smallest number of non-zero entries, that is, the one with minimal Hamming weight. One method of doing this is to compute the representation in non-adjacent form, or NAF for short, which is one that satisfies and denoted by . For example, the NAF representation of 478 is . This representation always has minimal Hamming weight. A simple algorithm to compute the NAF representation of a given integer with is the following:
for i = 0 to l − 1 do return
Another algorithm by Koyama and Tsuruoka does not require the condition that ; it still minimizes the Hamming weight.
Exponentiation by squaring can be viewed as a suboptimal addition-chain exponentiation algorithm: it computes the exponent by an addition chain consisting of repeated exponent doublings (squarings) and/or incrementing exponents by one (multiplying by x) only. More generally, if one allows any previously computed exponents to be summed (by multiplying those powers of x), one can sometimes perform the exponentiation using fewer multiplications (but typically using more memory). The smallest power where this occurs is for n = 15:
In general, finding the optimal addition chain for a given exponent is a hard problem, for which no efficient algorithms are known, so optimal chains are typically used for small exponents only (e.g. in compilers where the chains for small powers have been pre-tabulated). However, there are a number of heuristic algorithms that, while not being optimal, have fewer multiplications than exponentiation by squaring at the cost of additional bookkeeping work and memory usage. Regardless, the number of multiplications never grows more slowly than Θ(log n), so these algorithms improve asymptotically upon exponentiation by squaring by only a constant factor at best.
In mathematics, the factorial of a non-negative integer , denoted by , is the product of all positive integers less than or equal to . The factorial of also equals the product of with the next smaller factorial:
In mathematics, the greatest common divisor (GCD) of two or more integers, which are not all zero, is the largest positive integer that divides each of the integers. For two integers x, y, the greatest common divisor of x and y is denoted . For example, the GCD of 8 and 12 is 4, that is, gcd(8, 12) = 4.
In mathematics, the logarithm is the inverse function to exponentiation. That means that the logarithm of a number x to the base b is the exponent to which b must be raised to produce x. For example, since 1000 = 103, the logarithm base of 1000 is 3, or log10 (1000) = 3. The logarithm of x to base b is denoted as logb (x), or without parentheses, logb x. When the base is clear from the context or is irrelevant it is sometimes written log x.
A multiplication algorithm is an algorithm to multiply two numbers. Depending on the size of the numbers, different algorithms are more efficient than others. Efficient multiplication algorithms have existed since the advent of the decimal numeral system.
In mathematics, exponentiation is an operation involving two numbers: the base and the exponent or power. Exponentiation is written as bn, where b is the base and n is the power; this is pronounced as "b (raised) to the n". When n is a positive integer, exponentiation corresponds to repeated multiplication of the base: that is, bn is the product of multiplying n bases:
In mathematics, the binary logarithm is the power to which the number 2 must be raised to obtain the value n. That is, for any real number x,
In mathematics, tetration is an operation based on iterated, or repeated, exponentiation. There is no standard notation for tetration, though Knuth's up arrow notation and the left-exponent xb are common.
In mathematics, an addition chain for computing a positive integer n can be given by a sequence of natural numbers starting with 1 and ending with n, such that each number in the sequence is the sum of two previous numbers. The length of an addition chain is the number of sums needed to express all its numbers, which is one less than the cardinality of the sequence of numbers.
In mathematics and computer science, optimal addition-chain exponentiation is a method of exponentiation by a positive integer power that requires a minimal number of multiplications. Using the form of the shortest addition chain, with multiplication instead of addition, computes the desired exponent of the base. Each exponentiation in the chain can be evaluated by multiplying two of the earlier exponentiation results. More generally, addition-chain exponentiation may also refer to exponentiation by non-minimal addition chains constructed by a variety of algorithms.
Modular exponentiation is exponentiation performed over a modulus. It is useful in computer science, especially in the field of public-key cryptography, where it is used in both Diffie–Hellman key exchange and RSA public/private keys.
In number theory, the integer square root (isqrt) of a non-negative integer n is the non-negative integer m which is the greatest integer less than or equal to the square root of n,
The Schönhage–Strassen algorithm is an asymptotically fast multiplication algorithm for large integers, published by Arnold Schönhage and Volker Strassen in 1971. It works by recursively applying fast Fourier transform (FFT) over the integers modulo 2n+1. The run-time bit complexity to multiply two n-digit numbers using the algorithm is in big O notation.
A division algorithm is an algorithm which, given two integers N and D, computes their quotient and/or remainder, the result of Euclidean division. Some are applied by hand, while others are employed by digital circuit designs and software.
In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code. The approach can be applied to many types of problems, and recursion is one of the central ideas of computer science.
The power of recursion evidently lies in the possibility of defining an infinite set of objects by a finite statement. In the same manner, an infinite number of computations can be described by a finite recursive program, even if this program contains no explicit repetitions.
The Karatsuba algorithm is a fast multiplication algorithm. It was discovered by Anatoly Karatsuba in 1960 and published in 1962. It is a divide-and-conquer algorithm that reduces the multiplication of two n-digit numbers to three multiplications of n/2-digit numbers and, by repeating this reduction, to at most single-digit multiplications. It is therefore asymptotically faster than the traditional algorithm, which performs single-digit products.
The following tables list the computational complexity of various algorithms for common mathematical operations.
The BKM algorithm is a shift-and-add algorithm for computing elementary functions, first published in 1994 by Jean-Claude Bajard, Sylvanus Kla, and Jean-Michel Muller. BKM is based on computing complex logarithms (L-mode) and exponentials (E-mode) using a method similar to the algorithm Henry Briggs used to compute logarithms. By using a precomputed table of logarithms of negative powers of two, the BKM algorithm computes elementary functions using only integer add, shift, and compare operations.
An important aspect in the study of elliptic curves is devising effective ways of counting points on the curve. There have been several approaches to do so, and the algorithms devised have proved to be useful tools in the study of various fields such as number theory, and more recently in cryptography and Digital Signature Authentication. While in number theory they have important consequences in the solving of Diophantine equations, with respect to cryptography, they enable us to make effective use of the difficulty of the discrete logarithm problem (DLP) for the group , of elliptic curves over a finite field , where q = pk and p is a prime. The DLP, as it has come to be known, is a widely used approach to public key cryptography, and the difficulty in solving this problem determines the level of security of the cryptosystem. This article covers algorithms to count points on elliptic curves over fields of large characteristic, in particular p > 3. For curves over fields of small characteristic more efficient algorithms based on p-adic methods exist.
In computer science, sorting is the problem of sorting pairs of numbers by their sums. Applications of the problem include transit fare minimisation, VLSI design, and sparse polynomial multiplication. As with comparison sorting and integer sorting more generally, algorithms for this problem can be based only on comparisons of these sums, or on other operations that work only when the inputs are small integers.
In mathematics and computer science, polynomial evaluation refers to computation of the value of a polynomial when its indeterminates are substituted for some values. In other words, evaluating the polynomial at consists of computing See also Polynomial ring § Polynomial evaluation