-
Notifications
You must be signed in to change notification settings - Fork 4
/
ex1-28-miller-rabin.scm
99 lines (73 loc) · 2.16 KB
/
ex1-28-miller-rabin.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
; Ex. 1.28 Miller-Rabin test for prime numbers, that cannot be
; fooled by numbers like Carmichael numbers. This relies on a
; modified form of Fermat's little theorem which states that:
; if n is prime
; and 0 < a < n
; then a^(n-1) modulo n is congruent to 1 modulo n
(define (fast-prime? n times)
(cond ((= times 0) true)
((miller-rabin-test n) (fast-prime? n (- times 1)))
(else false)))
; Note how the argument passed to try-it has been changed. This is
; required to ensure that not only is the value non-zero, but also
; that it is at most equal to (- n 1).
(define (miller-rabin-test n)
(define (try-it a)
; n is not prime if a^(n-1) mod n equals 1 mod n
(= (expmod a (- n 1) n) 1)) ; false if n is not prime
(if (or (= n 1) (= n 2))
true
(try-it (+ 2 (random (- n 2)))))) ; any a where 0 < a < n
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(square-check (expmod base (/ exp 2) m) m))
(else
(remainder (* base (expmod base (- exp 1) m)) m))))
; (define (square n)
; (* n n))
; By redefining squaer as follows, we get a square-check operator
; that, when used in the expmod procedure will "wait" for a value
; to be generated. However, this will increase the number of
; deferred computations in the expmod procedure.
(define (square-check x m)
(if (and (not (or (= x 1) (= x (- m 1))))
(= (remainder (* x x) m) 1))
0
(remainder (* x x) m)))
(define (even? n)
(= (remainder n 2) 0))
; Sample output:
; (fast-prime? 1 100)
; ;Value: #t
; (fast-prime? 2 100)
; ;Value: #t
; (fast-prime? 3 100)
; ;Value: #t
; (fast-prime? 4 100)
; ;Value: #f
; (fast-prime? 5 100)
; ;Value: #t
; (fast-prime? 6 100)
; ;Value: #f
; (fast-prime? 7 100)
; ;Value: #t
; (fast-prime? 8 100)
; ;Value: #f
; (fast-prime? 9 100)
; ;Value: #f
; (fast-prime? 10 100)
; ;Value: #f
; ; Carmichaels Numbers:
; (fast-prime? 561 100)
; ;Value: #f
; (fast-prime? 1105 100)
; ;Value: #f
; (fast-prime? 1729 100)
; ;Value: #f
; (fast-prime? 2465 100)
; ;Value: #f
; (fast-prime? 2821 100)
; ;Value: #f
; (fast-prime? 6601 100)
; ;Value: #f