rabin-miller-test.scm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. (library (lib rabin-miller-test)
  2. (export
  3. rabin-miller-test)
  4. (import
  5. (except (rnrs base) let-values)
  6. (only (guile)
  7. lambda* λ
  8. remainder)
  9. (srfi srfi-1))
  10. ;; It is sufficient to check numbers with the following prime numbers as witnesses up to:
  11. ;; n < 3.317.044.064.679.887.385.961.981
  12. ;; This number is larger than 64bit integer range.
  13. ;; https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
  14. (define SIGNIFICANT-PRIMES (list 2 3 5 7 11 13 17 19 23 29 31 37 41))
  15. (define square
  16. (λ (x)
  17. (* x x)))
  18. (define halve
  19. (λ (x)
  20. (/ x 2)))
  21. (define divides?
  22. (λ (a b)
  23. (= (remainder b a) 0)))
  24. (define even?
  25. (λ (n)
  26. (divides? 2 n)))
  27. (define (next n)
  28. (cond
  29. ((< n 2) 2)
  30. ((even? n) (+ n 1))
  31. (else (+ n 2))))
  32. (define one-rabin-miller-check
  33. (λ (base exp m)
  34. "This is the actual test for non-trivial square roots of
  35. 1 congruent regarding m."
  36. (cond
  37. [(= exp 0) 1]
  38. [(even? exp)
  39. ;; If the exponent is an even number, we can halve
  40. ;; it, and the squaring happens outside! Why this
  41. ;; is possible? Check the rabin-miller-test.pdf /
  42. ;; .odt.
  43. (remainder (square (one-rabin-miller-check base
  44. (halve exp)
  45. m))
  46. m)]
  47. [else
  48. ;; in the else branch we take a factor outside instead:
  49. (remainder (* base (one-rabin-miller-check base
  50. (- exp 1)
  51. m))
  52. m)])))
  53. (define rabin-miller-test-single-significant-prime
  54. (λ (number-to-check a)
  55. "This procedure is only for calling
  56. one-rabin-miller-check with the correct parameters."
  57. (cond
  58. [(> 1 number-to-check) #f] ; safeguard against 0 or lower parameter
  59. [else
  60. (= (one-rabin-miller-check a
  61. (- number-to-check 1)
  62. number-to-check)
  63. 1)])))
  64. (define rabin-miller-test
  65. (λ (potential-prime significant-primes)
  66. (let iter ([number-to-check potential-prime]
  67. [remaining-significant-primes significant-primes])
  68. (cond
  69. [(null? remaining-significant-primes) #t]
  70. [else
  71. (let ([current-significant-prime
  72. (first remaining-significant-primes)])
  73. (cond
  74. [(>= current-significant-prime number-to-check) #t]
  75. [(rabin-miller-test-single-significant-prime
  76. number-to-check
  77. current-significant-prime)
  78. (iter number-to-check
  79. (drop remaining-significant-primes 1))]
  80. [else #f]))])))))
  81. ;; (define find-primes-limited
  82. ;; (λ (min max)
  83. ;; (cond
  84. ;; [(< min max)
  85. ;; (cond
  86. ;; [(rabin-miller-test min)
  87. ;; ;; test successful, number is prime according to
  88. ;; ;; test guaranteed to be true up to:
  89. ;; ;; n < 3.317.044.064.679.887.385.961.981
  90. ;; (display "prime:")(displayln min)
  91. ;; (find-primes-limited (next min) max)]
  92. ;; [else
  93. ;; (find-primes-limited (next min) max)])]
  94. ;; [else
  95. ;; (displayln "finished")])))
  96. ;; (time (find-primes-limited 0 1000000)))