17db96d56Sopenharmony_ci# 27db96d56Sopenharmony_ci# Copyright (c) 2008-2020 Stefan Krah. All rights reserved. 37db96d56Sopenharmony_ci# 47db96d56Sopenharmony_ci# Redistribution and use in source and binary forms, with or without 57db96d56Sopenharmony_ci# modification, are permitted provided that the following conditions 67db96d56Sopenharmony_ci# are met: 77db96d56Sopenharmony_ci# 87db96d56Sopenharmony_ci# 1. Redistributions of source code must retain the above copyright 97db96d56Sopenharmony_ci# notice, this list of conditions and the following disclaimer. 107db96d56Sopenharmony_ci# 117db96d56Sopenharmony_ci# 2. Redistributions in binary form must reproduce the above copyright 127db96d56Sopenharmony_ci# notice, this list of conditions and the following disclaimer in the 137db96d56Sopenharmony_ci# documentation and/or other materials provided with the distribution. 147db96d56Sopenharmony_ci# 157db96d56Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 167db96d56Sopenharmony_ci# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 177db96d56Sopenharmony_ci# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 187db96d56Sopenharmony_ci# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 197db96d56Sopenharmony_ci# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 207db96d56Sopenharmony_ci# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 217db96d56Sopenharmony_ci# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 227db96d56Sopenharmony_ci# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 237db96d56Sopenharmony_ci# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 247db96d56Sopenharmony_ci# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 257db96d56Sopenharmony_ci# SUCH DAMAGE. 267db96d56Sopenharmony_ci# 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci###################################################################### 307db96d56Sopenharmony_ci# This file lists and checks some of the constants and limits used # 317db96d56Sopenharmony_ci# in libmpdec's Number Theoretic Transform. At the end of the file # 327db96d56Sopenharmony_ci# there is an example function for the plain DFT transform. # 337db96d56Sopenharmony_ci###################################################################### 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci# 377db96d56Sopenharmony_ci# Number theoretic transforms are done in subfields of F(p). P[i] 387db96d56Sopenharmony_ci# are the primes, D[i] = P[i] - 1 are highly composite and w[i] 397db96d56Sopenharmony_ci# are the respective primitive roots of F(p). 407db96d56Sopenharmony_ci# 417db96d56Sopenharmony_ci# The strategy is to convolute two coefficients modulo all three 427db96d56Sopenharmony_ci# primes, then use the Chinese Remainder Theorem on the three 437db96d56Sopenharmony_ci# result arrays to recover the result in the usual base RADIX 447db96d56Sopenharmony_ci# form. 457db96d56Sopenharmony_ci# 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci# ====================================================================== 487db96d56Sopenharmony_ci# Primitive roots 497db96d56Sopenharmony_ci# ====================================================================== 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci# 527db96d56Sopenharmony_ci# Verify primitive roots: 537db96d56Sopenharmony_ci# 547db96d56Sopenharmony_ci# For a prime field, r is a primitive root if and only if for all prime 557db96d56Sopenharmony_ci# factors f of p-1, r**((p-1)/f) =/= 1 (mod p). 567db96d56Sopenharmony_ci# 577db96d56Sopenharmony_cidef prod(F, E): 587db96d56Sopenharmony_ci """Check that the factorization of P-1 is correct. F is the list of 597db96d56Sopenharmony_ci factors of P-1, E lists the number of occurrences of each factor.""" 607db96d56Sopenharmony_ci x = 1 617db96d56Sopenharmony_ci for y, z in zip(F, E): 627db96d56Sopenharmony_ci x *= y**z 637db96d56Sopenharmony_ci return x 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_cidef is_primitive_root(r, p, factors, exponents): 667db96d56Sopenharmony_ci """Check if r is a primitive root of F(p).""" 677db96d56Sopenharmony_ci if p != prod(factors, exponents) + 1: 687db96d56Sopenharmony_ci return False 697db96d56Sopenharmony_ci for f in factors: 707db96d56Sopenharmony_ci q, control = divmod(p-1, f) 717db96d56Sopenharmony_ci if control != 0: 727db96d56Sopenharmony_ci return False 737db96d56Sopenharmony_ci if pow(r, q, p) == 1: 747db96d56Sopenharmony_ci return False 757db96d56Sopenharmony_ci return True 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci# ================================================================= 797db96d56Sopenharmony_ci# Constants and limits for the 64-bit version 807db96d56Sopenharmony_ci# ================================================================= 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ciRADIX = 10**19 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci# Primes P1, P2 and P3: 857db96d56Sopenharmony_ciP = [2**64-2**32+1, 2**64-2**34+1, 2**64-2**40+1] 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci# P-1, highly composite. The transform length d is variable and 887db96d56Sopenharmony_ci# must divide D = P-1. Since all D are divisible by 3 * 2**32, 897db96d56Sopenharmony_ci# transform lengths can be 2**n or 3 * 2**n (where n <= 32). 907db96d56Sopenharmony_ciD = [2**32 * 3 * (5 * 17 * 257 * 65537), 917db96d56Sopenharmony_ci 2**34 * 3**2 * (7 * 11 * 31 * 151 * 331), 927db96d56Sopenharmony_ci 2**40 * 3**2 * (5 * 7 * 13 * 17 * 241)] 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci# Prime factors of P-1 and their exponents: 957db96d56Sopenharmony_ciF = [(2,3,5,17,257,65537), (2,3,7,11,31,151,331), (2,3,5,7,13,17,241)] 967db96d56Sopenharmony_ciE = [(32,1,1,1,1,1), (34,2,1,1,1,1,1), (40,2,1,1,1,1,1)] 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci# Maximum transform length for 2**n. Above that only 3 * 2**31 997db96d56Sopenharmony_ci# or 3 * 2**32 are possible. 1007db96d56Sopenharmony_ciMPD_MAXTRANSFORM_2N = 2**32 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci# Limits in the terminology of Pollard's paper: 1047db96d56Sopenharmony_cim2 = (MPD_MAXTRANSFORM_2N * 3) // 2 # Maximum length of the smaller array. 1057db96d56Sopenharmony_ciM1 = M2 = RADIX-1 # Maximum value per single word. 1067db96d56Sopenharmony_ciL = m2 * M1 * M2 1077db96d56Sopenharmony_ciP[0] * P[1] * P[2] > 2 * L 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci# Primitive roots of F(P1), F(P2) and F(P3): 1117db96d56Sopenharmony_ciw = [7, 10, 19] 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci# The primitive roots are correct: 1147db96d56Sopenharmony_cifor i in range(3): 1157db96d56Sopenharmony_ci if not is_primitive_root(w[i], P[i], F[i], E[i]): 1167db96d56Sopenharmony_ci print("FAIL") 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci# ================================================================= 1207db96d56Sopenharmony_ci# Constants and limits for the 32-bit version 1217db96d56Sopenharmony_ci# ================================================================= 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ciRADIX = 10**9 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci# Primes P1, P2 and P3: 1267db96d56Sopenharmony_ciP = [2113929217, 2013265921, 1811939329] 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci# P-1, highly composite. All D = P-1 are divisible by 3 * 2**25, 1297db96d56Sopenharmony_ci# allowing for transform lengths up to 3 * 2**25 words. 1307db96d56Sopenharmony_ciD = [2**25 * 3**2 * 7, 1317db96d56Sopenharmony_ci 2**27 * 3 * 5, 1327db96d56Sopenharmony_ci 2**26 * 3**3] 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci# Prime factors of P-1 and their exponents: 1357db96d56Sopenharmony_ciF = [(2,3,7), (2,3,5), (2,3)] 1367db96d56Sopenharmony_ciE = [(25,2,1), (27,1,1), (26,3)] 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci# Maximum transform length for 2**n. Above that only 3 * 2**24 or 1397db96d56Sopenharmony_ci# 3 * 2**25 are possible. 1407db96d56Sopenharmony_ciMPD_MAXTRANSFORM_2N = 2**25 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci# Limits in the terminology of Pollard's paper: 1447db96d56Sopenharmony_cim2 = (MPD_MAXTRANSFORM_2N * 3) // 2 # Maximum length of the smaller array. 1457db96d56Sopenharmony_ciM1 = M2 = RADIX-1 # Maximum value per single word. 1467db96d56Sopenharmony_ciL = m2 * M1 * M2 1477db96d56Sopenharmony_ciP[0] * P[1] * P[2] > 2 * L 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci# Primitive roots of F(P1), F(P2) and F(P3): 1517db96d56Sopenharmony_ciw = [5, 31, 13] 1527db96d56Sopenharmony_ci 1537db96d56Sopenharmony_ci# The primitive roots are correct: 1547db96d56Sopenharmony_cifor i in range(3): 1557db96d56Sopenharmony_ci if not is_primitive_root(w[i], P[i], F[i], E[i]): 1567db96d56Sopenharmony_ci print("FAIL") 1577db96d56Sopenharmony_ci 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci# ====================================================================== 1607db96d56Sopenharmony_ci# Example transform using a single prime 1617db96d56Sopenharmony_ci# ====================================================================== 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_cidef ntt(lst, dir): 1647db96d56Sopenharmony_ci """Perform a transform on the elements of lst. len(lst) must 1657db96d56Sopenharmony_ci be 2**n or 3 * 2**n, where n <= 25. This is the slow DFT.""" 1667db96d56Sopenharmony_ci p = 2113929217 # prime 1677db96d56Sopenharmony_ci d = len(lst) # transform length 1687db96d56Sopenharmony_ci d_prime = pow(d, (p-2), p) # inverse of d 1697db96d56Sopenharmony_ci xi = (p-1)//d 1707db96d56Sopenharmony_ci w = 5 # primitive root of F(p) 1717db96d56Sopenharmony_ci r = pow(w, xi, p) # primitive root of the subfield 1727db96d56Sopenharmony_ci r_prime = pow(w, (p-1-xi), p) # inverse of r 1737db96d56Sopenharmony_ci if dir == 1: # forward transform 1747db96d56Sopenharmony_ci a = lst # input array 1757db96d56Sopenharmony_ci A = [0] * d # transformed values 1767db96d56Sopenharmony_ci for i in range(d): 1777db96d56Sopenharmony_ci s = 0 1787db96d56Sopenharmony_ci for j in range(d): 1797db96d56Sopenharmony_ci s += a[j] * pow(r, i*j, p) 1807db96d56Sopenharmony_ci A[i] = s % p 1817db96d56Sopenharmony_ci return A 1827db96d56Sopenharmony_ci elif dir == -1: # backward transform 1837db96d56Sopenharmony_ci A = lst # input array 1847db96d56Sopenharmony_ci a = [0] * d # transformed values 1857db96d56Sopenharmony_ci for j in range(d): 1867db96d56Sopenharmony_ci s = 0 1877db96d56Sopenharmony_ci for i in range(d): 1887db96d56Sopenharmony_ci s += A[i] * pow(r_prime, i*j, p) 1897db96d56Sopenharmony_ci a[j] = (d_prime * s) % p 1907db96d56Sopenharmony_ci return a 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_cidef ntt_convolute(a, b): 1937db96d56Sopenharmony_ci """convolute arrays a and b.""" 1947db96d56Sopenharmony_ci assert(len(a) == len(b)) 1957db96d56Sopenharmony_ci x = ntt(a, 1) 1967db96d56Sopenharmony_ci y = ntt(b, 1) 1977db96d56Sopenharmony_ci for i in range(len(a)): 1987db96d56Sopenharmony_ci y[i] = y[i] * x[i] 1997db96d56Sopenharmony_ci r = ntt(y, -1) 2007db96d56Sopenharmony_ci return r 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci# Example: Two arrays representing 21 and 81 in little-endian: 2047db96d56Sopenharmony_cia = [1, 2, 0, 0] 2057db96d56Sopenharmony_cib = [1, 8, 0, 0] 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ciassert(ntt_convolute(a, b) == [1, 10, 16, 0]) 2087db96d56Sopenharmony_ciassert(21 * 81 == (1*10**0 + 10*10**1 + 16*10**2 + 0*10**3)) 209