fork download
  1. ; primitive roots
  2.  
  3. (define (factors n) ; 2,3,5-wheel
  4. (let ((wheel (vector 1 2 2 4 2 4 2 4 6 2 6)))
  5. (let loop ((n n) (f 2) (w 0) (fs (list)))
  6. (if (< n (* f f)) (reverse (cons n fs))
  7. (if (zero? (modulo n f))
  8. (loop (/ n f) f w (cons f fs))
  9. (loop n (+ f (vector-ref wheel w))
  10. (if (= w 10) 3 (+ w 1)) fs))))))
  11.  
  12. (define (unique eql? xs)
  13. (cond ((null? xs) '())
  14. ((null? (cdr xs)) xs)
  15. ((eql? (car xs) (cadr xs))
  16. (unique eql? (cdr xs)))
  17. (else (cons (car xs) (unique eql? (cdr xs))))))
  18.  
  19. (define (expm b e m)
  20. (define (m* x y) (modulo (* x y) m))
  21. (cond ((zero? e) 1)
  22. ((even? e) (expm (m* b b) (/ e 2) m))
  23. (else (m* b (expm (m* b b) (/ (- e 1) 2) m)))))
  24.  
  25. (define (prim-roots p)
  26. (let ((fs (unique = (factors (- p 1)))))
  27. (let loop ((a 1) (ps fs))
  28. (if (pair? ps)
  29. (if (= (expm a (/ (- p 1) (car ps)) p) 1)
  30. (loop (+ a 1) fs) ; try next a
  31. (loop a (cdr ps)))
  32. (let loop ((m 1) (rs (list)))
  33. (if (= m p) (sort rs <)
  34. (if (= (gcd m (- p 1)) 1)
  35. (loop (+ m 1) (cons (expm a m p) rs))
  36. (loop (+ m 1) rs))))))))
  37.  
  38. (display (prim-roots 47)) (newline)
Success #stdin #stdout 0.02s 50288KB
stdin
Standard input is empty
stdout
(5 10 11 13 15 19 20 22 23 26 29 30 31 33 35 38 39 40 41 43 44 45)