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.

110 lines
2.1 KiB

5 years ago
  1. '''
  2. Created on Dec 22, 2011
  3. @author: pablocelayes
  4. '''
  5. def egcd(a,b):
  6. '''
  7. Extended Euclidean Algorithm
  8. returns x, y, gcd(a,b) such that ax + by = gcd(a,b)
  9. '''
  10. u, u1 = 1, 0
  11. v, v1 = 0, 1
  12. while b:
  13. q = a // b
  14. u, u1 = u1, u - q * u1
  15. v, v1 = v1, v - q * v1
  16. a, b = b, a - q * b
  17. return u, v, a
  18. def gcd(a,b):
  19. '''
  20. 2.8 times faster than egcd(a,b)[2]
  21. '''
  22. a,b=(b,a) if a<b else (a,b)
  23. while b:
  24. a,b=b,a%b
  25. return a
  26. def modInverse(e,n):
  27. '''
  28. d such that de = 1 (mod n)
  29. e must be coprime to n
  30. this is assumed to be true
  31. '''
  32. return egcd(e,n)[0]%n
  33. def totient(p,q):
  34. '''
  35. Calculates the totient of pq
  36. '''
  37. return (p-1)*(q-1)
  38. def bitlength(x):
  39. '''
  40. Calculates the bitlength of x
  41. '''
  42. assert x >= 0
  43. n = 0
  44. while x > 0:
  45. n = n+1
  46. x = x>>1
  47. return n
  48. def isqrt(n):
  49. '''
  50. Calculates the integer square root
  51. for arbitrary large nonnegative integers
  52. '''
  53. if n < 0:
  54. raise ValueError('square root not defined for negative numbers')
  55. if n == 0:
  56. return 0
  57. a, b = divmod(bitlength(n), 2)
  58. x = 2**(a+b)
  59. while True:
  60. y = (x + n//x)//2
  61. if y >= x:
  62. return x
  63. x = y
  64. def is_perfect_square(n):
  65. '''
  66. If n is a perfect square it returns sqrt(n),
  67. otherwise returns -1
  68. '''
  69. h = n & 0xF; #last hexadecimal "digit"
  70. if h > 9:
  71. return -1 # return immediately in 6 cases out of 16.
  72. # Take advantage of Boolean short-circuit evaluation
  73. if ( h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8 ):
  74. # take square root if you must
  75. t = isqrt(n)
  76. if t*t == n:
  77. return t
  78. else:
  79. return -1
  80. return -1
  81. #TEST functions
  82. def test_is_perfect_square():
  83. print("Testing is_perfect_square")
  84. testsuit = [4, 0, 15, 25, 18, 901, 1000, 1024]
  85. for n in testsuit:
  86. print("Is ", n, " a perfect square?")
  87. if is_perfect_square(n)!= -1:
  88. print("Yes!")
  89. else:
  90. print("Nope")
  91. if __name__ == "__main__":
  92. test_is_perfect_square()