123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- (library (lib rabin-miller-test)
- (export
- rabin-miller-test)
- (import
- (except (rnrs base) let-values)
- (only (guile)
- lambda* λ
- remainder)
- (srfi srfi-1))
- ;; It is sufficient to check numbers with the following prime numbers as witnesses up to:
- ;; n < 3.317.044.064.679.887.385.961.981
- ;; This number is larger than 64bit integer range.
- ;; https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
- (define SIGNIFICANT-PRIMES (list 2 3 5 7 11 13 17 19 23 29 31 37 41))
- (define square
- (λ (x)
- (* x x)))
- (define halve
- (λ (x)
- (/ x 2)))
- (define divides?
- (λ (a b)
- (= (remainder b a) 0)))
- (define even?
- (λ (n)
- (divides? 2 n)))
- (define (next n)
- (cond
- ((< n 2) 2)
- ((even? n) (+ n 1))
- (else (+ n 2))))
- (define one-rabin-miller-check
- (λ (base exp m)
- "This is the actual test for non-trivial square roots of
- 1 congruent regarding m."
- (cond
- [(= exp 0) 1]
- [(even? exp)
- ;; If the exponent is an even number, we can halve
- ;; it, and the squaring happens outside! Why this
- ;; is possible? Check the rabin-miller-test.pdf /
- ;; .odt.
- (remainder (square (one-rabin-miller-check base
- (halve exp)
- m))
- m)]
- [else
- ;; in the else branch we take a factor outside instead:
- (remainder (* base (one-rabin-miller-check base
- (- exp 1)
- m))
- m)])))
- (define rabin-miller-test-single-significant-prime
- (λ (number-to-check a)
- "This procedure is only for calling
- one-rabin-miller-check with the correct parameters."
- (cond
- [(> 1 number-to-check) #f] ; safeguard against 0 or lower parameter
- [else
- (= (one-rabin-miller-check a
- (- number-to-check 1)
- number-to-check)
- 1)])))
- (define rabin-miller-test
- (λ (potential-prime significant-primes)
- (let iter ([number-to-check potential-prime]
- [remaining-significant-primes significant-primes])
- (cond
- [(null? remaining-significant-primes) #t]
- [else
- (let ([current-significant-prime
- (first remaining-significant-primes)])
- (cond
- [(>= current-significant-prime number-to-check) #t]
- [(rabin-miller-test-single-significant-prime
- number-to-check
- current-significant-prime)
- (iter number-to-check
- (drop remaining-significant-primes 1))]
- [else #f]))])))))
- ;; (define find-primes-limited
- ;; (λ (min max)
- ;; (cond
- ;; [(< min max)
- ;; (cond
- ;; [(rabin-miller-test min)
- ;; ;; test successful, number is prime according to
- ;; ;; test guaranteed to be true up to:
- ;; ;; n < 3.317.044.064.679.887.385.961.981
- ;; (display "prime:")(displayln min)
- ;; (find-primes-limited (next min) max)]
- ;; [else
- ;; (find-primes-limited (next min) max)])]
- ;; [else
- ;; (displayln "finished")])))
- ;; (time (find-primes-limited 0 1000000)))
|