def main(): print "Linear congruences (ax = b mod m)" print "" print "Enter a:", A = bigInt.bigInt(raw_input()) print "Enter b:", B = bigInt.bigInt(raw_input()) print "Enter m:", M = bigInt.bigInt(raw_input()) if (A < 0) or (B < 0) or (M <= 0): print "A and B must be positive!" print "Modulus must be > 0" return A = A % M B = B % M print A, "* x =", B, "mod", M isSolved, x = algs.LinCon(A, B, M) if isSolved: if x == -1: print "x - any" else: # решений может быть несколько x.sort() print "x =", x else: print "No solution"
def GCDEx(a, b): if b == 0: return a, 1, 0 if a == 0: return b, 1, 0 x1 = bigInt.bigInt(0) x2 = bigInt.bigInt(1) y1 = bigInt.bigInt(1) y2 = bigInt.bigInt(0) while b != 0: q = a / b r = a % b a = b b = r xx = x2 - x1 * q yy = y2 - y1 * q x2 = x1 x1 = xx y2 = y1 y1 = yy x = x2 y = y2 return a, x, y
def main(): print "Pollard's rho algorithm for logarithms (a^x = b mod m)" print "" print "Input: a, b, m (prime)" print "Ouput: x\n" print "Enter a:", a = bigInt.bigInt(raw_input()) print "Enter b:", b = bigInt.bigInt(raw_input()) print "Enter m:", m = bigInt.bigInt(raw_input()) if not algs.isPrime(m): print "m must be prime!" return print "" print a, "^ x =", b, "mod", m x = algs.RhoPollard(a, b, m) # if x == None: # print "No solution" # else: # print "x = ", x # print "x =", x
def RhoPollard(alpha, beta, N): n = N - 1 x = bigInt.bigInt(1) a = bigInt.bigInt(0) b = bigInt.bigInt(0) X = x A = a B = b i = bigInt.bigInt(1) while (i < n): x, a, b = new_xab( x, a, b, n, N, alpha, beta ) X, A, B = new_xab( X, A, B, n, N, alpha, beta ) X, A, B = new_xab( X, A, B, n, N, alpha, beta ) i += 1 if( x == X and i > 2): if (B - b) == 0: return None Bb = B - b Aa = A - a if Bb < 0: Bb = b - B if Aa < 0: Aa = a - A isSolved, res = LinCon(Bb, Aa, n) if not isSolved: return None if res == -1: return None return res[0]
def main(): print "Square root modulo a prime ( x^2 = a mod p (p - prime) )" print "" print "Input: a, p (odd prime)" print "Output: x: x^2 = a mod p\n" print "Enter a:", a = bigInt.bigInt(raw_input()) print "Enter p:", p = bigInt.bigInt(raw_input()) if p < 3: print "p must be odd prime!" return if not algs.isPrime(p): print "p must be prime!" return a = a % p if a < 0: a += p if a == 0: print "x = 0" return isSolution, res = algs.SqrtPrime(a, p) if not isSolution: print "\nNo solution" return print "\nx =", res
def getFromFiles (fileA, fileB, fileMod, binary): A = bigInt.bigInt() B = bigInt.bigInt() modulus = bigInt.bigInt() if (binary): if not A.getFromBinFile(fileA): print "Can't get number from:", fileA return False, A, B, modulus if not B.getFromBinFile(fileB): print "Can't get number from:", fileB return False, A, B, modulus if fileMod: if not modulus.getFromBinFile(fileMod): print "Can't get number from:", fileMod return False, A, B, modulus else: if not A.getFromTextFile(fileA): print "Can't get number from:", fileA return False, A, B, modulus if not B.getFromTextFile(fileB): print "Can't get number from:", fileB return False, A, B, modulus if fileMod: if not modulus.getFromTextFile(fileMod): print "Can't get number from:", fileMod return False, A, B, modulus return True, A, B, modulus
def JacobiSym (a, p): if GCD (a, p) != 1: return 0 r = bigInt.bigInt(1) if a < 0: a = -a if p % 4 == 3: r = -r while (a != 0): t = bigInt.bigInt(0) while a % 2 == 0: t += 1 a = a / 2 if t % 2 == 1: if p % 8 == 3 or p % 8 == 5: r = -r if a % 4 == 3 and p % 4 == 3: r = -r c = a a = p % c p = c return r
def main(): print "Euclid's algorithm for computing the greatest common divisor ( GCD(A, B) )" print "" print "Enter A:", A = bigInt.bigInt(raw_input()) print "Enter B:", B = bigInt.bigInt(raw_input()) print "GCD (", A, ",", B, ") =", algs.GCD(A, B)
def main(): print "Legendre symbol ( L(a, p) )" print "" print "Input: a, p (prime)" print "Output: L(a, p)\n" print "Enter a:", a = bigInt.bigInt(raw_input()) print "Enter p:", p = bigInt.bigInt(raw_input()) print "\nL(", a, ",", p, ") =", algs.LegSym(a, p)
def main(): print "Jacobi symbol ( J(a, p) )" print "" print "Input: a, p" print "Output: J(a, p)\n" print "Enter a:", a = bigInt.bigInt(raw_input()) print "Enter p:", p = bigInt.bigInt(raw_input()) print "\nJ(", a, ",", p, ") =", algs.JacobiSym(a, p)
def main(): print "Chinese remainder theorem" print "" print "X = R1 (mod A1)" print "X = R2 (mod A2)" print ". . . . . . . ." print "X = Rn (mod An)" print "X (mod A1 * ... * A2) - ?\n" print "Input: n, Ri, Ai (i = 1 .. n)" print "Output: X\n" print "Enter n:", n = int (input()) R = [0] * n A = [0] * n # Ввод Ri, Ai for i in range (n): print '\nEnter R%d:' % (i + 1), Ri = bigInt.bigInt(raw_input()) print 'Enter A%d:' % (i + 1), Ai = bigInt.bigInt(raw_input()) if Ai < 2: print "Modulus must be > 1!" return Ri %= Ai if Ri < 0: Ri += Ai R[i] = Ri A[i] = Ai # Проверка на попарную простоту Ai i = 0 isSimplePairwise = True while i != n and isSimplePairwise: j = i + 1 while j != n and isSimplePairwise: if algs.GCD(A[i], A[j]) != 1: isSimplePairwise = False j += 1 i += 1 if not isSimplePairwise: print "Modules (Ai) must be simple pairwise!" return print "" for i in range (n): print "X =", R[i], "mod", A[i] print "\nX =", algs.ChinRemTheorem(R, A)
def ChinRemTheorem(R, A): "Решение системы уравнений по китайской теореме об остатках" M = bigInt.bigInt(1) for Ai in A: M *= Ai x = bigInt.bigInt(0) for i in range(len(A)): Mi = M / A[i] isOK, invArr = LinCon (Mi, bigInt.bigInt(1), A[i]) # нахождение обратного для Mi MiInv = invArr[0] # в общем случае, у элемента может быть (?) несколько обратных, поэтому берём первый x = (x + R[i] * Mi * MiInv) % M return x
def GCDBin(a, b): if (a < b): return GCDBin (b, a) if a < 0: a = -a if b < 0: b = -b if b == 0: return a if a == 0: return b g = bigInt.bigInt(1) while (a % 2 == 0) and (b % 2 == 0): a /= 2 b /= 2 g *= 2 while a != 0: while a % 2 == 0: a /= 2 while b % 2 == 0: b /= 2 if a >= b: a = a - b else: b = b - a return g * b
def main(): print "Exponentiation modulo (a^b mod m)" print "" print "Enter base (a):", A = bigInt.bigInt(raw_input()) print "Enter power (b):", B = bigInt.bigInt(raw_input()) print "Enter modulus (m):", M = bigInt.bigInt(raw_input()) if (A < 0) or (B < 0) or (M <= 0): print "A and B must be positive!" print "Modulus must be > 0" return print A, "^", B, "mod", M, "=", algs.PowMod(A, B, M)
def main(): print "Extended Euclid's algorithm for computing the greatest common divisor ( GCD(A, B) )" print "" print "Enter A:", A = bigInt.bigInt(raw_input()) print "Enter B:", B = bigInt.bigInt(raw_input()) if (A < 0) or (B < 0): print "A and B must be positive!" return if A > B: GCD, X, Y = algs.GCDEx(A, B) else: GCD, Y, X = algs.GCDEx(B, A) print "GCD (", A, ",", B, ") =", GCD, "=", X, "*", A, "+", Y, "*", B
def GarnersAlg(R, A): "Решение системы линейных сравнений по алгоритму Гарнера" # инициализируем массив inverses, inverses[j,i] = aj^(-1) mod ai inverses = [] for i in range(len(A)): inverses.append([bigInt.bigInt(0)] * len(A)) for i in range (len(A)): for j in range (i): isOK, invArr = LinCon (A[j], bigInt.bigInt(1), A[i]) # нахождение обратного для A[i] inverses[j][i] = invArr[0] # подсчитываем коэффициенты по алгоритму Гарнера x = [bigInt.bigInt(0)] * len(A) for i in range (len(A)): x[i] = R[i] for j in range (i): x[i] = inverses[j][i] * (x[i] - x[j]) x[i] = x[i] % A[i]; if x[i] < 0: x[i] += A[i] return x
def noArguments(): print "Launched without parameters." print "Perform all kind of operations with entered numbers." print "Enter A:", a = bigInt.bigInt(raw_input()) print "Enter B:", b = bigInt.bigInt(raw_input()) print "A + B =", a, "+", b, "=", a + b print "A - B =", a, "-", b, "=", a - b print "A * B =", a, "*", b, "=", a * b if b != bigInt.bigInt("0"): print "A / B =", a, "/", b, "=", a / b print "A % B =", a, "%", b, "=", a % b else: print "Division by zero" print "Enter modulus for pow: ", mod = bigInt.bigInt(raw_input()) print "A ^ B mod N =", a, "^", b, "mod", mod, "=", bigInt.pow(a, b, mod) print "That's all"
def process(A, B, modulus, operation): zero = bigInt.bigInt("0") res = zero if (modulus < zero): print "Negative modulus!" return False, res if operation == '^': res = bigInt.pow(A, B, modulus) return True, res if (modulus > zero): A %= modulus B %= modulus if operation == '+': res = A + B elif operation == '-': res = A - B elif operation == '*': res = A * B elif operation == '/': if B == zero: print "Division by zero" return False, res res = A / B elif operation == '%': if (B == zero): print "Division by zero" return False, res res = A % B if (modulus > zero): res %= modulus while (res < zero): res += modulus return True, res
def main(): print "Quadratic congruences modulo a prime ( ax^2 + bx + c = 0 mod p )" print "" print "Input: a, b, c, p (odd prime)" print "Output: x:\n" print "Enter a:", a = bigInt.bigInt(raw_input()) print "Enter b:", b = bigInt.bigInt(raw_input()) print "Enter c:", c = bigInt.bigInt(raw_input()) print "Enter p:", p = bigInt.bigInt(raw_input()) if p < 3: print "p must be odd prime!" return if not algs.isPrime(p): print "p must be prime!" return a = a % p if a < 0: a += p b = b % p if b < 0: b += p c = c % p if c < 0: c += p if a == 0: print "This is linear congruence" c = p - c print b, "* x =", c, "mod", p isSolved, x = algs.LinCon(b, c, p) if isSolved: if x == -1: print "x - any" else: # решений может быть несколько x.sort() print "x =", x else: print "No solution" return # сокращаем на коэффициент a: # Вычисляем invA = a^(-1)mod p - обратный элемент в кольце Zp isOK, invArr = algs.LinCon (a, bigInt.bigInt(1), p) invA = invArr[0] b = (b * invA) % p c = (c * invA) % p if (b % 2 == 0): # делаем замену # y = x + b/2 # a = (b1/2)^2 - c # и получаем уравнение y^2 = a # решаем его if ((b/2 * b/2 - c) % p == 0): print "x =", (p + 1)/2 return isSolved, y = algs.SqrtPrime ( (b/2 * b/2 - c) % p, p) if not isSolved: print "No solution" return res = [0]*2 res[0] = (y[0] - b/2) % p res[1] = (y[1] - b/2) % p else: # делаем замену # y = x + (b + p)/2 # a = ((b + p) / 2)^2 - c isSolved, y = algs.SqrtPrime ( ((b + p)/2 * (b + p)/2 - c) % p , p) if not isSolved: print "No solution" return res = [0]*2 res[0] = (y[0] - (b + p)/2) % p res[1] = (y[1] - (b + p)/2) % p if res[0] < 0: res[0] += p if res[1] < 0: res[1] += p print "\nx =", res
def main(): print "Garner's algorithm" print "" print "X = R1 (mod A1)" print "X = R2 (mod A2)" print ". . . . . . . ." print "X = Rn (mod An)" print "X = x1 + x2 * a1 + ... + xn * a1 * ... * a(n-1) - ?" print "Input: n, Ri, Ai (i = 1 .. n)" print "Output: X, xi\n" print "Enter n:", n = int (input()) R = [0] * n A = [0] * n # Ввод Ri, Ai for i in range (n): print '\nEnter R%d:' % (i + 1), Ri = bigInt.bigInt(raw_input()) print 'Enter A%d:' % (i + 1), Ai = bigInt.bigInt(raw_input()) if Ai < 2: print "Modulus must be > 1!" return Ri %= Ai if Ri < 0: Ri += Ai R[i] = Ri A[i] = Ai # Проверка на попарную простоту Ai i = 0 isSimplePairwise = True while i != n and isSimplePairwise: j = i + 1 while j != n and isSimplePairwise: if algs.GCD(A[i], A[j]) != 1: isSimplePairwise = False j += 1 i += 1 if not isSimplePairwise: print "Modules (Ai) must be simple pairwise!" return print "" for i in range (n): print "X =", R[i], "mod", A[i] print "" x = algs.GarnersAlg(R, A) # получаем массив коэффициентов xi coefAi = bigInt.bigInt(1) # a1 * a2 * ... a(i-1) res = bigInt.bigInt(0) # X = x1 * a1 + ... print "X =", for i in range (len(x)): res = res + x[i] * coefAi print x[i], "*", coefAi, if i != n - 1: print "+", coefAi *= A[i] print "=", res
def test_add(self): a = bigInt.bigInt([1, 0]) b = bigInt.bigInt([1, 1, 0]) a.add(b) result = a.getNumberString() self.assertEqual(result, "120")
def SqrtPrime (a, p): "Нахождение квадратного корня по модулю простого числа по алгоритму Тонелли-Шенкса" if a == 0: return False, 0 # проверка, есть ли вообще решение if JacobiSym(a, p) == -1: return False, 0 # находим b такое что (b,p)=-1 b = bigInt.bigInt(2) while (JacobiSym(b, p) == 1): b += 1 # Представляем p-1 в виде p-1 = 2^s*t, где t - нечетное t = p - 1 s = bigInt.bigInt(0) while (t % 2 == 0): t /= 2 s += 1 # по методичке Шитова # # Вычисляем a2 = a^(-1)mod p - обратный элемент в кольце Zp # isOK, invArr = LinCon (a, bigInt.bigInt(1), p) # a2 = invArr[0] # # N1 = PowMod (b, t, p) # a1 = PowMod (a, (t + 1)/2, p) # N2 = bigInt.bigInt(1) # j = 0 # # i = bigInt.bigInt(0) # while i < s - 1: # b = (a1 * N2) % p # c = (a2 * b * b) % p # # e = PowMod(bigInt.bigInt(2), s - 2 - i, p) # d = PowMod (c, e, p) # # if d == 1: # j = 0 # if d == p - 1: # j = 1 # e = PowMod(bigInt.bigInt(2), i, p) # e *= j # N2 = (N2 * PowMod(N1, e, p)) % p # print "i =",i, "b =", b, "c =", c, "d =", d, "j =", j, "N2 =", N2 # i += 1 # r = (a1 * N2) % p # res = [r, p - r] # res.sort() # return True, res # Вычисляем invA = a^(-1)mod p - обратный элемент в кольце Zp isOK, invArr = LinCon (a, bigInt.bigInt(1), p) invA = invArr[0] c = PowMod (b, t, p) r = PowMod (a, (t + 1)/2, p) i = bigInt.bigInt(1) while i < s: # вычисляем d=[(r^2*invA)^(2^(s-i-1))][mod p] e = PowMod(bigInt.bigInt(2), s - i - 1, p) d = PowMod(r*r * invA, e, p) print "d =", d if d == p - 1: r = (r * c) % p c = (c * c) % p i += 1 res = [r, p - r] res.sort() return True, res