prime-sum.scm 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. ;;; prime-sum --- Sieve of Eratosthenes in Pre-Scheme
  2. (define string->integer
  3. (external "atol" (=> ((^ char)) integer)))
  4. (define (make-sieve limit)
  5. (let ((sieve (make-vector (+ limit 1) #t)))
  6. (vector-fill! sieve #t 0 (+ limit 1))
  7. (vector-set! sieve 0 #f)
  8. (vector-set! sieve 1 #f)
  9. (letrec ((update-squares!
  10. (lambda (i)
  11. (let ((j (* i i)))
  12. (unless (> j limit)
  13. (when (vector-ref sieve i)
  14. (update-multiples! i j))
  15. (update-squares! (+ i 1))))))
  16. (update-multiples!
  17. (lambda (i j)
  18. (unless (> j limit)
  19. (vector-set! sieve j #f)
  20. (update-multiples! i (+ j i))))))
  21. (update-squares! 2))
  22. sieve))
  23. (define (sum-sieve sieve limit)
  24. (vector-fold (lambda (x result prime?)
  25. (if prime?
  26. (+ result x)
  27. result))
  28. 0 sieve (+ limit 1)))
  29. (define (sum-of-primes limit)
  30. (if (< limit 2)
  31. 0
  32. (let* ((sieve (make-sieve limit))
  33. (result (sum-sieve sieve limit)))
  34. (deallocate sieve)
  35. result)))
  36. (define (main argc argv)
  37. (define out (current-output-port))
  38. (define err (current-error-port))
  39. (cond ((not (= argc 2))
  40. (write-string "usage: " err)
  41. (write-string (vector-ref argv 0) err)
  42. (write-string " <limit>" err)
  43. (newline err)
  44. 1)
  45. (else
  46. (let ((limit (string->integer (vector-ref argv 1))))
  47. (cond ((< limit 0)
  48. (write-string "Limit must be non-negative" err)
  49. (newline err)
  50. 1)
  51. (else
  52. (let ((result (sum-of-primes limit)))
  53. (write-string "Sum of primes up to " out)
  54. (write-integer limit out)
  55. (write-string " is " out)
  56. (write-integer result out)
  57. (newline out)
  58. 0)))))))