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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69c11faf9d0618a701ec125b9e6f4166770ade54b7868896535b75ef549c7beb
4
- data.tar.gz: f86764a32b94750b27444875ec6282cdfb2398de1bf55f643eb26c225b5a532d
3
+ metadata.gz: 145fdb7bf35cfc518b2ab469df94b560ee67199edccaef17caf2b20cc5adfd0f
4
+ data.tar.gz: c266767b310ed54143941a36449e0bb013d8b23a585dedc73662708056ba300e
5
5
  SHA512:
6
- metadata.gz: f5aa14e41c4c80c3c95828b2d7f019f220e1ba2ad461ab638ab32af7e98296e233ef390b90c13847e78b639e24fc47df8052e8f7c10c72181de743b3f78342e5
7
- data.tar.gz: 74d959b3a3d2ddb296dbf116cc8bed6314ca43fcedd98a7667ed520d3efa1340077b567a197ce0e164e21b2c7be43be28fb718ed80660d903b86d795a75c0bfb
6
+ metadata.gz: e8fa1c530cea6fa87d14911a9e5e98ca323ab81e680e8132a822b1ca9c1195469995948e9245dba45668864b4b08797a3f9bac713b8999b0e4a7a5ac9b772603
7
+ data.tar.gz: 0b7c4426d5f509d411fe8658f05811b6b1f7ce8b2d49125ef7f702725708ac4bc52b7a92c39e45633bab1d37adeb0e4f38bde72cb48d399682d9e50d430b065b
@@ -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
+ [![CI](https://github.com/ruby/prime/actions/workflows/test.yml/badge.svg)](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(779) #=> [[19, 1], [41, 1]]
37
- Prime.int_from_prime_division([[19, 1], [41, 1]]) #=> 779
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
@@ -2,8 +2,8 @@ require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
5
+ t.libs << "test/lib"
6
+ t.ruby_opts << "-rhelper"
7
7
  t.test_files = FileList["test/**/test_*.rb"]
8
8
  end
9
9
 
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 eratosthenes' sieve.
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.0"
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. The each internal
166
- # pair consists of a prime number -- a prime factor --
167
- # and a natural number -- an exponent.
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
- # For <tt>[[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]]</tt>, it returns:
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 the ascending
188
- # order. It must generate all prime numbers,
189
- # but may also generate non prime numbers too.
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(12) #=> [[2,2], [3,1]]
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 block_given?
288
- return each_with_index(&proc) if offset == 0
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 = ["Yuki Sonoda"]
12
- spec.email = ["yugui@yugui.jp"]
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.license = "BSD-2-Clause"
17
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
18
18
 
19
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/prime.rb", "prime.gemspec"]
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.add_development_dependency "bundler"
25
- spec.add_development_dependency "rake"
26
- spec.add_development_dependency "test-unit"
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
@@ -0,0 +1,2 @@
1
+ dependencies:
2
+ - name: singleton
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.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
- - Yuki Sonoda
7
+ - Marc-Andre Lafortune
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-01 00:00:00.000000000 Z
11
+ date: 2024-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
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: :development
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: rake
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: :development
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
- - yugui@yugui.jp
43
+ - ruby-core@marc-andre.ca
58
44
  executables: []
59
45
  extensions: []
60
46
  extra_rdoc_files: []
61
47
  files:
62
- - ".gitignore"
63
- - ".travis.yml"
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: '0'
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.2.0.pre1
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
@@ -1,9 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- Gemfile.lock
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.1
5
- - ruby-head
6
- before_install: gem install bundler -v 1.16.2
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in prime.gemspec
6
- gemspec
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__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here