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 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