SCIP 1.27
Exercise 1.27 asks us to demonstrate that the first six Carmicheal numbers (561, 1105, 1729, 2465, 2821, and 6601) really do fool the Fermat test.
We're to write a procedure that takes an integer n and tests whether an is congruent to a modulo n for every value less than n,
then test the procedure on each of the Carmichael numbers listed.
(defun squre(x)
(* x x))
(defun even?(x)
(= (mod x 2) 0))
(defun doublef(x)
(+ x x))
(defun half(x)
(/ x 2))
(defun smallest-divisor (n)
(find-divisor n 2))
(defun nxt (x)
( if(= x 2)
3
(+ x 2)))
(defun find-divisor(n test-divisor)
(cond ((> (squre test-divisor) n) n )
(( divides? test-divisor n) test-divisor)
( (find-divisor n (nxt test-divisor)))))
(defun divides? (a b)
(= (mod b a) 0))
(defun prime? (n)
(= n (smallest-divisor n)))
(defun expmod (base exp m)
(cond ((= exp 0) 1)
((even? exp) (mod (squre (expmod base (/ exp 2) m))
m))
( (mod (* base (expmod base (- exp 1) m))
m))))
(defun try-it (a n)
(= (expmod a n n) a))
(defun fermat-full-test-iter(start n)
( cond ( (= start (- n 1)) t)
( (try-it start n) (fermat-full-test-iter (+ start 1) n))
( nil)))
(defun fermat-full-test(n)
(fermat-full-test-iter 1 n))
(defun fermat-test(n)
(try-it (+ 1 (random (- n 1))) n))
(defun fast-prime? (n times)
(cond ( (= times 0) t)
( (fermat-test n) (fast-prime? n (- times 1)))
( nil)))
(defun search-for-primes (start end use-fast-prime?)
( if(even? start)
(search-for-primes (+ start 1) end use-fast-prime?)
(cond ( (< start end) (timed-prime-test start use-fast-prime?)
(search-for-primes (+ start 2) end use-fast-prime?)))))
(defun timed-prime-test(n use-fast-prime?)
(start-prime-test n (get-internal-real-time) use-fast-prime?))
(defun start-prime-test(n start-time use-fast-prime?)
(if use-fast-prime?
(cond ( (fast-prime? n 250000) (report-prime n (- (get-internal-real-time) start-time))))
(cond ( (prime? n ) (report-prime n (- (get-internal-real-time) start-time))))))
(defun report-prime (n elapsed-time)
(format t "~%~d***~d millisecond" n elapsed-time))
(defun search-primes-under170 (start use-fast-prime?)
(search-for-primes start (+ start 200) use-fast-prime?))
CL-USER 127 > (fermat-full-test 561)
T
CL-USER 128 > (fermat-full-test 1105)
T
CL-USER 129 > (fermat-full-test 1729)
T
CL-USER 130 > (fermat-full-test 2465)
T
CL-USER 131 > (fermat-full-test 2821)
T
CL-USER 132 > (fermat-full-test 6601)
T
CL-USER 133 > (fermat-full-test 6602)
NIL
Edit and test in LispWorks 7.0.0 Professional edition.