A simple prime-number bot, in python. WIP
mastodon
python
fediverse
bot
mathematics
prime-numbers

lucas.py 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. # Finding lucas pseudoprimes
  2. from math import sqrt, gcd
  3. def isqrt(n):
  4. """ Find the integer square root of n via newton's method, code via
  5. stackoverflow:
  6. (https://stackoverflow.com/questions/15390807/integer-square-root-in-python)
  7. """
  8. x = n
  9. y = (x + 1) // 2
  10. while y < x:
  11. x = y
  12. y = (x + n // x) // 2
  13. return x
  14. def hasIntSQRT(n):
  15. """Detect whether the square root of n is an integer,
  16. i.e. whether the isqrt(n) is the true square root.
  17. """
  18. isq = isqrt(n)
  19. return isq * isq == n
  20. def Dsequence():
  21. """Generate sequence 5, -7, 9, -11, 13, -15...
  22. """
  23. val = 5
  24. while True:
  25. if val % 4 == 1:
  26. yield val
  27. else:
  28. yield -val
  29. val = val + 2
  30. def Legendre(a, p):
  31. """Function for calculating Legendre symbol.
  32. Note that this is only supposed to be defined if p is an odd prime, but we
  33. don't know in advance if that is true - will therefore only throw and error
  34. if p is even.
  35. Uses original power definition from
  36. <https://en.wikipedia.org/wiki/Legendre_symbol>
  37. """
  38. if (p % 2 == 0):
  39. raise ValueError("p must be odd, is {}".format(p))
  40. lv = pow(a, (p-1)//2, p)
  41. if lv == p - 1:
  42. lv = -1
  43. return lv
  44. def Jacobi(a, n):
  45. """Function for calculating Jacobi symbol.
  46. Note that this is only defined for positive odd integers n.
  47. Uses algorithm from
  48. <https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol>
  49. """
  50. if n < 1:
  51. raise ValueError("n must be positive")
  52. if (n % 2 == 0):
  53. raise ValueError("n must be odd")
  54. if a % n != a:
  55. return Jacobi(a%n, n)
  56. if a != 0 and a % 2 == 0:
  57. nm8 = n % 8
  58. if (nm8 == 3 or nm8 == 5):
  59. return -1 * Jacobi(a//2, n)
  60. else:
  61. return Jacobi(a//2, n)
  62. if a == 1:
  63. return 1
  64. if gcd(a, n) != 1:
  65. return 0
  66. if a == 0 and n == 1:
  67. return 1
  68. if n % 4 == 3 and a % 4 == 3:
  69. return -1 * Jacobi(n, a)
  70. return Jacobi(n, a)
  71. def FirstD(n):
  72. """Return first D in the sequence 5, -7, 9, -11, 13, -15... for which the
  73. Jacobi symbol (D/n) is -1
  74. """
  75. if hasIntSQRT(n):
  76. raise ValueError("n must not be a square")
  77. if n < 1 or n % 2 == 0:
  78. raise ValueError("n must be a positive odd number")
  79. for D in Dsequence():
  80. if Jacobi(D/n) == -1:
  81. return D
  82. # Shouldn't fire
  83. return 0
  84. def Lucas(n, p, q):
  85. """Function for generating values of a lucas sequence with parameters p, q.
  86. Via formula at <https://en.wikipedia.org/wiki/Lucas_sequence>
  87. """
  88. if n < 0:
  89. raise ValueError("n must be a non-negative integer")
  90. if n == 0:
  91. return 0, 2
  92. Unm1, Vnm1 = Lucas(n - 1, p, q)
  93. Un = (p * Unm1 + Vnm1) // 2
  94. Vn = ((p * p - 4 * q) * Unm1 + p * Vnm1) // 2
  95. return Un, Vn
  96. def LucasUn(n, p, q):
  97. """Return only the U numbers from a lucas sequence Un(P, Q). For example if
  98. P = 1, and Q = -1 this will return the Fibonacci numbers; if P = 3 and Q =
  99. 2 then it returns the Mersenne numbers etc.
  100. """
  101. return Lucas(n, p, q)[0]
  102. def LucasVn(n, p, q):
  103. """Return only V numbers from a local sequence Vn(P, Q).
  104. """
  105. return Lucas(n, p, q)[1]
  106. def LucasFast(k, p, q, n):
  107. if k < 0:
  108. raise ValueError("k must be a non-negative integer")
  109. if n < 1:
  110. raise ValueError("n must be a postive integer")
  111. uc, vc = Lucas(1, p, q)
  112. dk = floor(log(k, 2))
  113. tp = 2**dk
  114. for i in range(dk):