primes.scm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. ;; prime utility functions
  2. (define-module (euler primes))
  3. (use-modules (srfi srfi-1)
  4. (rnrs sorting)
  5. (euler utils))
  6. ;; TODO: make vect smaller, and add page segmentation for larger prime values
  7. (define-public (erato limit)
  8. (let [(prime-bitvect (erato-bit limit))]
  9. (prime-bitvector->lst prime-bitvect)))
  10. (define-public (prime-bitvector->lst prime-bitvect)
  11. (let lp ([i (1- (bitvector-length prime-bitvect))]
  12. [primes '()])
  13. (if (zero? i) primes
  14. (lp (1- i)
  15. (if (bitvector-ref prime-bitvect i)
  16. (cons i primes)
  17. primes)))))
  18. (define-public (erato-bit limit)
  19. (define vect (make-bitvector (1+ limit) #t))
  20. (bitvector-set! vect 0 #f)
  21. (bitvector-set! vect 1 #f)
  22. (do [(p 2 (1+ p))]
  23. [(> p (sqrt limit))]
  24. (when (bitvector-ref vect p)
  25. (do [(mul (+ p p) (+ mul p))]
  26. [(> mul limit)]
  27. (bitvector-set! vect mul #f))))
  28. vect)
  29. ;; Good up to around (expt 10 4)
  30. (define-public (primes-in-range limit)
  31. (let loop ((curr 3) (primes '(2)))
  32. (if (> curr limit) (reverse primes)
  33. (loop (+ 2 curr)
  34. (if (fold-and (lambda (prime)
  35. (not (= 0 (modulo curr prime))))
  36. primes)
  37. (cons curr primes)
  38. primes)))))
  39. (define-public (first-n-primes n)
  40. (let ([generator (make-prime-generator)])
  41. (let lp ([i n] [acc '()])
  42. (if (zero? i) (reverse acc)
  43. (lp (1- i) (cons (generator) acc))))))
  44. ;; Need to consider difference between append and all that
  45. ;; Also might be interested in building a large list first...
  46. (define-public (make-prime-generator)
  47. (define prime-cache '())
  48. (lambda ()
  49. (cond
  50. [(null? prime-cache) (set! prime-cache '(2)) 2]
  51. [(= 1 (length prime-cache)) (set! prime-cache '(2 3)) 3]
  52. [else
  53. (let lp ([i (+ 2 (last prime-cache))])
  54. (if (fold-and (lambda (prime)
  55. (not (= 0 (modulo i prime))))
  56. prime-cache)
  57. (begin (set! prime-cache (append prime-cache (list i)))
  58. i)
  59. (lp (+ 2 i))))])))
  60. (define prime-cache #f)
  61. ;; Evenutally make prime input optional
  62. (define-public (prime-factors n primes)
  63. (let loop ((curr n) (primes primes) (prime-factors '()))
  64. (if (= 1 curr) (reverse prime-factors)
  65. (if (= 0 (modulo curr (car primes)))
  66. (loop (/ curr (car primes))
  67. primes
  68. (cons (car primes) prime-factors))
  69. (loop curr (cdr primes) prime-factors)))))
  70. (define (rad n primes)
  71. (let loop ((curr n) (primes primes) (prime-factors '()))
  72. (if (= 1 curr)
  73. (reduce * 1 (delete-duplicates prime-factors))
  74. (if (= 0 (modulo curr (car primes)))
  75. (loop (/ curr (car primes))
  76. primes
  77. (cons (car primes) prime-factors))
  78. (loop curr (cdr primes) prime-factors)))))
  79. (define-public (ordered-radicals limit)
  80. (let* ((primes (primes-in-range limit))
  81. (rad-pairs (zip (iota limit 1)
  82. (map (lambda (n)
  83. (rad n primes))
  84. (iota limit 1)))))
  85. (list-sort (lambda (p1 p2)
  86. (if (= (cadr p1) (cadr p2))
  87. (< (car p1) (car p2))
  88. (< (cadr p1) (cadr p2))))
  89. rad-pairs)))
  90. ;; Gary-Miller primality test
  91. (define (expm b e m) ; modular exponentiation
  92. (let loop ((b b) (e e) (x 1))
  93. (if (zero? e) x
  94. (loop (modulo (* b b) m) (quotient e 2)
  95. (if (odd? e) (modulo (* b x) m) x)))))
  96. (define (strong-pseudoprime? n a) ; strong pseudoprime base a
  97. (let loop ((r 0) (s (- n 1)))
  98. (if (even? s) (loop (+ r 1) (/ s 2))
  99. (if (= (expm a s n) 1) #t
  100. (let loop ((r r) (s s))
  101. (cond ((zero? r) #f)
  102. ((= (expm a s n) (- n 1)) #t)
  103. (else (loop (- r 1) (* s 2)))))))))
  104. ;; as set for very high valued primes
  105. (define-public (prime? n)
  106. (if (<= n 1) #f
  107. (let lp ([as '(2 3 5 7 11)])
  108. (cond
  109. [(null? as) #t]
  110. [(= n (car as)) #t]
  111. [(not (strong-pseudoprime? n (car as))) #f]
  112. [else (lp (cdr as))]))))
  113. (define (primek? n k)
  114. (let loop ((k k))
  115. (cond ((zero? k) #t)
  116. ((not (strong-pseudoprime? n (random (+ 2 (- n 3))))) #f)
  117. (else (loop (- k 1))))))
  118. (define (primality-test limit)
  119. (define primes (erato limit))
  120. (let lp ([primes primes] [t 0] [f 0])
  121. (cond
  122. [(null? primes) (values t f)]
  123. [(prime? (car primes)) (lp (cdr primes) (1+ t) f)]
  124. [else (display (car primes)) (newline)
  125. (lp (cdr primes) t (1+ f))])))