; proth primes and sierpinski numbers
(define (expm b e m)
(define (m* x y) (modulo (* x y) m))
(cond ((zero? e) 1)
((even? e) (expm (m* b b) (/ e 2) m))
(else (m* b (expm (m* b b) (/ (- e 1) 2) m)))))
(define (jacobi a m)
(if (not (integer? a)) (error 'jacobi "must be integer")
(if (not (and (integer? m) (positive? m) (odd? m)))
(error 'jacobi "modulus must be odd positive integer")
(let loop1 ((a (modulo a m)) (m m) (t 1))
(if (zero? a) (if (= m 1) t 0)
(let ((z (if (member (modulo m 8) (list 3 5)) -1 1)))
(let loop2 ((a a) (t t))
(if (even? a) (loop2 (/ a 2) (* t z))
(loop1 (modulo m a) a
(if (and (= (modulo a 4) 3)
(= (modulo m 4) 3))
(- t) t))))))))))
(define (proth? n)
(let loop ((a '(3 5 7 17)))
(if (null? a) #f
(if (not (= (jacobi (car a) n) -1)) (loop (cdr a))
(if (= (expm (car a) (/ (- n 1) 2) n) (- n 1)) #t
(loop (cdr a)))))))
(define (proth k limit)
(do ((k2n (* k 2) (* k2n 2)) (n 1 (+ n 1))) ((< limit n))
(when (proth? (+ k2n 1)) (display n) (newline))))
(proth 12909 1000)