primes-utils 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63a02f55e631a8d239a409e4b140d5323a45cdec
4
- data.tar.gz: aeab7ca1a389c6462ef0657998032f9e95020bff
3
+ metadata.gz: ff3c9d871e492288cbbfac6beb023fd765f9bf8e
4
+ data.tar.gz: 976926b10063c0fc58ea29b33765b800c937727f
5
5
  SHA512:
6
- metadata.gz: abe70b780cdf9efc202620c318e06373c710a46203393e4c7798df9502b48a5960ae7a07abafea4ffb2a8d837b3efdd308920a0006a581391eba06534f484caf
7
- data.tar.gz: 74faf8fc525138bfc7e29454e986428ae6254ac002bde7596c194c6ee27078783f25f8140532bd8ba3491133a846e7b44d09acd80f57d3bf26ad24d043d297ab
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
- 100000.primescnt => 9592
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 then the range size, or end_num, need arrays greater than the amount of avalable memory. The first case shows the message
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
 
@@ -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[1..-1]
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, primes = sozdata[1..-1]
56
- primescnt = primes.size
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.drop_while {|p| p < start_num} : []
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 the P5 Strictly Prime (SP) Prime Generator
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
- primes = [2,3,5] # P5 excluded primes lists
202
- plast = primes.last # last prime in primes
203
- return primes.select {|p| p >= start_num && p <= num}.size if num <= plast
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
- primes = start_num <= plast ? primes.drop_while {|p| p < start_num} : []
210
- primecnt = primes.size + prms[m..-1].count(1)
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[1..-1]
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, primes = sozdata[1..-1]
261
- primescnt = primes.size
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; start_num = start_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 [true, method_flag ? primes : primes.size]
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.drop_while {|p| p < start_num} : []
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
- [false, maxpcs-m, r, mod, modk, rescnt, residues, primes]
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) # find closest index nthprime <= requested nth
397
- nthkeys = nths.keys.sort # create array of indexed nth numbers
398
- return [nths[n], 0, true] if nthkeys.include? n # if n in nths table
399
- start_num, nth = 0, nthkeys[0]
400
- nthkeys.each {|i| start_num, nth = nths[i], i if n > i}
401
- [start_num, nth, false] # use index prime value as start_num of range
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
@@ -1,5 +1,5 @@
1
1
  module Primes
2
2
  module Utils
3
- VERSION = "2.2.0"
3
+ VERSION = "2.3.0"
4
4
  end
5
5
  end
@@ -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/primenth, factors/prime_division}
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.2.0
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-06-19 00:00:00.000000000 Z
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/primenth, factors/prime_division'
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.2.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