; 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)