Advertisement
Guest User

sieve

a guest
Mar 22nd, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 3.67 KB | None | 0 0
  1. (defun sieve-odds (maximum)
  2.   "Prime numbers sieve for odd numbers.
  3.   Returns a list with all primes that are less or equal to maximum."
  4.   ;; maxi represents the number of odd numbers that are >= 3 and <= maximum
  5.   ;; it's equal to (floor (1- maximum) 2)
  6.   ;; because there are (/ EVENX 2)      odd numbers that are <= EVENX
  7.   ;;   so there are (floor (1- EVENX) 2) odd numbers that are >= 3 and <= EVENX
  8.   ;; also there are (floor (1+ ODDX) 2) odd numbers <= ODDX
  9.   ;;   so there are (floor ODDX 2)=(floor (1- ODDX) 2) odd numbers that are >= 3 and <= ODDX
  10.   ;; thus maxi is equal to (floor (1- maximum) 2) or equivalently (ash (1- maximum) -1)
  11.   ;; also, maxi*2+1 is the highest odd number smaller than or equal to maximum
  12.   ;; stop is the bitarray index upperbound for the floored square root of maximum
  13.   ;; i is the bitarray index of the
  14.   ;; (i+1)th odd natural number (let's call this number oddi).
  15.   ;; i=1 maps to oddi=3, i=2 maps to 5,...
  16.   (loop :with maxi = (ash (1- maximum) -1)
  17.         :with stop = (ash (isqrt maximum) -1)
  18.         :with sieve = (make-array (1+ maxi) :element-type 'bit :initial-element 0)
  19.         :for i :from 1 :to maxi
  20.         :for odd-number = (1+ (ash i 1))
  21.         :when (zerop (sbit sieve i))
  22.           ;; the first bit (sbit sieve 0) is initialized to 0 so 3 will always be collected
  23.           :collect odd-number :into values
  24.         :when (<= i stop)
  25.           ;; next we're gonna sift out the multiples of oddi that are <= stop
  26.           :do (loop :for j :from (* i (1+ i) 2) :to maxi :by odd-number
  27.                     ;; j is the bitarray index of the (j-1)th odd number
  28.                     ;; (let's call this number oddj)
  29.                     ;; on every step j grows by oddj
  30.                     ;; so that it can reach through all the bitarray indexes of oddi's multiples
  31.                     ;; j starts from (* 2 (* i (1+ i))), which is (expt oddi 2)'s index
  32.                     ;; because (expt oddi 2) is the smallest multiple of oddi which hasn't been
  33.                     ;; yet sifted out: all multiples in the form oddi*oddk where k<i were
  34.                     ;; sifted in a previous iteration(when i was equal to k).
  35.                     ;; So because (expt oddi 2) is the smallest multiple to be sifted out
  36.                     ;; the outer loop must end when i > stop (=the index of (isqrt maximum)).
  37.                     #|
  38.                     Here's how to figure out the bitarray index of (expt oddi 2)
  39.                     array index                i:  1 2 3 4  5  6  7  8  9 10 11 12
  40.                     the corresponding value oddi:  3 5 7 9 11 13 15 17 19 21 23 25
  41.                     An index of 2 corresponds to the value 1+2*2=5
  42.                     An index of 3 corresponds to the value 1+3*2=7
  43.                     So to get from    index 2 (number 5) to index 12 (5^2)
  44.                     means to get from     1+2*2=5        to     1+12*2=25=(1+2*2)^2
  45.          
  46.                     Thus the index of the square of oddi is the x in this equation:
  47.                     (1+i*2)^2=1+x*2
  48.                     1+4i+4i^2=1+2x
  49.                     x=(1+4i+4i^2-1)/2
  50.                     x=4(i+i^2)/2
  51.                     x=2(i+i^2)
  52.                     x=2(i(1+i))
  53.                     |#
  54.                     ;; Therefore j starts from this 2(i(1+i)), goes up through all the multiples
  55.                     ;; and sifts them out.
  56.                     ;; The loop stops when it reaches the highest multiple
  57.                     ;; of oddi with the index smaller or equal to maxi
  58.                     ;; (that's the highest multiple indexed by our bitarray)
  59.                     :do (setf (sbit sieve j) 1))
  60.         :finally (return (cons 2 values))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement