You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
1.5 KiB

  1. # Chinese Remainder Theorem
  2. def crt(a_i, m_i, M):
  3. if len(a_i)!=len(m_i):
  4. raise Exception("error, a_i and m_i must be of the same length")
  5. x = 0
  6. for i in range(len(a_i)):
  7. M_i = M/m_i[i]
  8. y_i = Integer(mod(M_i^-1, m_i[i]))
  9. x = x + a_i[i] * M_i * y_i
  10. return mod(x, M)
  11. # gcd, using Binary Euclidean algorithm
  12. def gcd(a, b):
  13. g=1
  14. # random_elementove powers of two from the gcd
  15. while mod(a, 2)==0 and mod(b, 2)==0:
  16. a=a/2
  17. b=b/2
  18. g=2*g
  19. # at least one of a and b is now odd
  20. while a!=0:
  21. while mod(a, 2)==0:
  22. a=a/2
  23. while mod(b, 2)==0:
  24. b=b/2
  25. # now both a and b are odd
  26. if a>=b:
  27. a = (a-b)/2
  28. else:
  29. b = (b-a)/2
  30. return g*b
  31. def gcd_recursive(a, b):
  32. if mod(a, b)==0:
  33. return b
  34. return gcd_recursive(b, mod(a,b))
  35. # Extended Euclidean algorithm
  36. # Inputs: a, b
  37. # Outputs: r, x, y, such that r = gcd(a, b) = x*a + y*b
  38. def egcd(a, b):
  39. s=0
  40. s_=1
  41. t=1
  42. t_=0
  43. r=b
  44. r_=a
  45. while r!=0:
  46. q = r_ // r
  47. (r_,r) = (r,r_ - q*r)
  48. (s_,s) = (s,s_ - q*s)
  49. (t_,t) = (t,t_ - q*t)
  50. d = r_
  51. x = s_
  52. y = t_
  53. return d, x, y
  54. def egcd_recursive(a, b):
  55. if b==0:
  56. return a, 1, 0
  57. g, x, y = egcd_recursive(b, a%b)
  58. return g, y, x - (a//b) * y
  59. # Inverse modulo N, using the Extended Euclidean algorithm
  60. def inv_mod(a, N):
  61. g, x, y = egcd(a, N)
  62. if g != 1:
  63. raise Exception("inv_mod err, g!=1")
  64. return mod(x, N)