blob: 280db1cab935c0ba31eb5b9a6d543e4eceefeba7 [file] [log] [blame]
#
# Number Theoretic functions
# M Scott August 2013
#
import math
import types
import random
from XXX import curve
def to_bytes(b):
return b.to_bytes(curve.EFS, byteorder='big')
def from_bytes(B):
return int.from_bytes(B, byteorder='big')
# extract i-th bit
def bit(k, i):
if i == 0:
return k & 1
return ((k >> i) & 1)
# gcd
def gcd(x, y):
a = x
b = y
while b != 0:
a, b = b, a % b
return a
# inverse mod prime p
def invmodp(a, p):
n = p
x = a % n
kn = n
if x < 0:
x += n
if gcd(x, n) != 1:
return 0
a = 1
la = 0
while x > 1:
q, r = divmod(n, x)
t = la - a * q
la = a
a = t
n = x
x = r
if a < 0:
a += kn
return a
# Modular arithmetic
def modmul(a1, b1, p):
a = a1 % p
b = b1 % p
if a < 0:
a += p
if b < 0:
b += p
return a * b % p
def modadd(a, b, p):
c = a + b
if c >= p:
c -= p
return c
def modsub(a, b, p):
c = a - b
if c < 0:
c += p
return c
def moddiv(a, b, p):
i = invmodp(b, p)
if i != 0:
return modmul(a, i, p)
return 0
# modular square root. Fails spectacularly if p!=3 mod 4
def sqrtmodp(a, p):
if p % 4 == 3:
return pow(a, (p + 1) // 4, p)
if p % 8 == 5:
b = (p - 5) / 8
i = a * 2
v = pow(i, b, p)
i = modmul(i, v, p)
i = modmul(i, v, p)
i -= 1
r = modmul(a, v, p)
r = modmul(r, i, p)
return r
return 0
# chinese remainder theorem
def crt(rp, p, rq, q):
c = inverse(p, q)
t = modmult(c, rq - rp, q)
return t * p + rp
# find jacobi symbol for (x/p). Only defined for
# positive x and p, p odd. Otherwise returns 0
def jacobi(a, p):
if a < 1 or p < 2 or p % 2 == 0:
return 0
n = p
x = a % n
m = 0
while n > 1:
if x == 0:
return 0
n8 = n % 8
k = 0
while x % 2 == 0:
k += 1
x //= 2
if k % 2 == 1:
m += (n8 * n8 - 1) // 8
m += (n8 - 1) * (x % 4 - 1) // 4
t = n
t %= x
n = x
x = t
m %= 2
if m == 0:
return 1
else:
return -1
def rand(m):
return random.SystemRandom().randint(2, m - 1)