diff --git a/lib/prime.rb b/lib/prime.rb index 4a20d93..e2f6ac5 100644 --- a/lib/prime.rb +++ b/lib/prime.rb @@ -316,6 +316,17 @@ class Prime 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 @@ -427,6 +438,11 @@ class Prime 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. @@ -437,6 +453,34 @@ class Prime @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 @@ -462,9 +506,9 @@ class Prime # 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 @@ -473,13 +517,16 @@ class Prime 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<