primes-utils 3.1.0 → 3.1.1

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: 6e4efbd1adfba3980cb7d23ff8d6a604c835a1d8159993d52676941534ac9454
4
+ data.tar.gz: 1e730c6ec9e6e505cc7dbcaa706c7a788f25fd3b746b8d3738002f2c95d2d8bd
5
5
  SHA512:
6
- metadata.gz: e1af46320695654351eca38beeb8efa42b1c08a93399526155e6f6d120945bbcd0af35dcdec176c0f4a686132e073258beaa25b803ed0a486442fdbf32a784ad
7
- data.tar.gz: 2c2eff694192f3e007c788dd3788a6badce5920fd3539a6f0104e86b9b3f7333a93bb90444027817cb5b45a63062f592f4be361a25683325501f67e2d8a93313
6
+ metadata.gz: 6af6def197418a3c5cf68c0a75d0ce182a96b60f1f414d6da2762ddf7156476a0d863f79bc65d08dc6824d62421f932e082ffb0b718f632a19ac416af618292a
7
+ data.tar.gz: 954aa75ea469ef4ccaaaf3b14b20c78d4d2c1b7e2ee7803126d40e2d35fbcd68e9682bf30710ca7127af31b2f86688951970bef2f7e51ac8ff3102973d0ca984
data/README.md CHANGED
@@ -50,11 +50,15 @@ Uses PGT residues tests, then Miller-Rabin test using `primemr?`.
50
50
 
51
51
  **primemr?(k=5)**
52
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.
53
+ Optimized deterministic (to 128-bits) implementation of Miller-Rabin algorithm.
54
+ It's the underlying primality test for `prime`, and used in other methods.
55
+ Default probabilistic reliability constant set at k = 5, set higher if desired for numbers > 128-bts.
56
+ Not really necessary to do though.
55
57
 
56
58
  ```
57
- n.prime?(6)
59
+ 5_000_000_000_000_000_003.primemr? => true
60
+ 987_654_321_012_345_678_901_382_737.primemr? 6 => true
61
+ 987_654_321_012_345_678_901_382_739.primemr? 6 => false
58
62
  ```
59
63
 
60
64
  **factors or prime_division**
@@ -80,6 +84,12 @@ Pure Ruby version equivalent of `factors`.
80
84
  Not as fast as `factors` for some values with multiple large prime factors.
81
85
  Always available if OS doesn't have coreutils `factor`.
82
86
 
87
+ ```
88
+ 123_456_789.factors1 => [[3, 1], [7, 2], [839087, 1]]
89
+ 5_000_000_000_000_000_003.factors1 => [[5000000000000000003, 1]]
90
+ 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]]
91
+ ```
92
+
83
93
  **primes(start=0), primesmr(start=0)**
84
94
 
85
95
  Return an array of prime values within the inclusive integers range `[start_num - end_num]`.
@@ -108,8 +118,9 @@ prms => [1000003, 1000033, 1000037, 1000039, 1000081, 1000099]
108
118
  Provide count of primes within the inclusive integers range `[start_num - end_num]`.
109
119
  Input order doesn't matter if both given: `start_num.primes end_num <=> end_num.prime start_num`.
110
120
  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.
121
+ `primescnt` is generally faster; uses SoZ to identify|count primes from closest hashed value starting point.
122
+ `primescntmr` is situationally slower, but isn't memory limited, especially for very large numbers|ranges.
123
+ Can also perform effective primality test on an integer n as: `n.primescntmr n`
113
124
  See `PRIMES-UTILS HANDBOOK` for details on best use practices.
114
125
  Also see `Error Handling`.
115
126
 
@@ -120,8 +131,11 @@ Also see `Error Handling`.
120
131
  100000.primescntmr 100500 => 40
121
132
  n=10**400; (n-500).primescntmr(n+500) => 1
122
133
  n=10**8; (25*n).primescnt => 121443371
134
+ 541.primescntmr 7919 => 901
123
135
  0.primescnt => 0
124
136
  1.primescntmr => 0
137
+ 100.primescntmr 100 => 0
138
+ 101.primescntmr 101 => 1
125
139
  ```
126
140
 
127
141
  **primenth(p=0) or nthprime(p=0)**
@@ -174,7 +188,7 @@ Return value of previous prime < n > 2. Returns `nil` for n < 2 (and negatives)
174
188
  Displays a list of all the `primes-utils` methods available for a system.
175
189
  Use as eg: `0.primes_utils` where input n is any `class Integer` value.
176
190
 
177
- Available methods for 3.0.0.
191
+ Available methods for 3.1.1.
178
192
 
179
193
  ```
180
194
  0.primes_utils => "prime? primes primesmr primescnt primescntmr primenth|nthprime factors|prime_division factors1 next_prime prev_prime primes_utils"
@@ -194,9 +208,9 @@ If they occur you will know why now.
194
208
  This behavior is referenced to MRI Ruby.
195
209
 
196
210
  ## Coding Implementations
197
- The method `prime_division|factors` has 2 implementations. A pure ruby implementation, and a hybrid implementation
211
+ The method `prime_division|factors` has 2 implementations. A pure ruby implementation `factors1`, and a hybrid implementation
198
212
  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].
213
+ part of the GNU Core Utilities package [4]. However, `factors1` is always exists separately.
200
214
 
201
215
  Upon loading, the gem tests if the command `factor` exists on the host OS.
202
216
  If so, it performs a system call to it within `prime_division|factors`, and Ruby reformats its output.
@@ -208,6 +222,7 @@ All the `primes-utils` methods are `instance_methods` for `Class Integer`.
208
222
 
209
223
  ## History
210
224
  ```
225
+ 3.1.1 – some methods refactoring|DRYing, documentation updates
211
226
  3.1.0 – major performance enhancements for methods primescnt, primescntmr, and nthprimes,
212
227
  primarily by extending nth primes hash values up to 10.1 billion. Can now find nth primes
213
228
  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.1"
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
@@ -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,44 +263,28 @@ 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
- # Determine number of pcs upto the effective start, end, and range width.
274
+ # Determine number of pcs upto the effective start|end vals; w/flag
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).
287
- # inputs: end_num and start_num of range, and PGs residues array
288
- # outputs: pcs_to_end - number of pcs in <= end_num pc for PG
289
- # pcs_to_start - number of pcs < effective start_num pc for range
290
- # r1 - residue index for effective start_num pc
291
- # modk1 - mod resgroup value for effective start_num pc
292
- # pcs_in_range - total number of pcs in effective range
293
- def pcs_to_nums(end_num, start_num, residues)
277
+ # inputs: end_num|start_num of range, PGs residues array, start:t|end:f flag
278
+ # outputs: pcs_to_num - number of pcs < start_num or <= end_num
279
+ # r - residue index for effective start_num pc
280
+ # modk - mod resgroup value for effective num value
281
+ def pcs_to_num(num, residues, flag)
282
+ return [0, 0, 0] if num < residues[0]
294
283
  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]
284
+ val1, val2 = flag ? [num-2, num-1] : [(num-1)|1, (num-1)|1]
285
+ k = val1 / modpg; modk = k * modpg; r = 0; resk = val2 - modk
286
+ r = r.succ while resk >= residues[r]; pcs_to_num = k * rescnt + r
287
+ [pcs_to_num, r, modk]
304
288
  end
305
289
 
306
290
  # Select SP Prime Generator to parametize the pcs within inputs range
@@ -318,9 +302,7 @@ module Primes
318
302
  end
319
303
  residues = make_residues(modpg) # chosen PG residues
320
304
  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
305
+ _, r, modk = pcs_to_num(start_num, residues, true)
324
306
  [r, modk, residues, primes]
325
307
  end
326
308
 
@@ -333,10 +315,12 @@ module Primes
333
315
  # pcs2start- number of pcs < start_num pc
334
316
  # rs - residue index location for first pc >= start_num
335
317
  def sozcore2(end_num, start_num, modpg)
336
- 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
339
- pcs_to_sqrtN, _ = pcs_to_nums(sqrtN, 0, residues) # num pcs <= sqrtN
318
+ residues = make_residues(modpg)
319
+ rescnt, sqrtN = residues.size, Integer.sqrt(end_num)
320
+ pcs_to_start, rs, modks = pcs_to_num(start_num, residues, true) # num pcs < start_num
321
+ maxpcs, _ = pcs_to_num(end_num, residues, false) # num pcs <= end_num
322
+ pcs_to_sqrtN, _ = pcs_to_num(sqrtN, residues, false) # num pcs <= sqrtN
323
+ inputs_range, pcs_range = end_num - start_num, maxpcs - pcs_to_start
340
324
 
341
325
  m = pcs_to_start # index to start retrieving primes in prms array
342
326
  split_arrays = (start_num > sqrtN) # flag, true for split arrays
@@ -355,7 +339,7 @@ module Primes
355
339
  prm_r = residues[i % rescnt] # save its residue value
356
340
  prime = modpg*(k=i/rescnt) + prm_r # numerate its value; set k resgroup value
357
341
  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
342
+ next unless (prime - rem <= inputs_range) || rem == 0 # skip prime if no multiple in range
359
343
  prmstep = prime * rescnt # compute its primestep
360
344
  residues.each do |ri| # find|mark its multiples
361
345
  # 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.1
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: []