prime 0.1.0 → 0.1.3
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/{LICENSE.txt → BSDL} +3 -3
- data/COPYING +56 -0
- data/README.md +5 -2
- data/Rakefile +2 -2
- data/lib/prime.rb +121 -23
- data/prime.gemspec +8 -7
- data/sig/integer-extension.rbs +41 -0
- data/sig/manifest.yaml +2 -0
- data/sig/prime.rbs +372 -0
- metadata +16 -30
- data/.gitignore +0 -9
- data/.travis.yml +0 -6
- data/Gemfile +0 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 145fdb7bf35cfc518b2ab469df94b560ee67199edccaef17caf2b20cc5adfd0f
|
4
|
+
data.tar.gz: c266767b310ed54143941a36449e0bb013d8b23a585dedc73662708056ba300e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8fa1c530cea6fa87d14911a9e5e98ca323ab81e680e8132a822b1ca9c1195469995948e9245dba45668864b4b08797a3f9bac713b8999b0e4a7a5ac9b772603
|
7
|
+
data.tar.gz: 0b7c4426d5f509d411fe8658f05811b6b1f7ce8b2d49125ef7f702725708ac4bc52b7a92c39e45633bab1d37adeb0e4f38bde72cb48d399682d9e50d430b065b
|
data/{LICENSE.txt → BSDL}
RENAMED
@@ -4,10 +4,10 @@ Redistribution and use in source and binary forms, with or without
|
|
4
4
|
modification, are permitted provided that the following conditions
|
5
5
|
are met:
|
6
6
|
1. Redistributions of source code must retain the above copyright
|
7
|
-
notice, this list of conditions and the following disclaimer.
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
8
|
2. Redistributions in binary form must reproduce the above copyright
|
9
|
-
notice, this list of conditions and the following disclaimer in the
|
10
|
-
documentation and/or other materials provided with the distribution.
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
11
|
|
12
12
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
13
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
data/COPYING
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the
|
3
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a. place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b. use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c. give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d. make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a. distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b. accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c. give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d. make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
For the list of those files and their copying conditions, see the
|
45
|
+
file LEGAL.
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Prime
|
2
2
|
|
3
|
+
[](https://github.com/ruby/prime/actions/workflows/test.yml)
|
4
|
+
|
3
5
|
Prime numbers and factorization library.
|
4
6
|
|
5
7
|
## Installation
|
@@ -33,8 +35,9 @@ Prime.prime?(7) #=> true
|
|
33
35
|
8.prime? #=> false
|
34
36
|
|
35
37
|
# Factorization in prime numbers
|
36
|
-
Prime.prime_division(
|
37
|
-
Prime.int_from_prime_division([[
|
38
|
+
Prime.prime_division(8959) #=> [[17, 2], [31, 1]]
|
39
|
+
Prime.int_from_prime_division([[17, 2], [31, 1]]) #=> 8959
|
40
|
+
17**2 * 31 #=> 8959
|
38
41
|
```
|
39
42
|
|
40
43
|
## Contributing
|
data/Rakefile
CHANGED
data/lib/prime.rb
CHANGED
@@ -31,8 +31,14 @@ class Integer
|
|
31
31
|
end
|
32
32
|
|
33
33
|
# Returns true if +self+ is a prime number, else returns false.
|
34
|
+
# Not recommended for very big integers (> 10**23).
|
34
35
|
def prime?
|
35
36
|
return self >= 2 if self <= 3
|
37
|
+
|
38
|
+
if (bases = miller_rabin_bases)
|
39
|
+
return miller_rabin_test(bases)
|
40
|
+
end
|
41
|
+
|
36
42
|
return true if self == 5
|
37
43
|
return false unless 30.gcd(self) == 1
|
38
44
|
(7..Integer.sqrt(self)).step(30) do |p|
|
@@ -43,6 +49,73 @@ class Integer
|
|
43
49
|
true
|
44
50
|
end
|
45
51
|
|
52
|
+
MILLER_RABIN_BASES = [
|
53
|
+
[2],
|
54
|
+
[2,3],
|
55
|
+
[31,73],
|
56
|
+
[2,3,5],
|
57
|
+
[2,3,5,7],
|
58
|
+
[2,7,61],
|
59
|
+
[2,13,23,1662803],
|
60
|
+
[2,3,5,7,11],
|
61
|
+
[2,3,5,7,11,13],
|
62
|
+
[2,3,5,7,11,13,17],
|
63
|
+
[2,3,5,7,11,13,17,19,23],
|
64
|
+
[2,3,5,7,11,13,17,19,23,29,31,37],
|
65
|
+
[2,3,5,7,11,13,17,19,23,29,31,37,41],
|
66
|
+
].map!(&:freeze).freeze
|
67
|
+
private_constant :MILLER_RABIN_BASES
|
68
|
+
|
69
|
+
private def miller_rabin_bases
|
70
|
+
# Miller-Rabin's complexity is O(k log^3n).
|
71
|
+
# So we can reduce the complexity by reducing the number of bases tested.
|
72
|
+
# Using values from https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
|
73
|
+
i = case
|
74
|
+
when self < 0xffff then
|
75
|
+
# For small integers, Miller Rabin can be slower
|
76
|
+
# There is no mathematical significance to 0xffff
|
77
|
+
return nil
|
78
|
+
# when self < 2_047 then 0
|
79
|
+
when self < 1_373_653 then 1
|
80
|
+
when self < 9_080_191 then 2
|
81
|
+
when self < 25_326_001 then 3
|
82
|
+
when self < 3_215_031_751 then 4
|
83
|
+
when self < 4_759_123_141 then 5
|
84
|
+
when self < 1_122_004_669_633 then 6
|
85
|
+
when self < 2_152_302_898_747 then 7
|
86
|
+
when self < 3_474_749_660_383 then 8
|
87
|
+
when self < 341_550_071_728_321 then 9
|
88
|
+
when self < 3_825_123_056_546_413_051 then 10
|
89
|
+
when self < 318_665_857_834_031_151_167_461 then 11
|
90
|
+
when self < 3_317_044_064_679_887_385_961_981 then 12
|
91
|
+
else return nil
|
92
|
+
end
|
93
|
+
MILLER_RABIN_BASES[i]
|
94
|
+
end
|
95
|
+
|
96
|
+
private def miller_rabin_test(bases)
|
97
|
+
return false if even?
|
98
|
+
|
99
|
+
r = 0
|
100
|
+
d = self >> 1
|
101
|
+
while d.even?
|
102
|
+
d >>= 1
|
103
|
+
r += 1
|
104
|
+
end
|
105
|
+
|
106
|
+
self_minus_1 = self-1
|
107
|
+
bases.each do |a|
|
108
|
+
x = a.pow(d, self)
|
109
|
+
next if x == 1 || x == self_minus_1 || a == self
|
110
|
+
|
111
|
+
return false if r.times do
|
112
|
+
x = x.pow(2, self)
|
113
|
+
break if x == self_minus_1
|
114
|
+
end
|
115
|
+
end
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
46
119
|
# Iterates the given block over all prime numbers.
|
47
120
|
#
|
48
121
|
# See +Prime+#each for more details.
|
@@ -84,7 +157,7 @@ end
|
|
84
157
|
# There are few implementations of generator.
|
85
158
|
#
|
86
159
|
# [+Prime+::+EratosthenesGenerator+]
|
87
|
-
# Uses
|
160
|
+
# Uses Eratosthenes' sieve.
|
88
161
|
# [+Prime+::+TrialDivisionGenerator+]
|
89
162
|
# Uses the trial division method.
|
90
163
|
# [+Prime+::+Generator23+]
|
@@ -96,7 +169,7 @@ end
|
|
96
169
|
|
97
170
|
class Prime
|
98
171
|
|
99
|
-
VERSION = "0.1.
|
172
|
+
VERSION = "0.1.3"
|
100
173
|
|
101
174
|
include Enumerable
|
102
175
|
include Singleton
|
@@ -141,8 +214,22 @@ class Prime
|
|
141
214
|
generator.each(&block)
|
142
215
|
end
|
143
216
|
|
217
|
+
# Returns true if +obj+ is an Integer and is prime. Also returns
|
218
|
+
# true if +obj+ is a Module that is an ancestor of +Prime+.
|
219
|
+
# Otherwise returns false.
|
220
|
+
def include?(obj)
|
221
|
+
case obj
|
222
|
+
when Integer
|
223
|
+
prime?(obj)
|
224
|
+
when Module
|
225
|
+
Module.instance_method(:include?).bind(Prime).call(obj)
|
226
|
+
else
|
227
|
+
false
|
228
|
+
end
|
229
|
+
end
|
144
230
|
|
145
231
|
# Returns true if +value+ is a prime number, else returns false.
|
232
|
+
# Integer#prime? is much more performant.
|
146
233
|
#
|
147
234
|
# == Parameters
|
148
235
|
#
|
@@ -161,17 +248,23 @@ class Prime
|
|
161
248
|
|
162
249
|
# Re-composes a prime factorization and returns the product.
|
163
250
|
#
|
251
|
+
# For the decomposition:
|
252
|
+
#
|
253
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]],
|
254
|
+
#
|
255
|
+
# it returns:
|
256
|
+
#
|
257
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n.
|
258
|
+
#
|
164
259
|
# == Parameters
|
165
|
-
# +pd+:: Array of pairs of integers.
|
166
|
-
# pair consists of a prime number -- a prime factor --
|
167
|
-
# and a natural number --
|
260
|
+
# +pd+:: Array of pairs of integers.
|
261
|
+
# Each pair consists of a prime number -- a prime factor --
|
262
|
+
# and a natural number -- its exponent (multiplicity).
|
168
263
|
#
|
169
264
|
# == Example
|
170
|
-
#
|
171
|
-
#
|
172
|
-
# p_1**e_1 * p_2**e_2 * .... * p_n**e_n.
|
265
|
+
# Prime.int_from_prime_division([[3, 2], [5, 1]]) #=> 45
|
266
|
+
# 3**2 * 5 #=> 45
|
173
267
|
#
|
174
|
-
# Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12
|
175
268
|
def int_from_prime_division(pd)
|
176
269
|
pd.inject(1){|value, (prime, index)|
|
177
270
|
value * prime**index
|
@@ -180,27 +273,32 @@ class Prime
|
|
180
273
|
|
181
274
|
# Returns the factorization of +value+.
|
182
275
|
#
|
276
|
+
# For an arbitrary integer:
|
277
|
+
#
|
278
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n,
|
279
|
+
#
|
280
|
+
# prime_division returns an array of pairs of integers:
|
281
|
+
#
|
282
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]].
|
283
|
+
#
|
284
|
+
# Each pair consists of a prime number -- a prime factor --
|
285
|
+
# and a natural number -- its exponent (multiplicity).
|
286
|
+
#
|
183
287
|
# == Parameters
|
184
288
|
# +value+:: An arbitrary integer.
|
185
289
|
# +generator+:: Optional. A pseudo-prime generator.
|
186
290
|
# +generator+.succ must return the next
|
187
|
-
# pseudo-prime number in
|
188
|
-
#
|
189
|
-
# but may also generate non
|
291
|
+
# pseudo-prime number in ascending order.
|
292
|
+
# It must generate all prime numbers,
|
293
|
+
# but may also generate non-prime numbers, too.
|
190
294
|
#
|
191
295
|
# === Exceptions
|
192
296
|
# +ZeroDivisionError+:: when +value+ is zero.
|
193
297
|
#
|
194
298
|
# == Example
|
195
|
-
# For an arbitrary integer:
|
196
|
-
#
|
197
|
-
# n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n,
|
198
|
-
#
|
199
|
-
# prime_division(n) returns:
|
200
|
-
#
|
201
|
-
# [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]].
|
202
299
|
#
|
203
|
-
# Prime.prime_division(
|
300
|
+
# Prime.prime_division(45) #=> [[3, 2], [5, 1]]
|
301
|
+
# 3**2 * 5 #=> 45
|
204
302
|
#
|
205
303
|
def prime_division(value, generator = Prime::Generator23.new)
|
206
304
|
raise ZeroDivisionError if value == 0
|
@@ -283,9 +381,9 @@ class Prime
|
|
283
381
|
end
|
284
382
|
|
285
383
|
# see +Enumerator+#with_index.
|
286
|
-
def with_index(offset = 0)
|
287
|
-
return enum_for(:with_index, offset) { Float::INFINITY } unless
|
288
|
-
return each_with_index(&
|
384
|
+
def with_index(offset = 0, &block)
|
385
|
+
return enum_for(:with_index, offset) { Float::INFINITY } unless block
|
386
|
+
return each_with_index(&block) if offset == 0
|
289
387
|
|
290
388
|
each do |prime|
|
291
389
|
yield prime, offset
|
data/prime.gemspec
CHANGED
@@ -8,20 +8,21 @@ end
|
|
8
8
|
Gem::Specification.new do |spec|
|
9
9
|
spec.name = "prime"
|
10
10
|
spec.version = Prime::VERSION
|
11
|
-
spec.authors = ["
|
12
|
-
spec.email = ["
|
11
|
+
spec.authors = ["Marc-Andre Lafortune"]
|
12
|
+
spec.email = ["ruby-core@marc-andre.ca"]
|
13
13
|
|
14
14
|
spec.summary = %q{Prime numbers and factorization library.}
|
15
15
|
spec.description = %q{Prime numbers and factorization library.}
|
16
16
|
spec.homepage = "https://github.com/ruby/prime"
|
17
|
-
spec.
|
17
|
+
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
18
18
|
|
19
|
-
spec.files = ["
|
19
|
+
spec.files = ["BSDL", "COPYING", "README.md", "Rakefile", "lib/prime.rb", "prime.gemspec", "sig/integer-extension.rbs", "sig/manifest.yaml", "sig/prime.rbs"]
|
20
20
|
spec.bindir = "exe"
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.
|
25
|
-
|
26
|
-
spec.
|
24
|
+
spec.required_ruby_version = ">= 2.5.0"
|
25
|
+
|
26
|
+
spec.add_dependency "singleton"
|
27
|
+
spec.add_dependency "forwardable"
|
27
28
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
%a{annotate:rdoc:skip}
|
2
|
+
class Integer
|
3
|
+
# <!--
|
4
|
+
# rdoc-file=lib/prime.rb
|
5
|
+
# - each_prime(ubound) { |prime| ... }
|
6
|
+
# -->
|
7
|
+
# Iterates the given block over all prime numbers.
|
8
|
+
#
|
9
|
+
# See `Prime`#each for more details.
|
10
|
+
#
|
11
|
+
def self.each_prime: (Integer) { (Integer) -> void } -> void
|
12
|
+
|
13
|
+
# <!--
|
14
|
+
# rdoc-file=lib/prime.rb
|
15
|
+
# - from_prime_division(pd)
|
16
|
+
# -->
|
17
|
+
# Re-composes a prime factorization and returns the product.
|
18
|
+
#
|
19
|
+
# See Prime#int_from_prime_division for more details.
|
20
|
+
#
|
21
|
+
def self.from_prime_division: (Array[[ String ]]) -> Integer
|
22
|
+
|
23
|
+
# <!--
|
24
|
+
# rdoc-file=lib/prime.rb
|
25
|
+
# - prime_division(generator = Prime::Generator23.new)
|
26
|
+
# -->
|
27
|
+
# Returns the factorization of `self`.
|
28
|
+
#
|
29
|
+
# See Prime#prime_division for more details.
|
30
|
+
#
|
31
|
+
def prime_division: (?Prime::PseudoPrimeGenerator) -> Array[[ Integer, Integer ]]
|
32
|
+
|
33
|
+
# <!--
|
34
|
+
# rdoc-file=lib/prime.rb
|
35
|
+
# - prime?()
|
36
|
+
# -->
|
37
|
+
# Returns true if `self` is a prime number, else returns false. Not recommended
|
38
|
+
# for very big integers (> 10**23).
|
39
|
+
#
|
40
|
+
def prime?: () -> bool
|
41
|
+
end
|
data/sig/manifest.yaml
ADDED
data/sig/prime.rbs
ADDED
@@ -0,0 +1,372 @@
|
|
1
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
2
|
+
# The set of all prime numbers.
|
3
|
+
#
|
4
|
+
# ## Example
|
5
|
+
#
|
6
|
+
# Prime.each(100) do |prime|
|
7
|
+
# p prime #=> 2, 3, 5, 7, 11, ...., 97
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# Prime is Enumerable:
|
11
|
+
#
|
12
|
+
# Prime.first 5 # => [2, 3, 5, 7, 11]
|
13
|
+
#
|
14
|
+
# ## Retrieving the instance
|
15
|
+
#
|
16
|
+
# For convenience, each instance method of `Prime`.instance can be accessed as a
|
17
|
+
# class method of `Prime`.
|
18
|
+
#
|
19
|
+
# e.g.
|
20
|
+
# Prime.instance.prime?(2) #=> true
|
21
|
+
# Prime.prime?(2) #=> true
|
22
|
+
#
|
23
|
+
# ## Generators
|
24
|
+
#
|
25
|
+
# A "generator" provides an implementation of enumerating pseudo-prime numbers
|
26
|
+
# and it remembers the position of enumeration and upper bound. Furthermore, it
|
27
|
+
# is an external iterator of prime enumeration which is compatible with an
|
28
|
+
# Enumerator.
|
29
|
+
#
|
30
|
+
# `Prime`::`PseudoPrimeGenerator` is the base class for generators. There are
|
31
|
+
# few implementations of generator.
|
32
|
+
#
|
33
|
+
# `Prime`::`EratosthenesGenerator`
|
34
|
+
# : Uses Eratosthenes' sieve.
|
35
|
+
# `Prime`::`TrialDivisionGenerator`
|
36
|
+
# : Uses the trial division method.
|
37
|
+
# `Prime`::`Generator23`
|
38
|
+
# : Generates all positive integers which are not divisible by either 2 or 3.
|
39
|
+
# This sequence is very bad as a pseudo-prime sequence. But this is faster
|
40
|
+
# and uses much less memory than the other generators. So, it is suitable
|
41
|
+
# for factorizing an integer which is not large but has many prime factors.
|
42
|
+
# e.g. for Prime#prime? .
|
43
|
+
#
|
44
|
+
class Prime
|
45
|
+
include Singleton
|
46
|
+
|
47
|
+
include Enumerable[Integer]
|
48
|
+
|
49
|
+
extend Enumerable[Integer]
|
50
|
+
|
51
|
+
# <!--
|
52
|
+
# rdoc-file=lib/prime.rb
|
53
|
+
# - each(ubound = nil, generator = EratosthenesGenerator.new, &block)
|
54
|
+
# -->
|
55
|
+
# Iterates the given block over all prime numbers.
|
56
|
+
#
|
57
|
+
# ## Parameters
|
58
|
+
#
|
59
|
+
# `ubound`
|
60
|
+
# : Optional. An arbitrary positive number. The upper bound of enumeration.
|
61
|
+
# The method enumerates prime numbers infinitely if `ubound` is nil.
|
62
|
+
# `generator`
|
63
|
+
# : Optional. An implementation of pseudo-prime generator.
|
64
|
+
#
|
65
|
+
#
|
66
|
+
# ## Return value
|
67
|
+
#
|
68
|
+
# An evaluated value of the given block at the last time. Or an enumerator which
|
69
|
+
# is compatible to an `Enumerator` if no block given.
|
70
|
+
#
|
71
|
+
# ## Description
|
72
|
+
#
|
73
|
+
# Calls `block` once for each prime number, passing the prime as a parameter.
|
74
|
+
#
|
75
|
+
# `ubound`
|
76
|
+
# : Upper bound of prime numbers. The iterator stops after it yields all prime
|
77
|
+
# numbers p <= `ubound`.
|
78
|
+
#
|
79
|
+
def self.each: (?Integer? ubound, ?PseudoPrimeGenerator generator) { (Integer) -> void } -> void
|
80
|
+
| (?Integer? ubound, ?PseudoPrimeGenerator generator) -> PseudoPrimeGenerator
|
81
|
+
|
82
|
+
# <!--
|
83
|
+
# rdoc-file=lib/prime.rb
|
84
|
+
# - each(ubound = nil, generator = EratosthenesGenerator.new, &block)
|
85
|
+
# -->
|
86
|
+
# Iterates the given block over all prime numbers.
|
87
|
+
#
|
88
|
+
# ## Parameters
|
89
|
+
#
|
90
|
+
# `ubound`
|
91
|
+
# : Optional. An arbitrary positive number. The upper bound of enumeration.
|
92
|
+
# The method enumerates prime numbers infinitely if `ubound` is nil.
|
93
|
+
# `generator`
|
94
|
+
# : Optional. An implementation of pseudo-prime generator.
|
95
|
+
#
|
96
|
+
#
|
97
|
+
# ## Return value
|
98
|
+
#
|
99
|
+
# An evaluated value of the given block at the last time. Or an enumerator which
|
100
|
+
# is compatible to an `Enumerator` if no block given.
|
101
|
+
#
|
102
|
+
# ## Description
|
103
|
+
#
|
104
|
+
# Calls `block` once for each prime number, passing the prime as a parameter.
|
105
|
+
#
|
106
|
+
# `ubound`
|
107
|
+
# : Upper bound of prime numbers. The iterator stops after it yields all prime
|
108
|
+
# numbers p <= `ubound`.
|
109
|
+
#
|
110
|
+
def each: (?Integer? ubound, ?PseudoPrimeGenerator generator) { (Integer) -> void } -> void
|
111
|
+
| (?Integer? ubound, ?PseudoPrimeGenerator generator) -> PseudoPrimeGenerator
|
112
|
+
|
113
|
+
# <!--
|
114
|
+
# rdoc-file=lib/prime.rb
|
115
|
+
# - int_from_prime_division(pd)
|
116
|
+
# -->
|
117
|
+
# Re-composes a prime factorization and returns the product.
|
118
|
+
#
|
119
|
+
# For the decomposition:
|
120
|
+
#
|
121
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]],
|
122
|
+
#
|
123
|
+
# it returns:
|
124
|
+
#
|
125
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n.
|
126
|
+
#
|
127
|
+
# ## Parameters
|
128
|
+
# `pd`
|
129
|
+
# : Array of pairs of integers. Each pair consists of a prime number -- a
|
130
|
+
# prime factor -- and a natural number -- its exponent (multiplicity).
|
131
|
+
#
|
132
|
+
#
|
133
|
+
# ## Example
|
134
|
+
# Prime.int_from_prime_division([[3, 2], [5, 1]]) #=> 45
|
135
|
+
# 3**2 * 5 #=> 45
|
136
|
+
#
|
137
|
+
def self.int_from_prime_division: (Array[[ Integer, Integer ]]) -> (Integer | Rational)
|
138
|
+
|
139
|
+
# <!--
|
140
|
+
# rdoc-file=lib/prime.rb
|
141
|
+
# - int_from_prime_division(pd)
|
142
|
+
# -->
|
143
|
+
# Re-composes a prime factorization and returns the product.
|
144
|
+
#
|
145
|
+
# For the decomposition:
|
146
|
+
#
|
147
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]],
|
148
|
+
#
|
149
|
+
# it returns:
|
150
|
+
#
|
151
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n.
|
152
|
+
#
|
153
|
+
# ## Parameters
|
154
|
+
# `pd`
|
155
|
+
# : Array of pairs of integers. Each pair consists of a prime number -- a
|
156
|
+
# prime factor -- and a natural number -- its exponent (multiplicity).
|
157
|
+
#
|
158
|
+
#
|
159
|
+
# ## Example
|
160
|
+
# Prime.int_from_prime_division([[3, 2], [5, 1]]) #=> 45
|
161
|
+
# 3**2 * 5 #=> 45
|
162
|
+
#
|
163
|
+
def int_from_prime_division: (Array[[ Integer, Integer ]]) -> (Integer | Rational)
|
164
|
+
|
165
|
+
# <!--
|
166
|
+
# rdoc-file=lib/prime.rb
|
167
|
+
# - prime?(value, generator = Prime::Generator23.new)
|
168
|
+
# -->
|
169
|
+
# Returns true if `value` is a prime number, else returns false. Integer#prime?
|
170
|
+
# is much more performant.
|
171
|
+
#
|
172
|
+
# ## Parameters
|
173
|
+
#
|
174
|
+
# `value`
|
175
|
+
# : an arbitrary integer to be checked.
|
176
|
+
# `generator`
|
177
|
+
# : optional. A pseudo-prime generator.
|
178
|
+
#
|
179
|
+
def self.prime?: (Integer value, ?PseudoPrimeGenerator generator) -> bool
|
180
|
+
|
181
|
+
# <!--
|
182
|
+
# rdoc-file=lib/prime.rb
|
183
|
+
# - prime?(value, generator = Prime::Generator23.new)
|
184
|
+
# -->
|
185
|
+
# Returns true if `value` is a prime number, else returns false. Integer#prime?
|
186
|
+
# is much more performant.
|
187
|
+
#
|
188
|
+
# ## Parameters
|
189
|
+
#
|
190
|
+
# `value`
|
191
|
+
# : an arbitrary integer to be checked.
|
192
|
+
# `generator`
|
193
|
+
# : optional. A pseudo-prime generator.
|
194
|
+
#
|
195
|
+
def prime?: (Integer value, ?PseudoPrimeGenerator generator) -> bool
|
196
|
+
|
197
|
+
# <!--
|
198
|
+
# rdoc-file=lib/prime.rb
|
199
|
+
# - prime_division(value, generator = Prime::Generator23.new)
|
200
|
+
# -->
|
201
|
+
# Returns the factorization of `value`.
|
202
|
+
#
|
203
|
+
# For an arbitrary integer:
|
204
|
+
#
|
205
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n,
|
206
|
+
#
|
207
|
+
# prime_division returns an array of pairs of integers:
|
208
|
+
#
|
209
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]].
|
210
|
+
#
|
211
|
+
# Each pair consists of a prime number -- a prime factor -- and a natural number
|
212
|
+
# -- its exponent (multiplicity).
|
213
|
+
#
|
214
|
+
# ## Parameters
|
215
|
+
# `value`
|
216
|
+
# : An arbitrary integer.
|
217
|
+
# `generator`
|
218
|
+
# : Optional. A pseudo-prime generator. `generator`.succ must return the next
|
219
|
+
# pseudo-prime number in ascending order. It must generate all prime
|
220
|
+
# numbers, but may also generate non-prime numbers, too.
|
221
|
+
#
|
222
|
+
#
|
223
|
+
# ### Exceptions
|
224
|
+
# `ZeroDivisionError`
|
225
|
+
# : when `value` is zero.
|
226
|
+
#
|
227
|
+
#
|
228
|
+
# ## Example
|
229
|
+
#
|
230
|
+
# Prime.prime_division(45) #=> [[3, 2], [5, 1]]
|
231
|
+
# 3**2 * 5 #=> 45
|
232
|
+
#
|
233
|
+
def self.prime_division: (Integer, ?PseudoPrimeGenerator generator) -> Array[[ Integer, Integer ]]
|
234
|
+
|
235
|
+
# <!--
|
236
|
+
# rdoc-file=lib/prime.rb
|
237
|
+
# - prime_division(value, generator = Prime::Generator23.new)
|
238
|
+
# -->
|
239
|
+
# Returns the factorization of `value`.
|
240
|
+
#
|
241
|
+
# For an arbitrary integer:
|
242
|
+
#
|
243
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n,
|
244
|
+
#
|
245
|
+
# prime_division returns an array of pairs of integers:
|
246
|
+
#
|
247
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]].
|
248
|
+
#
|
249
|
+
# Each pair consists of a prime number -- a prime factor -- and a natural number
|
250
|
+
# -- its exponent (multiplicity).
|
251
|
+
#
|
252
|
+
# ## Parameters
|
253
|
+
# `value`
|
254
|
+
# : An arbitrary integer.
|
255
|
+
# `generator`
|
256
|
+
# : Optional. A pseudo-prime generator. `generator`.succ must return the next
|
257
|
+
# pseudo-prime number in ascending order. It must generate all prime
|
258
|
+
# numbers, but may also generate non-prime numbers, too.
|
259
|
+
#
|
260
|
+
#
|
261
|
+
# ### Exceptions
|
262
|
+
# `ZeroDivisionError`
|
263
|
+
# : when `value` is zero.
|
264
|
+
#
|
265
|
+
#
|
266
|
+
# ## Example
|
267
|
+
#
|
268
|
+
# Prime.prime_division(45) #=> [[3, 2], [5, 1]]
|
269
|
+
# 3**2 * 5 #=> 45
|
270
|
+
#
|
271
|
+
def prime_division: (Integer, ?PseudoPrimeGenerator generator) -> Array[[ Integer, Integer ]]
|
272
|
+
|
273
|
+
# Returns the singleton instance.
|
274
|
+
#
|
275
|
+
def self.instance: () -> Prime
|
276
|
+
|
277
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
278
|
+
# An abstract class for enumerating pseudo-prime numbers.
|
279
|
+
#
|
280
|
+
# Concrete subclasses should override succ, next, rewind.
|
281
|
+
#
|
282
|
+
class PseudoPrimeGenerator
|
283
|
+
# <!--
|
284
|
+
# rdoc-file=lib/prime.rb
|
285
|
+
# - new(ubound = nil)
|
286
|
+
# -->
|
287
|
+
#
|
288
|
+
def initialize: (?Integer?) -> void
|
289
|
+
|
290
|
+
include Enumerable[Integer]
|
291
|
+
|
292
|
+
# <!--
|
293
|
+
# rdoc-file=lib/prime.rb
|
294
|
+
# - upper_bound()
|
295
|
+
# -->
|
296
|
+
# ----
|
297
|
+
# <!--
|
298
|
+
# rdoc-file=lib/prime.rb
|
299
|
+
# - upper_bound=(ubound)
|
300
|
+
# -->
|
301
|
+
#
|
302
|
+
attr_accessor upper_bound(): Integer?
|
303
|
+
|
304
|
+
# <!--
|
305
|
+
# rdoc-file=lib/prime.rb
|
306
|
+
# - each() { |prime| ... }
|
307
|
+
# -->
|
308
|
+
# Iterates the given block for each prime number.
|
309
|
+
#
|
310
|
+
def each: () { (Integer) -> void } -> void
|
311
|
+
|
312
|
+
# <!--
|
313
|
+
# rdoc-file=lib/prime.rb
|
314
|
+
# - next()
|
315
|
+
# -->
|
316
|
+
# alias of `succ`.
|
317
|
+
#
|
318
|
+
def next: () -> Integer
|
319
|
+
|
320
|
+
# <!--
|
321
|
+
# rdoc-file=lib/prime.rb
|
322
|
+
# - rewind()
|
323
|
+
# -->
|
324
|
+
# Rewinds the internal position for enumeration.
|
325
|
+
#
|
326
|
+
# See `Enumerator`#rewind.
|
327
|
+
#
|
328
|
+
def rewind: () -> void
|
329
|
+
|
330
|
+
# <!--
|
331
|
+
# rdoc-file=lib/prime.rb
|
332
|
+
# - size()
|
333
|
+
# -->
|
334
|
+
#
|
335
|
+
def size: () -> Float
|
336
|
+
|
337
|
+
# <!--
|
338
|
+
# rdoc-file=lib/prime.rb
|
339
|
+
# - succ()
|
340
|
+
# -->
|
341
|
+
# returns the next pseudo-prime number, and move the internal position forward.
|
342
|
+
#
|
343
|
+
# `PseudoPrimeGenerator`#succ raises `NotImplementedError`.
|
344
|
+
#
|
345
|
+
def succ: () -> Integer
|
346
|
+
end
|
347
|
+
|
348
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
349
|
+
# An implementation of `PseudoPrimeGenerator`.
|
350
|
+
#
|
351
|
+
# Uses `EratosthenesSieve`.
|
352
|
+
#
|
353
|
+
class EratosthenesGenerator < PseudoPrimeGenerator
|
354
|
+
end
|
355
|
+
|
356
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
357
|
+
# An implementation of `PseudoPrimeGenerator` which uses a prime table generated
|
358
|
+
# by trial division.
|
359
|
+
#
|
360
|
+
class TrialDivisionGenerator < PseudoPrimeGenerator
|
361
|
+
end
|
362
|
+
|
363
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
364
|
+
# Generates all integers which are greater than 2 and are not divisible by
|
365
|
+
# either 2 or 3.
|
366
|
+
#
|
367
|
+
# This is a pseudo-prime generator, suitable on checking primality of an integer
|
368
|
+
# by brute force method.
|
369
|
+
#
|
370
|
+
class Generator23 < PseudoPrimeGenerator
|
371
|
+
end
|
372
|
+
end
|
metadata
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Marc-Andre Lafortune
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: singleton
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
|
-
type: :
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
@@ -25,27 +25,13 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: forwardable
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
|
-
type: :
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: test-unit
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
34
|
+
type: :runtime
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
@@ -54,23 +40,23 @@ dependencies:
|
|
54
40
|
version: '0'
|
55
41
|
description: Prime numbers and factorization library.
|
56
42
|
email:
|
57
|
-
-
|
43
|
+
- ruby-core@marc-andre.ca
|
58
44
|
executables: []
|
59
45
|
extensions: []
|
60
46
|
extra_rdoc_files: []
|
61
47
|
files:
|
62
|
-
-
|
63
|
-
-
|
64
|
-
- Gemfile
|
65
|
-
- LICENSE.txt
|
48
|
+
- BSDL
|
49
|
+
- COPYING
|
66
50
|
- README.md
|
67
51
|
- Rakefile
|
68
|
-
- bin/console
|
69
|
-
- bin/setup
|
70
52
|
- lib/prime.rb
|
71
53
|
- prime.gemspec
|
54
|
+
- sig/integer-extension.rbs
|
55
|
+
- sig/manifest.yaml
|
56
|
+
- sig/prime.rbs
|
72
57
|
homepage: https://github.com/ruby/prime
|
73
58
|
licenses:
|
59
|
+
- Ruby
|
74
60
|
- BSD-2-Clause
|
75
61
|
metadata: {}
|
76
62
|
post_install_message:
|
@@ -81,14 +67,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
67
|
requirements:
|
82
68
|
- - ">="
|
83
69
|
- !ruby/object:Gem::Version
|
84
|
-
version:
|
70
|
+
version: 2.5.0
|
85
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - ">="
|
88
74
|
- !ruby/object:Gem::Version
|
89
75
|
version: '0'
|
90
76
|
requirements: []
|
91
|
-
rubygems_version: 3.
|
77
|
+
rubygems_version: 3.5.11
|
92
78
|
signing_key:
|
93
79
|
specification_version: 4
|
94
80
|
summary: Prime numbers and factorization library.
|
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "prime"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|