Project

General

Profile

Feature #5378 ยป prime.patch

h.shirosaki (Hiroshi Shirosaki), 10/01/2011 03:26 PM

View differences:

lib/prime.rb
def rewind
initialize
end
def each(&block)
return self.dup unless block
if @ubound
EratosthenesSieve.instance.each(@ubound, &block)
else
loop do
block.call(succ)
end
end
end
alias next succ
end
......
ENTRIES_PER_TABLE = 8
NUMS_PER_TABLE = NUMS_PER_ENTRY * ENTRIES_PER_TABLE
FILLED_ENTRY = (1 << NUMS_PER_ENTRY) - 1
BITS_MASK = 0b00011111
BITS_SHIFT = 1
ENTRY_MASK = 0b11100000
ENTRY_SHIFT = 5
TABLE_SHIFT = 8
def initialize # :nodoc:
# bitmap for odd prime numbers less than 256.
......
@tables = [[0xcb6e, 0x64b4, 0x129a, 0x816d, 0x4c32, 0x864a, 0x820d, 0x2196].freeze]
end
def each(ubound, &block)
last_value = nil
last_value = block.call(2) if ubound > 1
ubound = (ubound-1).div(2)*2+1 # the biggist odd number less than or equal to ubound
to_table_index, to_integer_index, to_bit_index = indices(ubound)
extend_table until @tables.length > to_table_index
for i in 0..to_table_index
table_base = NUMS_PER_TABLE * i
tables_i = @tables[i]
end_integer_index = (i == to_table_index ? to_integer_index+1 : ENTRIES_PER_TABLE)
for j in 0...end_integer_index
tables_i_j = tables_i[j]
unless tables_i_j.zero?
integer_base = table_base + NUMS_PER_ENTRY * j
end_bit_index = (i == to_table_index && j == to_integer_index ?
to_bit_index+1 : BITS_PER_ENTRY)
for k in 0...end_bit_index
unless tables_i_j[k].zero?
last_value = block.call(integer_base + 2*k+1)
end
end
end
end
end
last_value
end
# returns the least odd prime number which is greater than +n+.
def next_to(n)
n = (n-1).div(2)*2+3 # the next odd number to given n
......
# indices: |-| k | j | i
# because of NUMS_PER_ENTRY, NUMS_PER_TABLE
k = (n & 0b00011111) >> 1
j = (n & 0b11100000) >> 5
i = n >> 8
k = (n & BITS_MASK) >> BITS_SHIFT
j = (n & ENTRY_MASK) >> ENTRY_SHIFT
i = n >> TABLE_SHIFT
return i, j, k
end
......
ubound = lbound + NUMS_PER_TABLE
new_table = [FILLED_ENTRY] * ENTRIES_PER_TABLE # which represents primarity in lbound...ubound
(3..Integer(Math.sqrt(ubound))).step(2) do |p|
i, j, k = indices(p)
k = (p & BITS_MASK) >> BITS_SHIFT
j = (p & ENTRY_MASK) >> ENTRY_SHIFT
i = p >> TABLE_SHIFT
next if @tables[i][j][k].zero?
start = (lbound.div(p)+1)*p # least multiple of p which is >= lbound
start += p if start.even?
(start...ubound).step(2*p) do |n|
_, j, k = indices(n)
k = (n & BITS_MASK) >> BITS_SHIFT
j = (n & ENTRY_MASK) >> ENTRY_SHIFT
new_table[j] &= FILLED_ENTRY^(1<<k)
end
end
test/test_prime.rb
assert_not_include Prime.each(7*37).to_a, 7*37, "[ruby-dev:39465]"
end
def test_each_with_ubound
primes = []
value = Prime.each(541) do |p|
primes << p
end
assert_equal PRIMES, primes
assert_equal PRIMES, value
end
def test_each_inject_with_ubound
assert_equal PRIMES, Prime.each(541).inject([]) {|a, p| a << p}
assert_equal PRIMES[0, PRIMES.size-1], Prime.each(540).inject([]) {|a, p| a << p}
assert_equal [], Prime.each(1).inject([]) {|a, p| a << p}
assert_equal [2], Prime.each(2).inject([]) {|a, p| a << p}
assert_equal [2, 3], Prime.each(3).inject([]) {|a, p| a << p}
end
end
    (1-1/1)