primes-utils 3.1.0 → 3.1.2

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
  SHA256:
3
- metadata.gz: 0d80c687d9af99e83fa89aa6d04b0d5b9f818568f46efb1d80ff31ee5959e348
4
- data.tar.gz: 5cad72faacddd4ec9ed53c712dfecc337728fea989eaf87d9a42732e7e6b2c02
3
+ metadata.gz: 3435da9b5d2751b38cfcd941c71b3964f6720d49d6135e107a6d510c94d1a300
4
+ data.tar.gz: 643aaddc60f88c661a5df46a157694dc09ccb1985d0934850b4cee10aec96315
5
5
  SHA512:
6
- metadata.gz: e1af46320695654351eca38beeb8efa42b1c08a93399526155e6f6d120945bbcd0af35dcdec176c0f4a686132e073258beaa25b803ed0a486442fdbf32a784ad
7
- data.tar.gz: 2c2eff694192f3e007c788dd3788a6badce5920fd3539a6f0104e86b9b3f7333a93bb90444027817cb5b45a63062f592f4be361a25683325501f67e2d8a93313
6
+ metadata.gz: 1ba81561472f6b2f0aca9fa13e64f7ebd646cb9dc87c967f6eac8c7d2abe201b65a5bf9ee8b4356e66112a71b3f88568f0182f7d2ec25ffc31419eeabc78688f
7
+ data.tar.gz: c124bddc0251d7362b01b62a1e64f4caee2e6b0c0bca837a1a472cdf0eb743592786d6af017dd3b07f1eec840bccbe8f5244e929653a1d7662df243f77dfc841
data/README.md CHANGED
@@ -34,28 +34,6 @@ Then require as:
34
34
 
35
35
  ## Methods
36
36
 
37
- **prime?**
38
-
39
- Determine if an integer value is prime, and return `true` or `false`.
40
- This replaces the `prime?` method in the `prime.rb` standard library.
41
- Uses PGT residues tests, then Miller-Rabin test using `primemr?`.
42
-
43
- ```
44
- 101.prime? => true
45
- 100.prime? => false
46
- -71.prime? => false
47
- 0.prime? => false
48
- 1.prime? => false
49
- ```
50
-
51
- **primemr?(k=5)**
52
-
53
- Optimized deterministic (over 64-bits) implementation of Miller-Rabin algorithm.
54
- Default non-deterministic reliability set at k = 5, set higher if desired for very large numbers > 64-bts.
55
-
56
- ```
57
- n.prime?(6)
58
- ```
59
37
 
60
38
  **factors or prime_division**
61
39
 
@@ -80,7 +58,32 @@ Pure Ruby version equivalent of `factors`.
80
58
  Not as fast as `factors` for some values with multiple large prime factors.
81
59
  Always available if OS doesn't have coreutils `factor`.
82
60
 
83
- **primes(start=0), primesmr(start=0)**
61
+ ```
62
+ 123_456_789.factors1 => [[3, 1], [7, 2], [839087, 1]]
63
+ 5_000_000_000_000_000_003.factors1 => [[5000000000000000003, 1]]
64
+ 987_654_321_012_345_678_901_382_739.factors1 => [[3, 1], [23, 1], [139, 1], [421, 1], [3469, 1], [7393, 1], [135899, 1], [70180703, 1]]
65
+ ```
66
+
67
+ **prime?(k=5) or primemr?(k=5)**
68
+
69
+ Determine if an integer value is prime, and return `true` or `false`.
70
+ `prime?` replaces the `prime?` method in the `prime.rb` standard library.
71
+ It uses PGT residues tests, then Miller-Rabin test using `primemr?`.
72
+ Default probabilistic reliability constant set at k = 5, set higher if desired for numbers > 128-bts.
73
+ Not really necessary to do though.
74
+
75
+ ```
76
+ 101.prime? => true
77
+ 100.prime? => false
78
+ -71.prime? => false
79
+ 0.primemr? => false
80
+ 1.primemr? => false
81
+ 5_000_000_000_000_000_003.primemr? => true
82
+ 987_654_321_012_345_678_901_382_737.prime? 6 => true
83
+ 987_654_321_012_345_678_901_382_739.prime? 6 => false
84
+ ```
85
+
86
+ **primes(start=0) or primesmr(start=0)**
84
87
 
85
88
  Return an array of prime values within the inclusive integers range `[start_num - end_num]`.
86
89
  Input order doesn't matter if both given: `start_num.primes end_num <=> end_num.prime start_num`.
@@ -103,13 +106,14 @@ prms => [1000003, 1000033, 1000037, 1000039, 1000081, 1000099]
103
106
  0.primesmr => []
104
107
  ```
105
108
 
106
- **primescnt(start=0), primescntmr(start=0)**
109
+ **primescnt(start=0) or primescntmr(start=0)**
107
110
 
108
111
  Provide count of primes within the inclusive integers range `[start_num - end_num]`.
109
112
  Input order doesn't matter if both given: `start_num.primes end_num <=> end_num.prime start_num`.
110
113
  A single input is taken as `end_num`, and the primes count <= to it are returned.
111
- `primescnt` is faster; uses SoZ to identify|count primes from closest hashed value starting point.
112
- `primescntmr` is slower, but isn't memory limited, especially for very large numbers|ranges.
114
+ `primescnt` is generally faster; uses SoZ to identify|count primes from closest hashed value starting point.
115
+ `primescntmr` is situationally slower, but isn't memory limited, especially for very large numbers|ranges.
116
+ Can also perform effective primality test on an integer n as: `n.primescntmr n`
113
117
  See `PRIMES-UTILS HANDBOOK` for details on best use practices.
114
118
  Also see `Error Handling`.
115
119
 
@@ -120,8 +124,11 @@ Also see `Error Handling`.
120
124
  100000.primescntmr 100500 => 40
121
125
  n=10**400; (n-500).primescntmr(n+500) => 1
122
126
  n=10**8; (25*n).primescnt => 121443371
127
+ 541.primescntmr 7919 => 901
123
128
  0.primescnt => 0
124
129
  1.primescntmr => 0
130
+ 100.primescntmr 100 => 0
131
+ 101.primescntmr 101 => 1
125
132
  ```
126
133
 
127
134
  **primenth(p=0) or nthprime(p=0)**
@@ -174,7 +181,7 @@ Return value of previous prime < n > 2. Returns `nil` for n < 2 (and negatives)
174
181
  Displays a list of all the `primes-utils` methods available for a system.
175
182
  Use as eg: `0.primes_utils` where input n is any `class Integer` value.
176
183
 
177
- Available methods for 3.0.0.
184
+ Available methods for 3.1.2.
178
185
 
179
186
  ```
180
187
  0.primes_utils => "prime? primes primesmr primescnt primescntmr primenth|nthprime factors|prime_division factors1 next_prime prev_prime primes_utils"
@@ -194,9 +201,9 @@ If they occur you will know why now.
194
201
  This behavior is referenced to MRI Ruby.
195
202
 
196
203
  ## Coding Implementations
197
- The method `prime_division|factors` has 2 implementations. A pure ruby implementation, and a hybrid implementation
204
+ The method `prime_division|factors` has 2 implementations. A pure ruby implementation `factors1`, and a hybrid implementation
198
205
  using the Unix cli command `factor` [5], if available on the host OS. It's an extremely fast C coded factoring algorithm,
199
- part of the GNU Core Utilities package [4].
206
+ part of the GNU Core Utilities package [4]. However, `factors1` is always exists separately.
200
207
 
201
208
  Upon loading, the gem tests if the command `factor` exists on the host OS.
202
209
  If so, it performs a system call to it within `prime_division|factors`, and Ruby reformats its output.
@@ -208,6 +215,8 @@ All the `primes-utils` methods are `instance_methods` for `Class Integer`.
208
215
 
209
216
  ## History
210
217
  ```
218
+ 3.1.2 – method refactor, documentation updates
219
+ 3.1.1 – some methods refactoring|DRYing, documentation updates
211
220
  3.1.0 – major performance enhancements for methods primescnt, primescntmr, and nthprimes,
212
221
  primarily by extending nth primes hash values up to 10.1 billion. Can now find nth primes
213
222
  over ranges up to 10.1 billion, and thus prime counts up to 253+ billion, in < 30 secs at ~5Ghz.
@@ -1,5 +1,5 @@
1
1
  module Primes
2
2
  module Utils
3
- VERSION = "3.1.0"
3
+ VERSION = "3.1.2"
4
4
  end
5
5
  end
data/lib/primes/utils.rb CHANGED
@@ -112,7 +112,7 @@ module Primes
112
112
  def primescnt(start_num = 0)
113
113
  end_num, start_num = check_inputs(self, start_num)
114
114
 
115
- nthflag, nth = 0, 0
115
+ nthflag, nth = nil, 0
116
116
  if start_num < 3 # for all primes upto num
117
117
  start_num, nth, nthflag = set_start_value(end_num, false) # closest nth value
118
118
  return nth unless nthflag # output num's key|count if ref nth value
@@ -149,7 +149,7 @@ module Primes
149
149
  def primescntmr(start_num = 0)
150
150
  end_num, start_num = check_inputs(self, start_num)
151
151
 
152
- nthflag, nth = 0, 0
152
+ nthflag, nth = nil, 0
153
153
  if start_num < 3 # for all primes upto num
154
154
  start_num, nth, nthflag = set_start_value(end_num, false) # closest nth value
155
155
  return nth unless nthflag # output num's key|count if ref nth value
@@ -167,7 +167,7 @@ module Primes
167
167
  end
168
168
 
169
169
  # PGT and Miller-Rabin combined primality tests for random n
170
- def prime? (k = 5) # Can change k up|down for primemr?
170
+ def prime?(k = 5) # Can change k up|down for primemr?
171
171
  # Use PGT residue checks for small values < PRIMES.last**2
172
172
  return PRIMES.include? self if self <= PRIMES.last
173
173
  return false if MODPN.gcd(self) != 1
@@ -247,7 +247,7 @@ module Primes
247
247
  PRIMES = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103]
248
248
  PRIMES_LAST_SQRD = PRIMES.last ** 2
249
249
 
250
- # Retunr correct order for inputs range values start_num|end_num
250
+ # Return correct order for inputs range values start_num|end_num
251
251
  # If either are negative then raise an error
252
252
  def check_inputs(end_num, start_num)
253
253
  raise "invalid negative input(s)" if end_num < 0 || start_num < 0
@@ -255,7 +255,7 @@ module Primes
255
255
  [end_num, start_num]
256
256
  end
257
257
 
258
- # Returns for SP PG mod value array of residues [r1, r2,..mod-1, mod+1]
258
+ # Returns for SP PG mod value array of residues [r0, r1,..mod-1, mod+1]
259
259
  def make_residues(modpg)
260
260
  return [ 7, 11, 13, 17, 19, 23, 29, 31] if modpg == 30
261
261
  return [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
@@ -263,24 +263,14 @@ module Primes
263
263
  139, 143, 149, 151, 157, 163, 167, 169, 173, 179, 181, 187, 191,
264
264
  193, 197, 199, 209, 211] if modpg == 210
265
265
  residues = []
266
- pc, inc, midmod = 13, 4, modpg >> 1
267
- while pc < midmod
268
- residues << pc << (modpg - pc) if modpg.gcd(pc) == 1
269
- pc += inc; inc ^= 0b110
266
+ rc, inc, midmod = 13, 4, modpg / 2
267
+ while rc < midmod
268
+ residues << rc << (modpg - rc) if modpg.gcd(rc) == 1
269
+ rc += inc; inc ^= 0b110
270
270
  end
271
271
  residues.sort << (modpg - 1) << (modpg + 1)
272
272
  end
273
273
 
274
- # lte = true: first output element is number of pcs <= num
275
- # lte = false: num pcs <, residue index, resgroup val, for (start_)num pc
276
- def pcs_to_num(num, residues, lte)
277
- modpg, rescnt = residues[-1] - 1, residues.size
278
- num -= 1; lte ? (num |= 1; k = num.abs/modpg) : k = (num - 1).abs/modpg
279
- modk = modpg * k; r = 0
280
- r = r.succ while num >= modk + residues[r]
281
- [rescnt * k + r, r, modk] # [num pcs, r index, num modulus]
282
- end
283
-
284
274
  # Determine number of pcs upto the effective start, end, and range width.
285
275
  # The effective start_num is first pc >= start_num, first pc <= end_num,
286
276
  # and effective range is number of pcs between them (inclusive).
@@ -292,15 +282,13 @@ module Primes
292
282
  # pcs_in_range - total number of pcs in effective range
293
283
  def pcs_to_nums(end_num, start_num, residues)
294
284
  modpg, rescnt = residues[-1] - 1, residues.size
295
- end_num = 2 if end_num < residues[0]
296
- start_num = 2 if start_num < residues[0]
297
- start_num -= 1; k1 = (start_num - 1)/modpg; modk1 = modpg * k1
298
- end_num -= 1; k2 = (end_num |= 1 )/modpg; modk2 = modpg * k2
299
- r1 = 0; r1 = r1.succ while start_num >= modk1 + residues[r1]
300
- r2 = 0; r2 = r2.succ while end_num >= modk2 + residues[r2]
301
- pcs_to_end = k2 * rescnt + r2; pcs_to_start = k1 * rescnt + r1
302
- pcs_in_range = pcs_to_end - pcs_to_start
303
- [pcs_to_end, pcs_to_start, r1, modk1, pcs_in_range]
285
+ end_num, k2 = end_num < residues[0] ? [1, 0] : [(end_num - 1)|1, ((end_num - 1)|1)/modpg]
286
+ start_num, k1 = start_num < residues[0] ? [1, 0] : [start_num - 1, (start_num - 2)/modpg]
287
+ r1, r2, resk1, resk2 = 0, 0, start_num - (modk1 = k1 * modpg), end_num - (k2 * modpg)
288
+ r1 = r1.succ while resk1 >= residues[r1]
289
+ r2 = r2.succ while resk2 >= residues[r2]
290
+ pcs_to_end, pcs_to_start = k2 * rescnt + r2, k1 * rescnt + r1
291
+ [pcs_to_end, pcs_to_start, r1, modk1, (pcs_in_range = pcs_to_end - pcs_to_start)]
304
292
  end
305
293
 
306
294
  # Select SP Prime Generator to parametize the pcs within inputs range
@@ -316,11 +304,11 @@ module Primes
316
304
  elsif range < 24_494_897; 510_510 # P17; Math.isqrt(600_000_000_000_000)
317
305
  else 9_699_690 # P19
318
306
  end
319
- residues = make_residues(modpg) # chosen PG residues
307
+ residues = make_residues(modpg) # chosen PG residues
320
308
  primes = PRIMES.select { |p| p < residues[0] && p.between?(start_num, end_num) }
321
- start_num = 2 if start_num < residues[0]
322
- k = (start_num - 2) / modpg; modk = k * modpg; r = 0
323
- while (start_num - 1) >= modk + residues[r]; r = r.succ end
309
+ start_num = start_num < residues[0] ? 1 : start_num - 1
310
+ k = (start_num - 1) / modpg; modk = k * modpg; r = 0; resk = start_num - modk
311
+ r = r.succ while resk >= residues[r]
324
312
  [r, modk, residues, primes]
325
313
  end
326
314
 
@@ -334,8 +322,8 @@ module Primes
334
322
  # rs - residue index location for first pc >= start_num
335
323
  def sozcore2(end_num, start_num, modpg)
336
324
  residues = make_residues(modpg); rescnt = residues.size
337
- maxpcs, pcs_to_start, rs, modks, pcs_range = pcs_to_nums(end_num, start_num, residues)
338
- sqrtN, inputs_range = Integer.sqrt(end_num), end_num - start_num
325
+ pcs_to_end, pcs_to_start, rs, modks, pcs_range = pcs_to_nums(end_num, start_num, residues)
326
+ sqrtN, maxpcs, inputs_range = Integer.sqrt(end_num), pcs_to_end, end_num - start_num
339
327
  pcs_to_sqrtN, _ = pcs_to_nums(sqrtN, 0, residues) # num pcs <= sqrtN
340
328
 
341
329
  m = pcs_to_start # index to start retrieving primes in prms array
@@ -355,7 +343,7 @@ module Primes
355
343
  prm_r = residues[i % rescnt] # save its residue value
356
344
  prime = modpg*(k=i/rescnt) + prm_r # numerate its value; set k resgroup value
357
345
  rem = start_num % prime # prime's modular distance to start_num
358
- next unless (prime - rem <= inputs_range) || rem == 0 # skip prime if no mulitple in range
346
+ next unless (prime - rem <= inputs_range) || rem == 0 # skip prime if no multiple in range
359
347
  prmstep = prime * rescnt # compute its primestep
360
348
  residues.each do |ri| # find|mark its multiples
361
349
  # convert (prime * (modk + ri)) pc value to its address in prms
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primes-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jabari Zakiya
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
94
  requirements: []
95
- rubygems_version: 3.6.9
95
+ rubygems_version: 4.0.3
96
96
  specification_version: 4
97
97
  summary: suite of extremely fast utility methods for testing and generating primes
98
98
  test_files: []