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 +4 -4
- data/README.md +23 -8
- data/lib/primes/utils/version.rb +1 -1
- data/lib/primes/utils.rb +27 -43
- 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: 6e4efbd1adfba3980cb7d23ff8d6a604c835a1d8159993d52676941534ac9454
|
|
4
|
+
data.tar.gz: 1e730c6ec9e6e505cc7dbcaa706c7a788f25fd3b746b8d3738002f2c95d2d8bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 (
|
|
54
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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.
|
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
|
|
@@ -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,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
|
-
|
|
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
|
-
#
|
|
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
|
|
288
|
-
# outputs:
|
|
289
|
-
#
|
|
290
|
-
#
|
|
291
|
-
|
|
292
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
-
|
|
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)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
|
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.
|
|
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:
|
|
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: []
|