Exponenciación por el cuadrado

Compartir Imprimir Citar

En matemáticas y programación informática, la exponenciación al cuadrado es un método general para el cálculo rápido de grandes potencias enteras positivas de un número, o más generalmente de un elemento de un semigrupo, como un polinomio o un matriz cuadrada. Algunas variantes se conocen comúnmente como algoritmos cuadrar y multiplicar o potenciación binaria. Estos pueden ser de uso bastante general, por ejemplo en aritmética modular o potenciación de matrices. Para los semigrupos para los que se usa comúnmente la notación aditiva, como las curvas elípticas que se usan en criptografía, este método también se conoce como doble y suma.

Método básico

Versión recursiva

El método se basa en la observación de que, para un entero positivo n, uno tiene

Esto se puede implementar directamente como el siguiente algoritmo recursivo:

 Función exp_by_squaring()x, n) si n . 0 entonces retorno exp_by_squaring()1 / x, -n); más si n = 0 entonces retorno 1; más si n es incluso entonces retorno exp_by_squaring()x * x, n / 2); más si n es extraño entonces retorno x * exp_by_squaring()x * x, ()n - 1) / 2);

Exponenciación recursiva en C++

#include ■iostreamutilizando namespace std;int exponentiation()int a, int b){ si()b==1) retorno a; si()b%2==1) retorno a*exponentiation()a, b-1); int tmp_exp = exponentiation()a, b/2); retorno tmp_exp * tmp_exp;}int principal(){} int a, b; Cout.."Da un "; cinc>a; Cout.."Give b"; cinc>b; Cout..exponentiation()a, b); retorno 0;}

En cada llamada recursiva, los dígitos menos significativos de la representación binaria n es eliminado. Sigue que el número de llamadas recursivas es el número de bits de la representación binaria de n. Así que este algoritmo calcula este número de plazas y un menor número de multiplicación, que es igual al número de plazas 1 en la representación binaria de n. Este número de operaciones logarítmicas se comparará con el algoritmo trivial que requiere n − 1 multiplicaciones.

Este algoritmo no es recursivo a la cola. Esto implica que requiere una memoria auxiliar que es aproximadamente proporcional (o mayor, si se tiene en cuenta el tamaño creciente de los datos) al número de llamadas recursivas.

Los algoritmos de la siguiente sección usan un enfoque diferente y los algoritmos resultantes necesitan la misma cantidad de operaciones, pero usan una memoria auxiliar que es aproximadamente la misma que la memoria requerida para almacenar el resultado.

Con memoria auxiliar constante

Las variantes descritas en esta sección se basan en la fórmula

Si se aplica recursivamente esta fórmula, comenzando con y = 1, se obtiene finalmente un exponente igual a 0, y el resultado deseado es entonces el factor de la izquierda.

Esto puede implementarse como una función recursiva de cola:

 Función exp_by_squaring()x, n) retorno exp_by_squaring2()1, x, n) Función exp_by_squaring2()Sí., x, n) si n . 0 entonces retorno exp_by_squaring2()Sí., 1 / x, - n); más si n = 0 entonces retorno Sí.; más si n es incluso entonces retorno exp_by_squaring2()Sí., x * x, n / 2); más si n es extraño entonces retorno exp_by_squaring2()x * Sí., x * x, ()n - 1) / 2).

La versión iterativa del algoritmo también utiliza un espacio auxiliar acotado y está dada por

 Función exp_by_squaring_iterative()x, n) si n . 0 entonces x := 1 / x; n := -n; si n = 0 entonces retorno 1 Sí. := 1; mientras n  1 do si n es incluso entonces x := x * x; n := n / 2; más Sí. := x * Sí.; x := x * x; n := ()n  1) / 2; retorno x * Sí.

La corrección del algoritmo resulta del hecho de que es invariante durante el cálculo; al principio; y al final.

Estos algoritmos usan exactamente el mismo número de operaciones que el algoritmo de la sección anterior, pero las multiplicaciones se realizan en un orden diferente.

Complejidad computacional

Un breve análisis muestra que tal algoritmo utiliza squarings and at most multiplicaciones, donde denota la función del suelo. Más precisamente, el número de multiplicaciones es menor que el número de las presentes en la expansión binaria n. Para n más grande que alrededor de 4 esto es computacionalmente más eficiente que multiplicar ingenuamente la base con sí misma repetidamente.

Cada elevación al cuadrado da como resultado aproximadamente el doble del número de dígitos del anterior, por lo que, si la multiplicación de números de dos ddígitos se implementa en O(dk) operaciones para algunos k fijos, luego la complejidad de calcular xn viene dado por

Método 2k-ario

Este algoritmo calcula el valor de xn después de expandir el exponente en base 2k. Brauer lo propuso por primera vez en 1939. En el siguiente algoritmo, utilizamos la siguiente función f(0) = (k,0) y f< /i>(m) = (s,u), donde m = u·2s con u impar.

Algoritmo:

Input
Un elemento x de G, un parámetro k in 0, un entero no negativo n =nl−1, nl−2,... n0)2k y los valores precomputados .
Producto
El elemento xn dentro G
y:= 1; i:= l - 1
mientras i ≥ 0 do
(s, u):= f(ni)
 para J:= 1 a k - s doY... Sí.2 Y...u para J:= 1 a s doY... Sí.2i:= I - 1
retorno Sí.

Para una eficiencia óptima, k debe ser el entero más pequeño que satisfaga

Método de ventana deslizante

Este método es una variante eficiente del método 2k-ario. Por ejemplo, para calcular el exponente 398, que tiene expansión binaria (110 001 110)2, tomamos una ventana de longitud 3 usando el 2k-ary y calcular 1, x3, x6, x12, x24, x48, x49, x98, x99, x198, x199, x398. Pero también podemos calcular 1, x3, x6, x12, x24, x< sup>48, x96, x192, x199, x398, lo que ahorra una multiplicación y equivale a evaluar (110 001 110)2

Este es el algoritmo general:

Algoritmo:

Input
Un elemento x de G, un entero no negativo n=nl−1, nl−2,... n0)2, un parámetro k Ø 0 y los valores precomputados .
Producto
El elemento xnG.

Algoritmo:

y:= 1; i:= l - 1
mientras i do si ni = 0 entoncesY... Sí.2Yo... i - 1
 másS:= max{i - k + 1, 0}
 mientras ns = 0 dos:= s + 1
 para h:= 1 a i - s + 1 doY... Sí.2No.i, ni-1,...s)2Y...ui:= s - 1
retorno Sí.

Técnica de la escalera de Montgomery

Muchos algoritmos de exponenciación no brindan defensa contra los ataques de canal lateral. Es decir, un atacante que observa la secuencia de elevaciones al cuadrado y multiplicaciones puede recuperar (parcialmente) el exponente involucrado en el cálculo. Este es un problema si el exponente debe permanecer en secreto, como ocurre con muchos criptosistemas de clave pública. Una técnica llamada 'escalera de Montgomery' aborda esta inquietud.

Dada la expansión binaria de un entero positivo distinto de cero n = (nk−1...n0)2 con nk−1 = 1, podemos calcular xn de la siguiente manera:

x1 = x; x2 = x2para i = k - 2 a 0 do si ni = 0 entoncesx2 = x1 *2; x1 = x12 másx1 = x1 *2; x2 = x22retorno x1

El algoritmo realiza una secuencia fija de operaciones (hasta logn): se realiza una multiplicación y un cuadrado para cada bit en el exponente, independientemente del valor específico del bit. Existe un algoritmo similar para la multiplicación por duplicación.

Esta implementación específica de la escalera de Montgomery aún no está protegida contra ataques de tiempo de caché: las latencias de acceso a la memoria aún pueden ser observables para un atacante, ya que se accede a diferentes variables según el valor de los bits del exponente secreto. Las implementaciones criptográficas modernas utilizan una "dispersión" técnica para asegurarse de que el procesador siempre pierda el caché más rápido.

Exponente de base fija

Hay varios métodos que se pueden emplear para calcular xn cuando la base es fija y el exponente varía. Como se puede ver, los cálculos previos juegan un papel clave en estos algoritmos.

El método de Yao

El método de Yao es ortogonal al método 2k-ary donde el exponente se expande en radix b = 2k y el cálculo se realiza como en el algoritmo anterior. Sea n, ni , b y bi sean números enteros.

Deje que el exponente n se escriba como

Donde para todos .

Sea xi = xbi< /i>.

Entonces el algoritmo usa la igualdad

Dado el elemento x de G, y el exponente n escrito en el formulario anterior, junto con los valores precalculados xb0...x bw−1, el elemento xn se calcula utilizando el siguiente algoritmo:

y = 1, u = 1, j = h - 1
mientras j latitud 0 do para I = 0 a w - 1 do si ni j entoncesU = u × xbiy
j = j) 1
retorno Sí.

Si nos fijamos h = 2k y bi = hi, entonces el ni valores son simplemente los dígitos de n en base h. El método de Yao se acumula en u primero xi que parecen al poder más alto ; en la siguiente vuelta aquellos con poder se recogen en u así como etc. La variable Sí. se multiplica tiempos con la inicial u, tiempos con los siguientes poderes más altos, y así sucesivamente. El algoritmo utiliza multiplicaciones, y elementos deben almacenarse para calcular xn.

Método euclidiano

El método euclidiano se introdujo por primera vez en Exponenciación eficiente mediante precálculo y cadenas de suma de vectores de P.D Rooij.

Este método de cálculo en grupo G, donde n es un entero natural, cuyo algoritmo se da a continuación, está utilizando la siguiente igualdad recursivamente:

Donde . En otras palabras, una división euclidiana del exponente n1 por n0 se utiliza para devolver un cociente q y un descanso n1 mod n0.

Dado el elemento base x en grupo G, y el exponente escrito como en el método de Yao, el elemento se calcula utilizando valores precomputados y luego el algoritmo debajo.

Comience el bucle Encontrar , tales que . Encontrar , tales que . Bucle de ruptura si . Vamos , y luego Deja . Computar recursivamente , y luego Deja .Loop final;
Regreso .

El algoritmo primero encuentra el valor más grande entre ni y luego el supremo dentro del conjunto de { ni i M . Luego eleva xM a la potencia q, multiplica este valor por xN, y luego asigna xN el resultado de este cálculo y nM el valor n< /i>M módulo nN .

Otras aplicaciones

La misma idea permite el cálculo rápido de exponentes grandes módulo un número. Especialmente en criptografía, es útil calcular potencias en un anillo de números enteros módulo q. También se puede usar para calcular potencias enteras en un grupo, usando la regla

Poder(x, −n(Power)x, n)−1.

El método funciona en todos los semigrupos y se usa a menudo para calcular potencias de matrices.

Por ejemplo, la evaluación de

13789722341 (mod 2345) = 2029

tomaría mucho tiempo y mucho espacio de almacenamiento si se utiliza el método ingenuo: computar 13789722341, entonces tome el resto cuando se divide en 2345. Incluso utilizando un método más eficaz tomará mucho tiempo: cuadrado 13789, tomar el resto cuando se divide en 2345, multiplicar el resultado por 13789, y así sucesivamente. Esto tomará menos que multiplicaciones modulares.

Aplicando el algoritmo exp-by-squareing anterior, con "*" interpretado como x * y = xy mod 2345 (es decir, una multiplicación seguida de una división con resto) conduce a solo 27 multiplicaciones y divisiones de números enteros, que pueden almacenarse en una sola palabra de máquina.

Grabación de dígitos con signo

En ciertos cálculos, puede ser más eficiente permitir coeficientes negativos y, por lo tanto, usar el inverso de la base, siempre que se invierta en G es "rápido" o ha sido precalculada. Por ejemplo, al calcular x2k−1, el método binario requiere k−1 multiplicaciones y k−1 cuadraturas. Sin embargo, uno podría realizar k cuadrados para obtener x2k y luego multiplicar por x−1 para obtener x2k−1.

Con este fin, definimos la representación de dígitos con signo de un número entero n en radix b como

Representación binaria firmada corresponde a la elección particular b = 2 y . Es denotado por . Hay varios métodos para calcular esta representación. La representación no es única. Por ejemplo, tome n = 478: dos representaciones firmadas-binarias distintas son dadas por y , donde se utiliza para denotar −1. Puesto que el método binario calcula una multiplicación por cada entrada no cero en la base-2 representación de n, estamos interesados en encontrar la representación binaria firmada con el menor número de entradas no cero, es decir, la con mínimo Hamming peso. Un método de hacer esto es calcular la representación en forma no adyacente, o NAF por corto, que es uno que satisface y denotado por . Por ejemplo, la representación de la NAF de 478 es . Esta representación siempre tiene un peso mínimo de Hamming. Un simple algoritmo para calcular la representación de NAF de un entero dado con es el siguiente:

para i = 0 a l − 1 do
  retorno 

Otro algoritmo de Koyama y Tsuruoka no requiere la condición de que ; todavía minimiza el peso de Hamming.

Alternativas y generalizaciones

La exponenciación por elevación al cuadrado puede verse como un algoritmo de potenciación de cadena de suma subóptimo: calcula el exponente por una cadena de suma que consiste en duplicaciones repetidas de exponentes (elevaciones al cuadrado) y/o exponentes incrementados por uno (multiplicando por x) solamente. De manera más general, si uno permite que se sumen cualquier exponentes previamente calculados (multiplicando esas potencias de x), a veces se puede realizar la exponenciación usando menos multiplicaciones (pero típicamente usando más memoria). La potencia más pequeña donde esto ocurre es para n = 15:

(squaring, 6 multiplicados),
(cadena adicional óptima, 5 multiplica si x3 es reutilizado).

En general, encontrar la cadena de suma óptima para un exponente dado es un problema difícil, para el cual no se conocen algoritmos eficientes, por lo que las cadenas óptimas generalmente solo se usan para exponentes pequeños (por ejemplo, en compiladores donde las cadenas para pequeñas potencias han sido pre-tabuladas). Sin embargo, hay una serie de algoritmos heurísticos que, si bien no son óptimos, tienen menos multiplicaciones que exponenciaciones al elevar al cuadrado a costa de un trabajo adicional de contabilidad y uso de memoria. Independientemente, el número de multiplicaciones nunca crece más lentamente que Θ(log n), por lo que estos algoritmos solo mejoran asintóticamente con la exponenciación al elevar al cuadrado por un factor constante en el mejor de los casos.