naive-prime-test.scm 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. (library (lib naive-prime-test)
  2. (export prime?)
  3. (import
  4. (except (rnrs base) let-values)
  5. (only (guile)
  6. lambda* λ
  7. remainder
  8. inexact->exact)
  9. (prefix (lib math) math:))
  10. ;; The biggest potential factor of a number is at maximum
  11. ;; its square root. Since we are looking for integer
  12. ;; factors, we also floor the square root. If it is even, we
  13. ;; substract 1, because even numbers cannot be prime
  14. ;; factors, except for 2.
  15. (define biggest-potential-factor
  16. (λ (num)
  17. (let ([near-sqrt (inexact->exact (floor (sqrt num)))])
  18. (cond
  19. [(= near-sqrt 2) near-sqrt]
  20. [(math:even? near-sqrt) (- near-sqrt 1)]
  21. [else near-sqrt]))))
  22. (define biggest-prime-factor
  23. (λ (num)
  24. (let iter ([fac (biggest-potential-factor num)])
  25. (cond
  26. ;; Stop looking for factors when reaching 1. This
  27. ;; prevents the search from going into negative
  28. ;; numbers towards negative infinity.
  29. [(= fac 1) 1]
  30. ;; If the number fac is really a factor of num and it
  31. ;; is prime, then that is the result.
  32. [(and (math:divides? fac num) (prime? fac)) fac]
  33. ;; 2 is the only even prime factor. If we reach 3, we
  34. ;; need to decrease by 1 only, so that we also test 2
  35. ;; as a prime factor.
  36. [(<= fac 3) (iter (- fac 1))]
  37. ;; Decrease by 2, to skip even numbers.
  38. [else (iter (- fac 2))]))))
  39. (define prime?
  40. (λ (num)
  41. (cond
  42. [(= num 0) #f]
  43. [(= num 1) #f]
  44. [(negative? num) #f]
  45. [else (= (biggest-prime-factor num) 1)]))))