primes-utils 2.2.0 → 2.3.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 +27 -3
- data/lib/primes/utils.rb +61 -42
- data/lib/primes/utils/version.rb +1 -1
- data/primes-utils.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff3c9d871e492288cbbfac6beb023fd765f9bf8e
|
4
|
+
data.tar.gz: 976926b10063c0fc58ea29b33765b800c937727f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e1b3235a3252ce746a1ba5210060fc9b73998a4b4b789ce37a1bf85a8591ac4bc7f70d76250ac34a71538705c8e2d06f906b15db440ae27e6b555c33fea491b
|
7
|
+
data.tar.gz: cd933f765848c9d5777aa34f677a85c01b3f591205eceb545cd523cd159db5c42381ca27d8044d1ef1f38ce8bd9a472fa93036a37f225cfcd8581fd469e2b28a
|
data/README.md
CHANGED
@@ -114,7 +114,9 @@ See `PRIMES-UTILS HANDBOOK` for details on best use practices.
|
|
114
114
|
Also see `Error Handling`.
|
115
115
|
|
116
116
|
```
|
117
|
-
|
117
|
+
100001.primescnt => 9592
|
118
|
+
100002.primescnt => 9592
|
119
|
+
100003.primescnt => 9593
|
118
120
|
100000.primescntf 100500 => 40
|
119
121
|
n=10**400; (n-500).primescntmr(n+500) => 1
|
120
122
|
-10.primescnt -50 => 11
|
@@ -151,7 +153,7 @@ Use as `x.primes_utils` where x is any `class Integer` value.
|
|
151
153
|
|
152
154
|
## Error Handling
|
153
155
|
Starting with 2.2.0, error handling has been implemented to gracefully handle when array creation requires more memory than available.
|
154
|
-
This occurs
|
156
|
+
This occurs when the range size, or end_num, need arrays greater than the amount of avalable memory. The first case shows the message
|
155
157
|
`ERROR1: range size too big for available memory.` and the second case `ERROR2: end_num too big for available memory.`
|
156
158
|
The affected methods are `nthprime|primenth`, `primes`, and `primescnt`.
|
157
159
|
`nthprime|primenth` also displays the error message `<yyyy> not enough primes, approx nth too small.`
|
@@ -160,7 +162,6 @@ For all errors, the return value for each method is `nil`.
|
|
160
162
|
|
161
163
|
This behavior is referenced to MRI Ruby.
|
162
164
|
|
163
|
-
|
164
165
|
## Coding Implementations
|
165
166
|
The methods `primemr?`, `nthprime|primenth`, `primes`, `primescnt`, `primesmr`, and `primescnt` are coded in pure ruby.
|
166
167
|
The methods `prime?` and `prime_division|factors` have two implementations.
|
@@ -175,6 +176,29 @@ New in 2.2.0, upon loading with Ruby 1.8 `require 'rubygems'` is invoked to enab
|
|
175
176
|
|
176
177
|
All the `primes-utils` methods are `instance_methods` for `class Integer`.
|
177
178
|
|
179
|
+
## History
|
180
|
+
```
|
181
|
+
2.3.0 – primescnt now finds primes upto some integer much faster, and for much larger integers
|
182
|
+
increased index nth primes to over 2 billionth; used in nthprime|primenth and primescnt
|
183
|
+
2.2.0 – for sozcore2: refactored to include more common code; changed output api; added memory
|
184
|
+
error messages when prms and prms_range arrays creation fails; for primenth: used new
|
185
|
+
function to compute parameter b and removed ceiling for it; increased number of index primes
|
186
|
+
in nths; primes, primescnt, and primenth|nthprime also refactored, will use all available mem
|
187
|
+
2.1.0 – changed default PG in primes and primescnt from P13 to P5, significantly faster
|
188
|
+
2.0.0 – new methods primesf, primesmr, primescnt, primescntf, primescntmr, primes_utils
|
189
|
+
also improved mem efficiency/speed and extended range for primes and primenth
|
190
|
+
changed default PG in nthprime|primenth from P11 to P7, major refactoring of all methods
|
191
|
+
1.1.1 – more efficient/faster code to count up to nth prime in primenth
|
192
|
+
1.1.0 – new nth prime approximation method in primenth
|
193
|
+
1.0.6 – fixed n=1 check error for prime?
|
194
|
+
1.0.5 – minor bug fix
|
195
|
+
1.0.4 – fixed n=0 case for primenth; fixed subtle bug in primes, refactored to generalize code
|
196
|
+
1.0.3 – minor bug fix
|
197
|
+
1.0.2 – directly test for cli command factor on installed platform at start
|
198
|
+
1.0.1 – check if using Ruby 1.8 at start, if so, require 'rational' library for gcd method
|
199
|
+
1.0.0 – initial release April 1, 2015 with methods prime?, primemr?, primes, prime_division|factors, primenth|nthprime
|
200
|
+
```
|
201
|
+
|
178
202
|
## Author
|
179
203
|
Jabari Zakiya
|
180
204
|
|
data/lib/primes/utils.rb
CHANGED
@@ -37,8 +37,8 @@ module Primes
|
|
37
37
|
# Find primes within a number range: end_num - start_num
|
38
38
|
# Uses 'prime?' to check primality of prime candidates in range
|
39
39
|
sozdata = sozcore1(self, start_num, true) # true for primes
|
40
|
-
return sozdata[1] if sozdata[0]
|
41
|
-
pcs_in_range, r, mod, modk, rescnt, residues, primes = sozdata
|
40
|
+
return sozdata[1] if !sozdata[0] # if sozdata[0] false
|
41
|
+
pcs_in_range, r, mod, modk, rescnt, residues, primes = sozdata
|
42
42
|
pcs_in_range.times do # find primes from this num pcs in range
|
43
43
|
prime = modk + residues[r]
|
44
44
|
primes << prime if prime.prime?
|
@@ -51,9 +51,9 @@ module Primes
|
|
51
51
|
# Count primes within a number range: end_num - start_num
|
52
52
|
# Uses 'prime?' to check primality of prime candidates in range
|
53
53
|
sozdata = sozcore1(self, start_num, false) # false for primescnt
|
54
|
-
return sozdata[1] if sozdata[0]
|
55
|
-
pcs_in_range, r, mod, modk, rescnt, residues,
|
56
|
-
|
54
|
+
return sozdata[1] if !sozdata[0] # if sozdata[0] false
|
55
|
+
pcs_in_range, r, mod, modk, rescnt, residues, primescnt = sozdata
|
56
|
+
|
57
57
|
pcs_in_range.times do # count primes from this num pcs in range
|
58
58
|
primescnt +=1 if (modk + residues[r]).prime?
|
59
59
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
@@ -143,25 +143,22 @@ module Primes
|
|
143
143
|
|
144
144
|
n = self.abs # the desired nth prime
|
145
145
|
return n != 0 ? seeds[n-1] : 0 if n <= seeds.size
|
146
|
-
|
147
|
-
start_num, nth, nthflag = set_start_value(n)
|
146
|
+
|
147
|
+
start_num, nth, nthflag = set_start_value(n,true)
|
148
148
|
return start_num if nthflag # output nthprime if nth ref value
|
149
149
|
|
150
150
|
num = approximate_nth(n) # close approx to nth >= real nth
|
151
151
|
primes = seeds[0..seeds.index(p)]
|
152
152
|
|
153
|
-
prms, m, mod, modk, residues, * = sozcore2(num, start_num, primes)
|
153
|
+
prms, m, mod, modk, residues, rescnt, * = sozcore2(num, start_num, primes)
|
154
154
|
return if prms == nil # exit gracefully if sozcore2 mem error
|
155
|
-
|
156
|
-
rescnt = residues[1..-1].size
|
157
|
-
pcs2ks = rescnt*(modk/mod) # rescnt*ks - number of pcs upto ks resgroup
|
158
|
-
|
155
|
+
|
159
156
|
# starting at start_num's location, find nth prime within given range
|
160
157
|
prmcnt = n > nth ? nth-1 : primes.size
|
161
158
|
pcnt = prmcnt + prms[m..-1].count(1) # number of primes upto nth approx
|
162
159
|
return puts "#{pcnt} not enough primes, approx nth too small." if pcnt < n
|
163
160
|
while prmcnt < n; prmcnt +=1 if prms[m] == 1; m +=1 end
|
164
|
-
k, r = (m+pcs2ks).divmod rescnt
|
161
|
+
k, r = (m + rescnt*(modk/mod)).divmod rescnt # (m+pcs2ks).divmod rescnt
|
165
162
|
mod*k + residues[r]
|
166
163
|
end
|
167
164
|
|
@@ -177,13 +174,11 @@ module Primes
|
|
177
174
|
plast = primes.last # last prime in primes
|
178
175
|
return primes.select {|p| p >= start_num && p <= num} if num <= plast
|
179
176
|
|
180
|
-
prms, m, mod, modk, residues, maxprms, r = sozcore2(num, start_num, primes)
|
177
|
+
prms, m, mod, modk, residues, rescnt, maxprms, r = sozcore2(num, start_num, primes)
|
181
178
|
return if prms == nil # exit gracefully if sozcore2 mem error
|
182
179
|
|
183
|
-
rescnt = residues[1..-1].size
|
184
|
-
|
185
180
|
# starting at start_num's location, extract primes within given range
|
186
|
-
primes = start_num <= plast ? primes.
|
181
|
+
primes = start_num <= plast ? primes.select {|p| p >= start_num} : []
|
187
182
|
while m < maxprms # find primes from pcs within given range
|
188
183
|
primes << modk + residues[r] if prms[m] == 1
|
189
184
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
@@ -194,20 +189,27 @@ module Primes
|
|
194
189
|
|
195
190
|
def primescnt(start_num=0)
|
196
191
|
# Count primes between a number range: end_num - start_num
|
197
|
-
# Uses
|
192
|
+
# Uses P5 or P7 Strictly Prime (SP) Prime Generators
|
198
193
|
num = self.abs; start_num = start_num.abs
|
199
194
|
num, start_num = start_num, num if start_num > num
|
200
195
|
|
201
|
-
|
202
|
-
plast
|
203
|
-
return
|
196
|
+
seeds = [2, 3, 5, 7, 11, 13]
|
197
|
+
plast = seeds.last # last prime in seeds
|
198
|
+
return seeds.select {|p| p >= start_num && p <= num}.size if num <= plast
|
199
|
+
|
200
|
+
if start_num == 0
|
201
|
+
start_num, nth, nthflag = set_start_value(num,false)
|
202
|
+
return nth if !nthflag # output nth's number if n a ref nth prime
|
203
|
+
end
|
204
204
|
|
205
|
+
primes = nthflag ? [2,3,5,7] : [2,3,5] # choose P7 or P5
|
205
206
|
prms, m, * = sozcore2(num, start_num, primes)
|
206
207
|
return if prms == nil # exit gracefully if sozcore2 mem error
|
207
208
|
|
208
209
|
# starting at start_num's location, count primes within given range
|
209
|
-
|
210
|
-
|
210
|
+
prmcnt = start_num <= plast ? primes.select {|p| p >= start_num}.size : 0
|
211
|
+
prmcnt = nth > 0 ? nth-1 : primes.size if nthflag # nflag is nil or true
|
212
|
+
prmcnt + prms[m..-1].count(1)
|
211
213
|
end
|
212
214
|
|
213
215
|
# Miller-Rabin prime test in Ruby
|
@@ -242,8 +244,8 @@ module Primes
|
|
242
244
|
# Find primes within a number range: end_num - start_num
|
243
245
|
# Uses 'primemr' to check primality of prime candidates in range
|
244
246
|
sozdata = sozcore1(self, start_num, true) # true for primes
|
245
|
-
return sozdata[1] if sozdata[0]
|
246
|
-
pcs_in_range, r, mod, modk, rescnt, residues, primes = sozdata
|
247
|
+
return sozdata[1] if !sozdata[0] # if sozdata[0] false
|
248
|
+
pcs_in_range, r, mod, modk, rescnt, residues, primes = sozdata
|
247
249
|
pcs_in_range.times do # find primes from this num pcs in range
|
248
250
|
prime = modk + residues[r]
|
249
251
|
primes << prime if prime.primemr?
|
@@ -256,9 +258,9 @@ module Primes
|
|
256
258
|
# Count primes within a number range: end_num - start_num
|
257
259
|
# Uses 'primemr' to check primality of prime candidates in range
|
258
260
|
sozdata = sozcore1(self, start_num, false) # false for primescnt
|
259
|
-
return sozdata[1] if sozdata[0]
|
260
|
-
pcs_in_range, r, mod, modk, rescnt, residues,
|
261
|
-
|
261
|
+
return sozdata[1] if !sozdata[0] # if sozdata[0] false
|
262
|
+
pcs_in_range, r, mod, modk, rescnt, residues, primescnt = sozdata
|
263
|
+
|
262
264
|
pcs_in_range.times do # count primes from this num pcs in range
|
263
265
|
primescnt +=1 if (modk + residues[r]).primemr?
|
264
266
|
r +=1; if r > rescnt; r=1; modk +=mod end
|
@@ -301,23 +303,24 @@ module Primes
|
|
301
303
|
|
302
304
|
def sozcore1(num, start_num, method_flag)
|
303
305
|
# Uses the P13 Strictly Prime (SP) Prime Generator
|
304
|
-
num = num.abs;
|
306
|
+
num = num.abs; start_num = start_num.abs
|
305
307
|
num, start_num = start_num, num if start_num > num
|
306
308
|
|
307
309
|
primes = [2,3,5,7,11,13] # P13 excluded primes lists
|
308
310
|
plast = primes.last # last prime in primes
|
309
311
|
if num <= plast
|
310
312
|
primes = primes.select {|p| p >= start_num && p <= num}
|
311
|
-
return [
|
313
|
+
return [false, method_flag ? primes : primes.size]
|
312
314
|
end
|
313
315
|
mod = primes.reduce(:*) # P13 modulus: 2*3*5*7*11*13 = 30030
|
314
316
|
residues, rescnt = make_residues_rescnt(mod)
|
315
|
-
maxpcs = pcs_to_num(num,mod,rescnt,residues) # num of pcs <= end_num
|
317
|
+
maxpcs = pcs_to_num(num, mod, rescnt, residues) # num of pcs <= end_num
|
316
318
|
|
317
319
|
# compute parameters for start location and number of pcs within range
|
318
|
-
primes = start_num <= plast ? primes.
|
320
|
+
primes = start_num <= plast ? primes.select {|p| p >= start_num} : []
|
319
321
|
m, r, modk = pcs_to_start_num(start_num, mod, rescnt, residues)
|
320
|
-
|
322
|
+
|
323
|
+
[maxpcs-m, r, mod, modk, rescnt, residues, method_flag ? primes : primes.size]
|
321
324
|
end
|
322
325
|
|
323
326
|
# Perform SoZ for given Prime Generator and return array of parameters
|
@@ -327,8 +330,9 @@ module Primes
|
|
327
330
|
# mod - modulus value for PG
|
328
331
|
# modk - mod*ks; mod value for ks, start_num's resgroup
|
329
332
|
# residues - array of residues plus mod+1 for PG
|
333
|
+
# rescnt - number of residues < mod
|
330
334
|
# maxprms - the number of pcs in range to find primes from
|
331
|
-
# r - first residue location in ks >= start_num
|
335
|
+
# r - first residue index location in ks >= start_num
|
332
336
|
|
333
337
|
def sozcore2(num, start_num, primes)
|
334
338
|
mod = primes.reduce(:*) # modulus: modPn = 2*3*5*7*..*Pn
|
@@ -384,7 +388,7 @@ module Primes
|
|
384
388
|
r=1; modk = mod*ks # find 1st residue val|location
|
385
389
|
while modk + residues[r] < start_num; r +=1 end # r in ks >= start_num
|
386
390
|
|
387
|
-
[prms, m=r-1, mod, modk, residues, maxprms, r] # parameter output
|
391
|
+
[prms, m=r-1, mod, modk, residues, rescnt, maxprms, r] # parameter output
|
388
392
|
end
|
389
393
|
|
390
394
|
def approximate_nth(n) # approximate nthprime value >= real value
|
@@ -393,12 +397,16 @@ module Primes
|
|
393
397
|
(n*(Math.log(n)+a)+3).to_i # use nth approximation as end_num of range
|
394
398
|
end
|
395
399
|
|
396
|
-
def set_start_value(n)
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
400
|
+
def set_start_value(n, hshflag) # find largest index nthprime|val <= requested
|
401
|
+
if hshflag
|
402
|
+
return [nths[n], 0, true] if nths.has_key? n # if n is key in nths table
|
403
|
+
nth = nths.keys.sort.select {|k| k < n}.last # find largest indexed key < n
|
404
|
+
[nth ? nths[nth] : 0, nth ||= n+1, false] # [start_num, nth, false]
|
405
|
+
else
|
406
|
+
return [0,nths.key(n),false] if nths.has_value? n # if n is value in nths table
|
407
|
+
v=val = nths.values.sort.select {|v| v < n}.last # find largest indexed val < n
|
408
|
+
[v ||= 0, val ? nths.key(val) : 0, true] # [start_num, nth, true]
|
409
|
+
end
|
402
410
|
end
|
403
411
|
|
404
412
|
def nths # hash table index of reference nth primes
|
@@ -445,7 +453,18 @@ module Primes
|
|
445
453
|
1462500000=>33930284893, 1475000000=>34233442279, 1487500000=>34536683891,
|
446
454
|
1500000000=>34840062373, 1512500000=>35143545889, 1525000000=>35447088559,
|
447
455
|
1537500000=>35750747297, 1550000000=>36054501641, 1562500000=>36358440731,
|
448
|
-
1575000000=>36662430631, 1587500000=>36966563321, 1600000000=>37270791697
|
456
|
+
1575000000=>36662430631, 1587500000=>36966563321, 1600000000=>37270791697,
|
457
|
+
1612500000=>37575137933, 1625000000=>37879532671, 1637500000=>38184009763,
|
458
|
+
1650000000=>38488677419, 1662500000=>38793413899, 1675000000=>39098225629,
|
459
|
+
1687500000=>39403174463, 1700000000=>39708229123, 1712500000=>40013309359,
|
460
|
+
1725000000=>40318523009, 1737500000=>40623800311, 1750000000=>40929166261,
|
461
|
+
1762500000=>41234743751, 1775000000=>41540289619, 1787500000=>41845958971,
|
462
|
+
1800000000=>42151671491, 1812500000=>42457500313, 1825000000=>42763499629,
|
463
|
+
1837500000=>43069571603, 1850000000=>43375710643, 1862500000=>43681898699,
|
464
|
+
1875000000=>43988172667, 1887500000=>44294549347, 1900000000=>44601021791,
|
465
|
+
1912500000=>44907564593, 1925000000=>45214177441, 1937500000=>45520935011,
|
466
|
+
1950000000=>45827700419, 1962500000=>46134655219, 1975000000=>46441643177,
|
467
|
+
1987500000=>46748693981, 2000000000=>47055833459, 2012500000=>47363059687
|
449
468
|
}
|
450
469
|
end
|
451
470
|
end
|
data/lib/primes/utils/version.rb
CHANGED
data/primes-utils.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["jzakiya@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{suite of extremely fast utility methods for testing and generating primes}
|
13
|
-
spec.description = %q{Methods: prime?, primemr?, primes, primesf, primesmr, primescnt, primescntf, primescntmr, nthprime
|
13
|
+
spec.description = %q{Methods: prime?, primemr?, primes, primesf, primesmr, primescnt, primescntf, primescntmr, primenth|nthprime, factors|prime_division}
|
14
14
|
spec.homepage = "https://github.com/jzakiya/primes-utils"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
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.3.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-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
description: 'Methods: prime?, primemr?, primes, primesf, primesmr, primescnt, primescntf,
|
42
|
-
primescntmr, nthprime
|
42
|
+
primescntmr, primenth|nthprime, factors|prime_division'
|
43
43
|
email:
|
44
44
|
- jzakiya@gmail.com
|
45
45
|
executables: []
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
78
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.
|
79
|
+
rubygems_version: 2.4.6
|
80
80
|
signing_key:
|
81
81
|
specification_version: 4
|
82
82
|
summary: suite of extremely fast utility methods for testing and generating primes
|