class PRIME_NUMBER_SIEVE_4
Implementation using bits compacted into an array of type SPECIAL [NATURAL_32]
note
description: "Implementation using bits compacted into an array of type ${SPECIAL [NATURAL_32]}"
author: "Alexander Kogtenkov"
copyright: "Copyright (c) 2001-2021 Alexander Kogtenkov"
contact: "kwaxer at eiffel dot com"
license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
date: "2024-01-20 19:18:27 GMT (Saturday 20th January 2024)"
revision: "6"
class
PRIME_NUMBER_SIEVE_4
inherit
PRIME_NUMBER_COMMAND
SINGLE_MATH
export
{NONE} all
end
create
make
feature {NONE} -- Initialization
make (n: INTEGER)
local
i: INTEGER
count: INTEGER
do
sieve_size := n
-- Compute the number of elements.
count := n |>> index_shift + (n & index_mask > 0).to_integer
-- Exclude even items right from the beginning.
create area.make_filled (0xAAAAAAAA, count)
-- Clear bit 1.
clear (area, 1)
-- Clear bits outside the sieve.
from
count := count * element_size - 1
i := n + 1
until
i >= count
loop
clear (area, i)
i := i + 1
end
ensure
sieve_size = n
end
feature -- Measurement
sieve_size: INTEGER
-- The number of potential items.
feature -- Access
prime_count: INTEGER
local
i, size: INTEGER
a: like area
v: NATURAL_32
do
from
Result := 1
a := area
size := a.count
until
i >= size
loop
v := a [i]
v := v - ((v |>> 1) & 0x55555555)
v := (v & 0x33333333) + ((v |>> 2) & 0x33333333)
Result := Result + ((((v + (v |>> 4)) & 0x0F0F0F0F) * 0x01010101) |>> 24).as_integer_32
i := i + 1
end
end
feature -- Basic operations
execute
local
factor, q, i, size: INTEGER
f: INTEGER
a: like area
do
size := sieve_size
q := sqrt (size.to_real).rounded
a := area
from factor := 3 until factor > q loop
from
i := factor
until
i >= size or item (a, i)
loop
i := i + 2
end
if i < size then
factor := i
end
f := factor * 2
from
i := factor * factor
until
i >= size
loop
clear (a, i)
i := i + f
end
factor := factor + 2
end
end
feature -- Access
item (a: like area; i: INTEGER): BOOLEAN
-- Value of `i`-th bit of `a`.
do
Result := a.item (i |>> index_shift).bit_test (i & index_mask)
end
feature -- Modification
clear (a: like area; i: INTEGER)
-- Put `False` at `i`-th bit of `a`.
require
valid_bit_index: 0 <= i and i < sieve_size
local
index: INTEGER
v: like area.item
do
index := i |>> index_shift
v := a [index] & (one |<< (i & index_mask)).bit_not
a [index] := v
ensure
cleared: not item (a, i)
end
feature {NONE} -- Internal attributes
one: NATURAL_32 = 1
-- An element with a single lower bit.
area: SPECIAL [like one]
-- Storage for booleans.
element_size: INTEGER = 32
-- Size of one element in bits.
index_mask: INTEGER = 31
-- A mask of an index to access a bit in the selected element.
index_shift: INTEGER = 5
-- A number of bits the index should be shifted to obtain the element position.
-- `Double` and `Prime_count_table` are as in your code.
feature {NONE} -- Constants
Name: STRING = "Bit shifting SPECIAL [NATURAL_32]"
end