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 +4 -4
- data/README.md +38 -29
- data/lib/primes/utils/version.rb +1 -1
- data/lib/primes/utils.rb +23 -35
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3435da9b5d2751b38cfcd941c71b3964f6720d49d6135e107a6d510c94d1a300
|
|
4
|
+
data.tar.gz: 643aaddc60f88c661a5df46a157694dc09ccb1985d0934850b4cee10aec96315
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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)
|
|
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.
|
|
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
|
|
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.
|
data/lib/primes/utils/version.rb
CHANGED
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 =
|
|
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 =
|
|
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?
|
|
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
|
-
#
|
|
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 [
|
|
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
|
-
|
|
267
|
-
while
|
|
268
|
-
residues <<
|
|
269
|
-
|
|
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 =
|
|
296
|
-
start_num =
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
pcs_to_end
|
|
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)
|
|
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 =
|
|
322
|
-
k = (start_num -
|
|
323
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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:
|
|
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: []
|