primes-utils 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +19 -12
- data/lib/primes/utils.rb +68 -75
- data/lib/primes/utils/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af94be1cfe58cb1704376223da97cdb48d6cc8a0
|
|
4
|
+
data.tar.gz: 924587a02967cd156d2115d5d1ac22d547ca9089
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b30b2ac81ef9e21321a667d3e5f009218300048367a6be81c083f3293c32b131bd1461020ec349674d7449f0bef453431aaa96b334a526c0cb065dc9c2c5ba0
|
|
7
|
+
data.tar.gz: 78bdfd7fcc6d0b9904a42b13b4cf5be82c45da2a21317e47c05efefc44928b411a6612a6b044b4ff9536a29500d49a099714c4155f1e8a4c98ab01c17c2b341e
|
data/README.md
CHANGED
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
`primes-utils` is a Rubygem which provides a suite of extremely fast
|
|
5
|
+
`primes-utils` is a Rubygem which provides a suite of extremely fast utility methods for testing and generating primes.
|
|
6
6
|
|
|
7
|
-
For details on
|
|
7
|
+
For details on the Math and Code used to implement them see:
|
|
8
8
|
|
|
9
9
|
`PRIMES-UTILS HANDBOOK`
|
|
10
10
|
|
|
11
|
+
Now available and `FREE` to view and download at:
|
|
12
|
+
|
|
11
13
|
https://www.scribd.com/doc/266461408/Primes-Utils-Handbook
|
|
12
14
|
|
|
13
|
-
Periodically check for updates.
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
17
18
|
Add this line to your application's Gemfile:
|
|
18
19
|
|
|
19
|
-
```
|
|
20
|
+
```
|
|
20
21
|
gem 'primes-utils'
|
|
21
22
|
```
|
|
22
23
|
|
|
@@ -59,8 +60,9 @@ The reliability can be increased by increasing the default input parameter of k=
|
|
|
59
60
|
1111111111111111111.primemr?(50) => true
|
|
60
61
|
11111111111111111111.primemr? => false
|
|
61
62
|
-3333333333333333333.primemr? => false
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
n=10**1700; (n+469).primemr? => true
|
|
64
|
+
0.primemr? => false
|
|
65
|
+
1.primemr? => false
|
|
64
66
|
```
|
|
65
67
|
|
|
66
68
|
**factors(p=13) or prime_division(p=13)**
|
|
@@ -86,7 +88,7 @@ Can change SP PG used on input. Acceptable primes range: [3 - 19].
|
|
|
86
88
|
|
|
87
89
|
Return an array of primes within the absolute value range `(|start| - |end|)`.
|
|
88
90
|
The order of the range doesn't matter if both given: `start.primes end <=> end.prime start`.
|
|
89
|
-
If only one parameter used, then all the primes
|
|
91
|
+
If only one parameter used, then all the primes up to that number will be returned.
|
|
90
92
|
See `PRIMES-UTILS HANDBOOK` for details on best use practices.
|
|
91
93
|
Also see `Error Handling`.
|
|
92
94
|
|
|
@@ -112,7 +114,7 @@ n=10**8; (25*n).primes -> ERROR3: not enough memory to store all primes in outp
|
|
|
112
114
|
|
|
113
115
|
Provide count of primes within the absolute value range `(|start| - |end|)`.
|
|
114
116
|
The order of the range doesn't matter if both given: `start.primes end <=> end.prime start`.
|
|
115
|
-
If only one parameter used, the count of all the primes
|
|
117
|
+
If only one parameter used, the count of all the primes up to that number will be returned.
|
|
116
118
|
See `PRIMES-UTILS HANDBOOK` for details on best use practices.
|
|
117
119
|
Also see `Error Handling`.
|
|
118
120
|
|
|
@@ -152,7 +154,7 @@ n = 10**11; n.primenth -> ERROR1: range size too big for available memory. => ni
|
|
|
152
154
|
**primes_utils**
|
|
153
155
|
|
|
154
156
|
Displays a list of all the `primes-utils` methods available for your system.
|
|
155
|
-
Use as `
|
|
157
|
+
Use as `n.primes_utils` where n is any `class Integer` value.
|
|
156
158
|
|
|
157
159
|
```
|
|
158
160
|
0.primes_utils => "prime? primemr? primes primesf primesmr primescnt primescntf primescntmr primenth|nthprime factors|prime_division"
|
|
@@ -162,9 +164,9 @@ Use as `x.primes_utils` where x is any `class Integer` value.
|
|
|
162
164
|
Starting with 2.2.0, error handling has been implemented to gracefully fail when array creation requires more memory than available.
|
|
163
165
|
This occurs when the range size, or end_num, need arrays greater than the amount of avalable memory. The first case shows the message
|
|
164
166
|
`ERROR1: range size too big for available memory.` and the second case `ERROR2: end_num too big for available memory.`
|
|
165
|
-
The affected methods are `primes`,
|
|
167
|
+
The affected methods are `primes`, `primescnt`, and `nthprime|primenth`.
|
|
166
168
|
`nthprime|primenth` also displays the error message `<pcnt> not enough primes, approx nth too small.`
|
|
167
|
-
(`<pcnt>` is computed count of primes) when the computed approx_nth value < nth value (though this should never happen by design).
|
|
169
|
+
(`<pcnt>` is computed count of primes) when the computed approx_nth value is < nth value (though this should never happen by design).
|
|
168
170
|
With 2.4.0 error handling was added to `primes` that catches the error and displays message `ERROR3: not enough memory to store all primes in output array.`.
|
|
169
171
|
For all errors, the return value for each method is `nil`.
|
|
170
172
|
|
|
@@ -191,12 +193,17 @@ All the `primes-utils` methods are `instance_methods` for `class Integer`.
|
|
|
191
193
|
|
|
192
194
|
## History
|
|
193
195
|
```
|
|
196
|
+
2.5.0 – 9 more index primes under the 110-millionth in nths; fixed Ruby 1.8 incompatibility in primes;
|
|
197
|
+
better|simpler technique for select_pg, significant speed increases for large ranges; used now
|
|
198
|
+
in all sozcore2 client methods primes, primescnt and primenth|nthprime; more code cleanups
|
|
194
199
|
2.4.0 – fixed error in algorithm when ks resgroup ≤ sqrt(end_num) resgroup; algorithm now split
|
|
195
200
|
arrays when start_num > sqrt(end_num) in sozcore2, whose code also signficantly optimized,
|
|
196
201
|
with API change adding pcs2start value to output parameters to use in primenth, which changed
|
|
197
202
|
to use it; ruby idiom code opt for set_start_value; consolidated pcs_to_num | pcs_to_start_num
|
|
198
203
|
functions into one new pcs_to_num, with associated changes in sozcore1|2; primes|cnt also
|
|
199
|
-
significantly faster resulting from sozcore2 changes; massive code cleanups all-arround
|
|
204
|
+
significantly faster resulting from sozcore2 changes; massive code cleanups all-arround; added
|
|
205
|
+
private methods select_pg (to adaptively select the pg used in primes), and array_check (used in
|
|
206
|
+
sozcore2 to catch array creation out-of-memory errors)
|
|
200
207
|
2.3.0 – primescnt now finds primes upto some integer much faster, and for much larger integers
|
|
201
208
|
increased index nth primes to over 2 billionth; used in nthprime|primenth and primescnt
|
|
202
209
|
2.2.0 – for sozcore2: refactored to include more common code; changed output api; added memory
|
data/lib/primes/utils.rb
CHANGED
|
@@ -7,39 +7,34 @@ module Primes
|
|
|
7
7
|
module Utils
|
|
8
8
|
# Upon loading, determine if platform has cli command 'factor'
|
|
9
9
|
private
|
|
10
|
-
os_has_factor = false
|
|
10
|
+
@@os_has_factor = false
|
|
11
11
|
begin
|
|
12
12
|
if `factor 10`.split(' ') == ["10:", "2", "5"]
|
|
13
|
-
os_has_factor = true
|
|
13
|
+
@@os_has_factor = true
|
|
14
14
|
end
|
|
15
15
|
rescue
|
|
16
|
-
os_has_factor = false
|
|
16
|
+
@@os_has_factor = false
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# Methods primes* and primescnt* use a number range: end_num - start_num
|
|
20
|
-
# Use as: end_num.primes*(start_num) (or vice versa) or end_num.primes
|
|
21
|
-
# If start_num omitted, the method will find all primes <= end_num
|
|
22
|
-
# If start_num > self, values are switched to make end_num > start_num
|
|
23
|
-
|
|
24
19
|
public
|
|
25
|
-
if os_has_factor # for platforms with cli 'factor' command
|
|
20
|
+
if @@os_has_factor # for platforms with cli 'factor' command
|
|
26
21
|
|
|
27
22
|
def prime?
|
|
28
23
|
`factor #{self.abs}`.split(' ').size == 2
|
|
29
24
|
end
|
|
30
25
|
|
|
31
|
-
def factors(p=0)
|
|
26
|
+
def factors(p=0) # p is unused dummy variable for method consistency
|
|
32
27
|
factors = `factor #{self.abs}`.split(' ')[1..-1].map(&:to_i)
|
|
33
28
|
h = Hash.new(0); factors.each {|f| h[f] +=1}; h.to_a.sort
|
|
34
29
|
end
|
|
35
30
|
|
|
36
31
|
def primesf(start_num=0)
|
|
37
|
-
#
|
|
32
|
+
# List primes within a number range: end_num - start_num
|
|
38
33
|
# Uses 'prime?' to check primality of prime candidates in range
|
|
39
|
-
sozdata = sozcore1(self, start_num, true)
|
|
34
|
+
sozdata = sozcore1(self, start_num, true) # true for primes list
|
|
40
35
|
pcs_in_range, r, mod, modk, rescnt, residues, primes = sozdata
|
|
41
36
|
|
|
42
|
-
pcs_in_range.times do #
|
|
37
|
+
pcs_in_range.times do # list primes from this num pcs in range
|
|
43
38
|
prime = modk + residues[r]
|
|
44
39
|
primes << prime if prime.prime?
|
|
45
40
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
|
@@ -50,7 +45,7 @@ module Primes
|
|
|
50
45
|
def primescntf(start_num=0)
|
|
51
46
|
# Count primes within a number range: end_num - start_num
|
|
52
47
|
# Uses 'prime?' to check primality of prime candidates in range
|
|
53
|
-
sozdata = sozcore1(self, start_num, false) # false for
|
|
48
|
+
sozdata = sozcore1(self, start_num, false) # false for primes count
|
|
54
49
|
pcs_in_range, r, mod, modk, rescnt, residues, primescnt = sozdata
|
|
55
50
|
|
|
56
51
|
pcs_in_range.times do # count primes from this num pcs in range
|
|
@@ -71,11 +66,9 @@ module Primes
|
|
|
71
66
|
mod=210; # rescnt=48
|
|
72
67
|
|
|
73
68
|
n = self.abs
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
167, 173, 179, 181, 191, 193, 197, 199, 211].include? n
|
|
78
|
-
return false unless residues.include?(n%mod) and n > 1
|
|
69
|
+
is_a_pc = residues.include?(n%mod) # true if n is a prime candidate
|
|
70
|
+
return false unless (n > 1 and is_a_pc) or [2,3,5,7].include? n
|
|
71
|
+
return true if n <= 211 and not [121,143,169,187,209].include? n
|
|
79
72
|
|
|
80
73
|
sqrtN = Math.sqrt(n).to_i
|
|
81
74
|
p=11 # first test prime pj
|
|
@@ -95,7 +88,7 @@ module Primes
|
|
|
95
88
|
n%(p+186)== 0 or n%(p+188)==0 or n%(p+198)== 0 or n%(p+200)==0
|
|
96
89
|
p += mod # first prime candidate for next kth residues group
|
|
97
90
|
end
|
|
98
|
-
true
|
|
91
|
+
true # n is prime (100%|deterministically)
|
|
99
92
|
end
|
|
100
93
|
|
|
101
94
|
def factors(p=13)
|
|
@@ -116,13 +109,12 @@ module Primes
|
|
|
116
109
|
primes.each {|p| while n%p == 0; factors << p; n /= p end }
|
|
117
110
|
|
|
118
111
|
sqrtN = Math.sqrt(n).to_i
|
|
119
|
-
modk,r=0,1
|
|
120
|
-
while p <= sqrtN
|
|
112
|
+
modk,r=0,1
|
|
113
|
+
while (p = modk+residues[r]) <= sqrtN
|
|
121
114
|
if n%p == 0
|
|
122
115
|
factors << p; r -=1; n /= p; sqrtN = Math.sqrt(n).to_i
|
|
123
116
|
end
|
|
124
117
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
|
125
|
-
p = modk+residues[r] # next (or current) prime candidate
|
|
126
118
|
end
|
|
127
119
|
factors << n if n > 1
|
|
128
120
|
h=Hash.new(0); factors.each {|f| h[f] +=1}; h.to_a.sort
|
|
@@ -130,26 +122,26 @@ module Primes
|
|
|
130
122
|
|
|
131
123
|
puts "Using pure ruby versions for all methods"
|
|
132
124
|
end
|
|
133
|
-
|
|
125
|
+
|
|
134
126
|
# Replace slow ruby library method prime_division with faster version
|
|
135
127
|
alias prime_division factors
|
|
136
128
|
|
|
137
|
-
def primenth(p=
|
|
138
|
-
# Return value of nth prime
|
|
129
|
+
def primenth(p=0)
|
|
130
|
+
# Return value of nth prime
|
|
131
|
+
# Adaptively selects best SP PG, unless valid input PG given at runtime
|
|
139
132
|
seeds = [2, 3, 5, 7, 11, 13]
|
|
140
|
-
p =
|
|
133
|
+
(primes=seeds[0..seeds.index(p)]; mod=primes.reduce(:*)) if seeds.include? p
|
|
141
134
|
|
|
142
135
|
n = self.abs # the desired nth prime
|
|
143
|
-
return n
|
|
136
|
+
return n > 0 ? seeds[n-1] : 0 if n <= seeds.size
|
|
144
137
|
|
|
145
138
|
start_num, nth, nthflag = set_start_value(n,true)
|
|
146
|
-
return start_num if nthflag # output nthprime if
|
|
139
|
+
return start_num if nthflag # output nthprime value if n a ref prime key
|
|
147
140
|
|
|
148
141
|
num = approximate_nth(n) # close approx to nth >= real nth
|
|
149
|
-
primes =
|
|
150
|
-
mod = primes.reduce(:*) # create modulus of SP PG
|
|
142
|
+
primes, mod = select_pg(num, start_num) unless primes
|
|
151
143
|
prms, m, modk, residues, rescnt, pcs2start, * = sozcore2(num, start_num, mod)
|
|
152
|
-
return
|
|
144
|
+
return unless prms # exit gracefully if sozcore2 mem error
|
|
153
145
|
|
|
154
146
|
# starting at start_num's location, find nth prime within given range
|
|
155
147
|
prmcnt = n > nth ? nth-1 : primes.size
|
|
@@ -163,23 +155,22 @@ module Primes
|
|
|
163
155
|
alias nthprime primenth # to make life easier
|
|
164
156
|
|
|
165
157
|
def primes(start_num=0)
|
|
166
|
-
#
|
|
158
|
+
# List primes between a number range: end_num - start_num
|
|
167
159
|
# Adaptively selects Strictly Prime (SP) Prime Generator
|
|
168
160
|
num = self.abs; start_num = start_num.abs
|
|
169
161
|
num, start_num = start_num, num if start_num > num
|
|
170
162
|
|
|
171
163
|
primes, mod = select_pg(num, start_num) # adaptively select PG
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return if prms == nil # exit gracefully if sozcore2 mem error
|
|
164
|
+
prms, m, modk, residues, rescnt, x, maxprms, r = sozcore2(num, start_num, mod)
|
|
165
|
+
return unless prms # exit gracefully if sozcore2 mem error
|
|
175
166
|
|
|
176
167
|
# init 'primes' w/any excluded primes in range then extract primes from prms
|
|
177
|
-
primes
|
|
178
|
-
while m < maxprms #
|
|
168
|
+
primes.select! {|p| p >= start_num && p <= num}
|
|
169
|
+
while m < maxprms # list primes from sieved pcs in prms for range
|
|
179
170
|
begin
|
|
180
171
|
primes << modk + residues[r] if prms[m] == 1
|
|
181
|
-
|
|
182
|
-
|
|
172
|
+
rescue Exception
|
|
173
|
+
return puts "ERROR3: not enough memory to store all primes in output array."
|
|
183
174
|
end
|
|
184
175
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
|
185
176
|
m +=1
|
|
@@ -189,23 +180,22 @@ module Primes
|
|
|
189
180
|
|
|
190
181
|
def primescnt(start_num=0)
|
|
191
182
|
# Count primes between a number range: end_num - start_num
|
|
192
|
-
#
|
|
183
|
+
# Adaptively selects Strictly Prime (SP) Prime Generator
|
|
193
184
|
num = self.abs; start_num = start_num.abs
|
|
194
185
|
num, start_num = start_num, num if start_num > num
|
|
195
186
|
|
|
196
187
|
if start_num < 3 # for all primes upto num
|
|
197
188
|
start_num, nth, nthflag = set_start_value(num,false)
|
|
198
|
-
return nth unless nthflag # output
|
|
189
|
+
return nth unless nthflag # output num's key|count if a ref nth value
|
|
199
190
|
end
|
|
200
191
|
|
|
201
|
-
primes =
|
|
202
|
-
mod = primes.reduce(:*)
|
|
192
|
+
primes,mod = select_pg(num, start_num) # adaptively select PG
|
|
203
193
|
prms, m, * = sozcore2(num, start_num, mod)
|
|
204
|
-
return
|
|
194
|
+
return unless prms # exit gracefully if sozcore2 mem error
|
|
205
195
|
|
|
206
196
|
# init prmcnt for any excluded primes in range then count primes in prms
|
|
207
|
-
prmcnt = primes.
|
|
208
|
-
prmcnt = nth-1 if nthflag && nth > 0 #
|
|
197
|
+
prmcnt = primes.count {|p| p >= start_num && p <= num}
|
|
198
|
+
prmcnt = nth-1 if nthflag && nth > 0 # start count for small range
|
|
209
199
|
prmcnt + prms[m..-1].count(1)
|
|
210
200
|
end
|
|
211
201
|
|
|
@@ -234,16 +224,16 @@ module Primes
|
|
|
234
224
|
end
|
|
235
225
|
return false if x != n-1
|
|
236
226
|
end
|
|
237
|
-
true # with high probability
|
|
227
|
+
true # n is prime (with high probability)
|
|
238
228
|
end
|
|
239
229
|
|
|
240
230
|
def primesmr(start_num=0)
|
|
241
|
-
#
|
|
231
|
+
# List primes within a number range: end_num - start_num
|
|
242
232
|
# Uses 'primemr' to check primality of prime candidates in range
|
|
243
233
|
sozdata = sozcore1(self, start_num, true) # true for primes
|
|
244
234
|
pcs_in_range, r, mod, modk, rescnt, residues, primes = sozdata
|
|
245
235
|
|
|
246
|
-
pcs_in_range.times do #
|
|
236
|
+
pcs_in_range.times do # list primes from this num pcs in range
|
|
247
237
|
prime = modk + residues[r]
|
|
248
238
|
primes << prime if prime.primemr?
|
|
249
239
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
|
@@ -264,14 +254,10 @@ module Primes
|
|
|
264
254
|
primescnt
|
|
265
255
|
end
|
|
266
256
|
|
|
267
|
-
def primes_utils
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if os_has_factor
|
|
272
|
-
def primes_utils
|
|
273
|
-
"prime? primemr? primes primesf primesmr primescnt primescntf primescntmr primenth|nthprime factors|prime_division"
|
|
274
|
-
end
|
|
257
|
+
def primes_utils # display list of available methods
|
|
258
|
+
methods = %w/prime? primemr? primes primesf primesmr primescnt
|
|
259
|
+
primescntf primescntmr primenth|nthprime factors|prime_division/
|
|
260
|
+
(methods - (@@os_has_factor ? [] : %w/primesf primescntf/)).join(" ")
|
|
275
261
|
end
|
|
276
262
|
|
|
277
263
|
private
|
|
@@ -281,7 +267,7 @@ module Primes
|
|
|
281
267
|
[residues, residues.size-1] # return residues array and rescnt
|
|
282
268
|
end
|
|
283
269
|
|
|
284
|
-
# lte= true: first output element is number pcs <= num
|
|
270
|
+
# lte= true: first output element is number of pcs <= num
|
|
285
271
|
# lte=false: num pcs <, residue index, and resgroup value, for (start_)num pc
|
|
286
272
|
def pcs_to_num(num,mod,rescnt,residues,lte)
|
|
287
273
|
num -=1; lte ? (num |=1; k=num.abs/mod) : k = (num-1).abs/mod
|
|
@@ -309,7 +295,7 @@ module Primes
|
|
|
309
295
|
maxpcs,* = pcs_to_num(num,mod,rescnt,residues,true) # num pcs <= end_num
|
|
310
296
|
|
|
311
297
|
# init 'primes' w/any excluded primes in the range, or [] if none
|
|
312
|
-
primes
|
|
298
|
+
primes.select! {|p| p >= start_num && p <= num}
|
|
313
299
|
|
|
314
300
|
# compute parameters for start_num pc, then create output parameters array
|
|
315
301
|
m, r, modk = pcs_to_num(start_num, mod, rescnt, residues, false)
|
|
@@ -330,17 +316,17 @@ module Primes
|
|
|
330
316
|
residues, rescnt = make_residues_rescnt(mod) # parameters for the PG
|
|
331
317
|
maxprms,* = pcs_to_num(num,mod,rescnt,residues,true) # num pcs <= end_num
|
|
332
318
|
|
|
333
|
-
# for start_num pc, find num pcs <, residue index, and resgroup mod value
|
|
334
|
-
pcs2start, rs, modks = pcs_to_num(start_num, mod, rescnt, residues, false)
|
|
335
|
-
|
|
319
|
+
# for start_num pc, find num pcs <, residue index, and resgroup mod value
|
|
320
|
+
pcs2start, rs, modks = pcs_to_num(start_num, mod, rescnt, residues, false)
|
|
321
|
+
|
|
336
322
|
sqrtN = Math.sqrt(num).to_i # sqrt of end_num (end of range)
|
|
337
323
|
pcs2sqrtN,* = pcs_to_num(sqrtN,mod,rescnt,residues,true) # num pcs <= sqrtN
|
|
338
324
|
|
|
339
325
|
split_arrays = start_num > sqrtN # flag, true if two arrays used for sieve
|
|
340
|
-
maxpcs = maxprms # init array size for all pcs to end_num
|
|
326
|
+
maxpcs = maxprms # init array size for all pcs to end_num
|
|
341
327
|
if split_arrays # if start_num > sqrtN create two arrays
|
|
342
328
|
maxpcs = pcs2sqrtN # number of pcs|array size, for pcs <= sqrtN
|
|
343
|
-
max_range = maxprms-pcs2start # number of pcs in range start_num to end_num
|
|
329
|
+
max_range = maxprms-pcs2start # number of pcs in range start_num to end_num
|
|
344
330
|
prms_range = array_check(max_range,1) # array to represent pcs in range
|
|
345
331
|
return puts "ERROR1: range size too big for available memory." unless prms_range
|
|
346
332
|
end
|
|
@@ -361,9 +347,9 @@ module Primes
|
|
|
361
347
|
kcon = k * prmstep # its inner loop constant computed
|
|
362
348
|
residues[1..-1].each do |ri|# now perform sieve with it
|
|
363
349
|
# convert (prime * (modk + ri)) pc value to its address in prms
|
|
364
|
-
|
|
350
|
+
# computed as nonprm = (k*(prime + ri) + kn)*rescnt + pos[rr]
|
|
365
351
|
kn,rr = (prm_r * ri).divmod mod # residues product res[group|track]
|
|
366
|
-
|
|
352
|
+
nonprm = kcon + (k*ri + kn)*rescnt + pos[rr]# 1st prime multiple address with ri
|
|
367
353
|
while nonprm < maxpcs; prms[nonprm]=0; nonprm +=prmstep end
|
|
368
354
|
if split_arrays # when start_num > sqrtN
|
|
369
355
|
nonprm = (pcs2start - nonprm)%prmstep # (start_num - last multiple) pcs
|
|
@@ -386,20 +372,23 @@ module Primes
|
|
|
386
372
|
def set_start_value(n, hshflag) # find largest index nthprime|val <= n
|
|
387
373
|
if hshflag
|
|
388
374
|
return [nths[n], 0, true] if nths.has_key? n # if n is key in nths table
|
|
389
|
-
|
|
375
|
+
nth = nths.keys.sort.reverse.detect {|k| k < n} # find largest indexed key < n
|
|
390
376
|
[nth ? nths[nth] : 0, nth ||= n+1, false] # [start_num, nth, false]
|
|
391
377
|
else
|
|
392
378
|
return [0,nths.key(n),false] if nths.has_value? n # if n is value in nths table
|
|
393
|
-
|
|
379
|
+
v=val= nths.values.sort.reverse.detect {|v| v < n} # find largest indexed val < n
|
|
394
380
|
[v ||= 0, val ? nths.key(val) : 0, true] # [start_num, nth, true]
|
|
395
381
|
end
|
|
396
382
|
end
|
|
397
383
|
|
|
398
384
|
def nths # hash table index of reference nth primes
|
|
399
385
|
nths={1000000 => 15485863, 5000000 => 86028121, 7500000 => 132276691,
|
|
400
|
-
10000000 => 179424673, 12500000 => 227254201,
|
|
401
|
-
|
|
402
|
-
|
|
386
|
+
10000000 => 179424673, 12500000 => 227254201, 15000000 => 275604541,
|
|
387
|
+
18500000 => 344032387, 25000000 => 472882027, 31000000 => 593441843,
|
|
388
|
+
37500000 => 725420401, 43500000 => 848321917, 50000000 => 982451653,
|
|
389
|
+
56000000 => 1107029837, 62500000 => 1242809749, 68500000 => 1368724829,
|
|
390
|
+
75000000 => 1505776939, 81500000 => 1643429659, 87500000 => 1770989609,
|
|
391
|
+
93500000 => 1898979367, 100000000 => 2038074743, 106500000 => 2177624377,
|
|
403
392
|
112500000 => 2306797469, 125000000 => 2576983867, 137500000 => 2848518523,
|
|
404
393
|
150000000 => 3121238909, 162500000 => 3395057291, 175000000 => 3669829403,
|
|
405
394
|
187500000 => 3945592087, 200000000 => 4222234741, 212500000 => 4499683009,
|
|
@@ -455,14 +444,18 @@ module Primes
|
|
|
455
444
|
end
|
|
456
445
|
|
|
457
446
|
def select_pg(num, start_num) # adaptively select PG
|
|
458
|
-
|
|
459
|
-
primes =
|
|
447
|
+
range_size = num - start_num
|
|
448
|
+
primes = [2, 3, 5] # use P5 for small ranges
|
|
449
|
+
primes << 7 if range_size > 35*10**5 # use P7 for midsize ranges
|
|
450
|
+
primes << 11 if range_size > 850*10**5 # use P11 for large ranges
|
|
451
|
+
primes << 13 if range_size > 550*10**7 # use P13 for larger ranges
|
|
460
452
|
[primes, primes.reduce(:*)] # [excluded primes, mod] for PG
|
|
461
453
|
end
|
|
462
454
|
|
|
463
455
|
def array_check(n,v) # catch out-of-memory errors on array creation
|
|
464
|
-
|
|
456
|
+
Array.new(n,v) rescue return # return an array or nil
|
|
465
457
|
end
|
|
458
|
+
|
|
466
459
|
end
|
|
467
460
|
end
|
|
468
461
|
|
data/lib/primes/utils/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: primes-utils
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jabari Zakiya
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-12-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|