rubysl-prime 2.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fd3a6866a24b3b275738de634a876ffa2fb3642e
4
+ data.tar.gz: a196c1f0d9552ad62c724e70088e884fba6cb3fb
5
+ SHA512:
6
+ metadata.gz: faecbed84cb564c60fd85586d241b9b5f120790414da934d3681e621e55442659ae3fca22fde5ac748fbf7e0a3576958fa2a3de3c52d41673a316600b23666a7
7
+ data.tar.gz: a4b28519f03e56553392650f36a011c71233920bcef7974a4694056ded1a8a15031ea0302b8c5fb78f625b76778ad2637343c0c05b1aa141b9e993d2ca979291
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ env:
3
+ - RUBYLIB=lib
4
+ script: bundle exec mspec
5
+ rvm:
6
+ - 1.9.3
7
+ - rbx-nightly-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rubysl-prime.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2013, Brian Shirai
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ 3. Neither the name of the library nor the names of its contributors may be
13
+ used to endorse or promote products derived from this software without
14
+ specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
20
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Rubysl::Prime
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rubysl-prime'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rubysl-prime
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/prime.rb ADDED
@@ -0,0 +1 @@
1
+ require "rubysl/prime"
@@ -0,0 +1,2 @@
1
+ require "rubysl/prime/prime"
2
+ require "rubysl/prime/version"
@@ -0,0 +1,509 @@
1
+ #
2
+ # = prime.rb
3
+ #
4
+ # Prime numbers and factorization library.
5
+ #
6
+ # Copyright::
7
+ # Copyright (c) 1998-2008 Keiju ISHITSUKA(SHL Japan Inc.)
8
+ # Copyright (c) 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
9
+ #
10
+ # Documentation::
11
+ # Yuki Sonoda
12
+ #
13
+
14
+ require "singleton"
15
+ require "forwardable"
16
+
17
+ class Integer
18
+ # Re-composes a prime factorization and returns the product.
19
+ #
20
+ # See Prime#int_from_prime_division for more details.
21
+ def Integer.from_prime_division(pd)
22
+ Prime.int_from_prime_division(pd)
23
+ end
24
+
25
+ # Returns the factorization of +self+.
26
+ #
27
+ # See Prime#prime_division for more details.
28
+ def prime_division(generator = Prime::Generator23.new)
29
+ Prime.prime_division(self, generator)
30
+ end
31
+
32
+ # Returns true if +self+ is a prime number, false for a composite.
33
+ def prime?
34
+ Prime.prime?(self)
35
+ end
36
+
37
+ # Iterates the given block over all prime numbers.
38
+ #
39
+ # See +Prime+#each for more details.
40
+ def Integer.each_prime(ubound, &block) # :yields: prime
41
+ Prime.each(ubound, &block)
42
+ end
43
+ end
44
+
45
+ #
46
+ # The set of all prime numbers.
47
+ #
48
+ # == Example
49
+ #
50
+ # Prime.each(100) do |prime|
51
+ # p prime #=> 2, 3, 5, 7, 11, ...., 97
52
+ # end
53
+ #
54
+ # Prime is Enumerable:
55
+ #
56
+ # Prime.first 5 # => [2, 3, 5, 7, 11]
57
+ #
58
+ # == Retrieving the instance
59
+ #
60
+ # +Prime+.new is obsolete. Now +Prime+ has the default instance and you can
61
+ # access it as +Prime+.instance.
62
+ #
63
+ # For convenience, each instance method of +Prime+.instance can be accessed
64
+ # as a class method of +Prime+.
65
+ #
66
+ # e.g.
67
+ # Prime.instance.prime?(2) #=> true
68
+ # Prime.prime?(2) #=> true
69
+ #
70
+ # == Generators
71
+ #
72
+ # A "generator" provides an implementation of enumerating pseudo-prime
73
+ # numbers and it remembers the position of enumeration and upper bound.
74
+ # Furthermore, it is a external iterator of prime enumeration which is
75
+ # compatible to an Enumerator.
76
+ #
77
+ # +Prime+::+PseudoPrimeGenerator+ is the base class for generators.
78
+ # There are few implementations of generator.
79
+ #
80
+ # [+Prime+::+EratosthenesGenerator+]
81
+ # Uses eratosthenes's sieve.
82
+ # [+Prime+::+TrialDivisionGenerator+]
83
+ # Uses the trial division method.
84
+ # [+Prime+::+Generator23+]
85
+ # Generates all positive integers which is not divided by 2 nor 3.
86
+ # This sequence is very bad as a pseudo-prime sequence. But this
87
+ # is faster and uses much less memory than other generators. So,
88
+ # it is suitable for factorizing an integer which is not large but
89
+ # has many prime factors. e.g. for Prime#prime? .
90
+
91
+ class Prime
92
+ include Enumerable
93
+ @the_instance = Prime.new
94
+
95
+ # obsolete. Use +Prime+::+instance+ or class methods of +Prime+.
96
+ def initialize
97
+ @generator = EratosthenesGenerator.new
98
+ extend OldCompatibility
99
+ warn "Prime::new is obsolete. use Prime::instance or class methods of Prime."
100
+ end
101
+
102
+ class << self
103
+ extend Forwardable
104
+ include Enumerable
105
+ # Returns the default instance of Prime.
106
+ def instance; @the_instance end
107
+
108
+ def method_added(method) # :nodoc:
109
+ (class<< self;self;end).def_delegator :instance, method
110
+ end
111
+ end
112
+
113
+ # Iterates the given block over all prime numbers.
114
+ #
115
+ # == Parameters
116
+ #
117
+ # +ubound+::
118
+ # Optional. An arbitrary positive number.
119
+ # The upper bound of enumeration. The method enumerates
120
+ # prime numbers infinitely if +ubound+ is nil.
121
+ # +generator+::
122
+ # Optional. An implementation of pseudo-prime generator.
123
+ #
124
+ # == Return value
125
+ #
126
+ # An evaluated value of the given block at the last time.
127
+ # Or an enumerator which is compatible to an +Enumerator+
128
+ # if no block given.
129
+ #
130
+ # == Description
131
+ #
132
+ # Calls +block+ once for each prime number, passing the prime as
133
+ # a parameter.
134
+ #
135
+ # +ubound+::
136
+ # Upper bound of prime numbers. The iterator stops after
137
+ # yields all prime numbers p <= +ubound+.
138
+ #
139
+ # == Note
140
+ #
141
+ # +Prime+.+new+ returns a object extended by +Prime+::+OldCompatibility+
142
+ # in order to compatibility to Ruby 1.8, and +Prime+#each is overwritten
143
+ # by +Prime+::+OldCompatibility+#+each+.
144
+ #
145
+ # +Prime+.+new+ is now obsolete. Use +Prime+.+instance+.+each+ or simply
146
+ # +Prime+.+each+.
147
+ def each(ubound = nil, generator = EratosthenesGenerator.new, &block)
148
+ generator.upper_bound = ubound
149
+ generator.each(&block)
150
+ end
151
+
152
+
153
+ # Returns true if +value+ is prime, false for a composite.
154
+ #
155
+ # == Parameters
156
+ #
157
+ # +value+:: an arbitrary integer to be checked.
158
+ # +generator+:: optional. A pseudo-prime generator.
159
+ def prime?(value, generator = Prime::Generator23.new)
160
+ value = -value if value < 0
161
+ return false if value < 2
162
+ for num in generator
163
+ q,r = value.divmod num
164
+ return true if q < num
165
+ return false if r == 0
166
+ end
167
+ end
168
+
169
+ # Re-composes a prime factorization and returns the product.
170
+ #
171
+ # == Parameters
172
+ # +pd+:: Array of pairs of integers. The each internal
173
+ # pair consists of a prime number -- a prime factor --
174
+ # and a natural number -- an exponent.
175
+ #
176
+ # == Example
177
+ # For <tt>[[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]]</tt>, it returns:
178
+ #
179
+ # p_1**e_1 * p_2**e_2 * .... * p_n**e_n.
180
+ #
181
+ # Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12
182
+ def int_from_prime_division(pd)
183
+ pd.inject(1){|value, (prime, index)|
184
+ value *= prime**index
185
+ }
186
+ end
187
+
188
+ # Returns the factorization of +value+.
189
+ #
190
+ # == Parameters
191
+ # +value+:: An arbitrary integer.
192
+ # +generator+:: Optional. A pseudo-prime generator.
193
+ # +generator+.succ must return the next
194
+ # pseudo-prime number in the ascendent
195
+ # order. It must generate all prime numbers,
196
+ # but may generate non prime numbers.
197
+ #
198
+ # === Exceptions
199
+ # +ZeroDivisionError+:: when +value+ is zero.
200
+ #
201
+ # == Example
202
+ # For an arbitrary integer:
203
+ #
204
+ # n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n,
205
+ #
206
+ # prime_division(n) returns:
207
+ #
208
+ # [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]].
209
+ #
210
+ # Prime.prime_division(12) #=> [[2,2], [3,1]]
211
+ #
212
+ def prime_division(value, generator= Prime::Generator23.new)
213
+ raise ZeroDivisionError if value == 0
214
+ if value < 0
215
+ value = -value
216
+ pv = [[-1, 1]]
217
+ else
218
+ pv = []
219
+ end
220
+ for prime in generator
221
+ count = 0
222
+ while (value1, mod = value.divmod(prime)
223
+ mod) == 0
224
+ value = value1
225
+ count += 1
226
+ end
227
+ if count != 0
228
+ pv.push [prime, count]
229
+ end
230
+ break if value1 <= prime
231
+ end
232
+ if value > 1
233
+ pv.push [value, 1]
234
+ end
235
+ return pv
236
+ end
237
+
238
+ # An abstract class for enumerating pseudo-prime numbers.
239
+ #
240
+ # Concrete subclasses should override succ, next, rewind.
241
+ class PseudoPrimeGenerator
242
+ include Enumerable
243
+
244
+ def initialize(ubound = nil)
245
+ @ubound = ubound
246
+ end
247
+
248
+ def upper_bound=(ubound)
249
+ @ubound = ubound
250
+ end
251
+ def upper_bound
252
+ @ubound
253
+ end
254
+
255
+ # returns the next pseudo-prime number, and move the internal
256
+ # position forward.
257
+ #
258
+ # +PseudoPrimeGenerator+#succ raises +NotImplementedError+.
259
+ def succ
260
+ raise NotImplementedError, "need to define `succ'"
261
+ end
262
+
263
+ # alias of +succ+.
264
+ def next
265
+ raise NotImplementedError, "need to define `next'"
266
+ end
267
+
268
+ # Rewinds the internal position for enumeration.
269
+ #
270
+ # See +Enumerator+#rewind.
271
+ def rewind
272
+ raise NotImplementedError, "need to define `rewind'"
273
+ end
274
+
275
+ # Iterates the given block for each prime numbers.
276
+ def each(&block)
277
+ return self.dup unless block
278
+ if @ubound
279
+ last_value = nil
280
+ loop do
281
+ prime = succ
282
+ break last_value if prime > @ubound
283
+ last_value = block.call(prime)
284
+ end
285
+ else
286
+ loop do
287
+ block.call(succ)
288
+ end
289
+ end
290
+ end
291
+
292
+ # see +Enumerator+#with_index.
293
+ alias with_index each_with_index
294
+
295
+ # see +Enumerator+#with_object.
296
+ def with_object(obj)
297
+ return enum_for(:with_object) unless block_given?
298
+ each do |prime|
299
+ yield prime, obj
300
+ end
301
+ end
302
+ end
303
+
304
+ # An implementation of +PseudoPrimeGenerator+.
305
+ #
306
+ # Uses +EratosthenesSieve+.
307
+ class EratosthenesGenerator < PseudoPrimeGenerator
308
+ def initialize
309
+ @last_prime = nil
310
+ super
311
+ end
312
+
313
+ def succ
314
+ @last_prime = @last_prime ? EratosthenesSieve.instance.next_to(@last_prime) : 2
315
+ end
316
+ def rewind
317
+ initialize
318
+ end
319
+ alias next succ
320
+ end
321
+
322
+ # An implementation of +PseudoPrimeGenerator+ which uses
323
+ # a prime table generated by trial division.
324
+ class TrialDivisionGenerator<PseudoPrimeGenerator
325
+ def initialize
326
+ @index = -1
327
+ super
328
+ end
329
+
330
+ def succ
331
+ TrialDivision.instance[@index += 1]
332
+ end
333
+ def rewind
334
+ initialize
335
+ end
336
+ alias next succ
337
+ end
338
+
339
+ # Generates all integer which are greater than 2 and
340
+ # are not divided by 2 nor 3.
341
+ #
342
+ # This is a pseudo-prime generator, suitable on
343
+ # checking primality of a integer by brute force
344
+ # method.
345
+ class Generator23<PseudoPrimeGenerator
346
+ def initialize
347
+ @prime = 1
348
+ @step = nil
349
+ super
350
+ end
351
+
352
+ def succ
353
+ loop do
354
+ if (@step)
355
+ @prime += @step
356
+ @step = 6 - @step
357
+ else
358
+ case @prime
359
+ when 1; @prime = 2
360
+ when 2; @prime = 3
361
+ when 3; @prime = 5; @step = 2
362
+ end
363
+ end
364
+ return @prime
365
+ end
366
+ end
367
+ alias next succ
368
+ def rewind
369
+ initialize
370
+ end
371
+ end
372
+
373
+ # Internal use. An implementation of prime table by trial division method.
374
+ class TrialDivision
375
+ include Singleton
376
+
377
+ def initialize # :nodoc:
378
+ # These are included as class variables to cache them for later uses. If memory
379
+ # usage is a problem, they can be put in Prime#initialize as instance variables.
380
+
381
+ # There must be no primes between @primes[-1] and @next_to_check.
382
+ @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]
383
+ # @next_to_check % 6 must be 1.
384
+ @next_to_check = 103 # @primes[-1] - @primes[-1] % 6 + 7
385
+ @ulticheck_index = 3 # @primes.index(@primes.reverse.find {|n|
386
+ # n < Math.sqrt(@@next_to_check) })
387
+ @ulticheck_next_squared = 121 # @primes[@ulticheck_index + 1] ** 2
388
+ end
389
+
390
+ # Returns the cached prime numbers.
391
+ def cache
392
+ return @primes
393
+ end
394
+ alias primes cache
395
+ alias primes_so_far cache
396
+
397
+ # Returns the +index+th prime number.
398
+ #
399
+ # +index+ is a 0-based index.
400
+ def [](index)
401
+ while index >= @primes.length
402
+ # Only check for prime factors up to the square root of the potential primes,
403
+ # but without the performance hit of an actual square root calculation.
404
+ if @next_to_check + 4 > @ulticheck_next_squared
405
+ @ulticheck_index += 1
406
+ @ulticheck_next_squared = @primes.at(@ulticheck_index + 1) ** 2
407
+ end
408
+ # Only check numbers congruent to one and five, modulo six. All others
409
+
410
+ # are divisible by two or three. This also allows us to skip checking against
411
+ # two and three.
412
+ @primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil?
413
+ @next_to_check += 4
414
+ @primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil?
415
+ @next_to_check += 2
416
+ end
417
+ return @primes[index]
418
+ end
419
+ end
420
+
421
+ # Internal use. An implementation of eratosthenes's sieve
422
+ class EratosthenesSieve
423
+ include Singleton
424
+
425
+ BITS_PER_ENTRY = 16 # each entry is a set of 16-bits in a Fixnum
426
+ NUMS_PER_ENTRY = BITS_PER_ENTRY * 2 # twiced because even numbers are omitted
427
+ ENTRIES_PER_TABLE = 8
428
+ NUMS_PER_TABLE = NUMS_PER_ENTRY * ENTRIES_PER_TABLE
429
+ FILLED_ENTRY = (1 << NUMS_PER_ENTRY) - 1
430
+
431
+ def initialize # :nodoc:
432
+ # bitmap for odd prime numbers less than 256.
433
+ # For an arbitrary odd number n, @tables[i][j][k] is
434
+ # * 1 if n is prime,
435
+ # * 0 if n is composite,
436
+ # where i,j,k = indices(n)
437
+ @tables = [[0xcb6e, 0x64b4, 0x129a, 0x816d, 0x4c32, 0x864a, 0x820d, 0x2196].freeze]
438
+ end
439
+
440
+ # returns the least odd prime number which is greater than +n+.
441
+ def next_to(n)
442
+ n = (n-1).div(2)*2+3 # the next odd number to given n
443
+ table_index, integer_index, bit_index = indices(n)
444
+ loop do
445
+ extend_table until @tables.length > table_index
446
+ for j in integer_index...ENTRIES_PER_TABLE
447
+ if !@tables[table_index][j].zero?
448
+ for k in bit_index...BITS_PER_ENTRY
449
+ return NUMS_PER_TABLE*table_index + NUMS_PER_ENTRY*j + 2*k+1 if !@tables[table_index][j][k].zero?
450
+ end
451
+ end
452
+ bit_index = 0
453
+ end
454
+ table_index += 1; integer_index = 0
455
+ end
456
+ end
457
+
458
+ private
459
+ # for an odd number +n+, returns (i, j, k) such that @tables[i][j][k] represents primarity of the number
460
+ def indices(n)
461
+ # binary digits of n: |0|1|2|3|4|5|6|7|8|9|10|11|....
462
+ # indices: |-| k | j | i
463
+ # because of NUMS_PER_ENTRY, NUMS_PER_TABLE
464
+
465
+ k = (n & 0b00011111) >> 1
466
+ j = (n & 0b11100000) >> 5
467
+ i = n >> 8
468
+ return i, j, k
469
+ end
470
+
471
+ def extend_table
472
+ lbound = NUMS_PER_TABLE * @tables.length
473
+ ubound = lbound + NUMS_PER_TABLE
474
+ new_table = [FILLED_ENTRY] * ENTRIES_PER_TABLE # which represents primarity in lbound...ubound
475
+ (3..Integer(Math.sqrt(ubound))).step(2) do |p|
476
+ i, j, k = indices(p)
477
+ next if @tables[i][j][k].zero?
478
+
479
+ start = (lbound.div(p)+1)*p # least multiple of p which is >= lbound
480
+ start += p if start.even?
481
+ (start...ubound).step(2*p) do |n|
482
+ _, j, k = indices(n)
483
+ new_table[j] &= FILLED_ENTRY^(1<<k)
484
+ end
485
+ end
486
+ @tables << new_table.freeze
487
+ end
488
+ end
489
+
490
+ # Provides a +Prime+ object with compatibility to Ruby 1.8 when instantiated via +Prime+.+new+.
491
+ module OldCompatibility
492
+ # Returns the next prime number and forwards internal pointer.
493
+ def succ
494
+ @generator.succ
495
+ end
496
+ alias next succ
497
+
498
+ # Overwrites Prime#each.
499
+ #
500
+ # Iterates the given block over all prime numbers. Note that enumeration
501
+ # starts from the current position of internal pointer, not rewound.
502
+ def each(&block)
503
+ return @generator.dup unless block_given?
504
+ loop do
505
+ yield succ
506
+ end
507
+ end
508
+ end
509
+ end
@@ -0,0 +1,5 @@
1
+ module RubySL
2
+ module Prime
3
+ VERSION = "2.0.0"
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ require './lib/rubysl/prime/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "rubysl-prime"
6
+ spec.version = RubySL::Prime::VERSION
7
+ spec.authors = ["Brian Shirai"]
8
+ spec.email = ["brixen@gmail.com"]
9
+ spec.description = %q{Ruby standard library prime.}
10
+ spec.summary = %q{Ruby standard library prime.}
11
+ spec.homepage = "https://github.com/rubysl/rubysl-prime"
12
+ spec.license = "BSD"
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.3"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "mspec", "~> 1.5"
22
+ end
data/spec/each_spec.rb ADDED
@@ -0,0 +1,157 @@
1
+
2
+ # force reload for Prime::method_added and Prime::instance
3
+ Object.send(:remove_const, :Prime) if defined?(Prime)
4
+ load 'prime.rb'
5
+
6
+ describe :prime_each, :shared => true do
7
+ before :each do
8
+ ScratchPad.record []
9
+ end
10
+
11
+ it "yields ascending primes to the block" do
12
+ previous = 1
13
+ @object.each do |prime|
14
+ break if prime > 1000
15
+ ScratchPad << prime
16
+ prime.should > previous
17
+ previous = prime
18
+ end
19
+
20
+ all_prime = true
21
+ ScratchPad.recorded.all? do |prime|
22
+ all_prime &&= (2..Math.sqrt(prime)).all? { |d| prime % d != 0 }
23
+ end
24
+
25
+ all_prime.should be_true
26
+ end
27
+
28
+ it "returns the last evaluated expression in the passed block" do
29
+ @object.each { break :value }.should equal(:value)
30
+ end
31
+
32
+ describe "when not passed a block" do
33
+ before :each do
34
+ @prime_enum = @object.each
35
+ end
36
+
37
+ it "returns an object that is Enumerable" do
38
+ @prime_enum.each.should be_kind_of(Enumerable)
39
+ end
40
+
41
+ it "returns an object that responds to #with_index" do
42
+ @prime_enum.should respond_to(:with_index)
43
+ end
44
+
45
+ it "returns an object that responds to #with_object" do
46
+ @prime_enum.should respond_to(:with_object)
47
+ end
48
+
49
+ it "returns an object that responds to #next" do
50
+ @prime_enum.should respond_to(:next)
51
+ end
52
+
53
+ it "returns an object that responds to #rewind" do
54
+ @prime_enum.should respond_to(:rewind)
55
+ end
56
+
57
+ it "yields primes starting at 2 independent of prior enumerators" do
58
+ @prime_enum.next.should == 2
59
+ @prime_enum.next.should == 3
60
+
61
+ @object.each { |prime| break prime }.should == 2
62
+ end
63
+
64
+ it "returns an enumerator that yields previous primes when #rewind is called" do
65
+ @prime_enum.next.should == 2
66
+ @prime_enum.next.should == 3
67
+ @prime_enum.rewind
68
+ @prime_enum.next.should == 2
69
+ end
70
+
71
+ it "returns independent enumerators" do
72
+ enum = @object.each
73
+ enum.next.should == 2
74
+ enum.next.should == 3
75
+
76
+ @prime_enum.next.should == 2
77
+
78
+ enum.next.should == 5
79
+ end
80
+ end
81
+ end
82
+
83
+ describe :prime_each_with_arguments, :shared => true do
84
+ before :each do
85
+ ScratchPad.record []
86
+ end
87
+
88
+ it "yields ascending primes less than or equal to the argument" do
89
+ bound = 1000
90
+ previous = 1
91
+ @object.each(bound) do |prime|
92
+ ScratchPad << prime
93
+ prime.should > previous
94
+ previous = prime
95
+ end
96
+
97
+ ScratchPad.recorded.all? do |prime|
98
+ (2..Math.sqrt(prime)).all? { |d| prime % d != 0 }
99
+ end.should be_true
100
+
101
+ ScratchPad.recorded.all? { |prime| prime <= bound }.should be_true
102
+ end
103
+
104
+ it "returns nil when no prime is generated" do
105
+ @object.each(1) { :value }.should be_nil
106
+ end
107
+
108
+ it "yields primes starting at 2 independent of prior enumeration" do
109
+ @object.each(10) { |prime| prime }.should == 7
110
+ @object.each(10) { |prime| break prime }.should == 2
111
+ end
112
+
113
+ it "accepts a pseudo-prime generator as the second argument" do
114
+ generator = mock('very bad pseudo-prime generator')
115
+ generator.should_receive(:upper_bound=).with(100)
116
+ generator.should_receive(:each).and_yield(2).and_yield(3).and_yield(4)
117
+
118
+ @object.each(100, generator) { |prime| ScratchPad << prime }
119
+ ScratchPad.recorded.should == [2, 3, 4]
120
+ end
121
+
122
+ describe "when not passed a block" do
123
+ it "returns an object that returns primes less than or equal to the bound" do
124
+ bound = 100
125
+ @object.each(bound).all? { |prime| prime <= bound }.should be_true
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "Prime.each" do
131
+ it_behaves_like :prime_each, :each, Prime
132
+ end
133
+
134
+ describe "Prime.each" do
135
+ it_behaves_like :prime_each_with_arguments, :each, Prime
136
+ end
137
+
138
+ describe "Prime#each with Prime.instance" do
139
+ it_behaves_like :prime_each, :each, Prime.instance
140
+ end
141
+
142
+ describe "Prime#each with Prime.instance" do
143
+ it_behaves_like :prime_each_with_arguments, :each, Prime.instance
144
+ end
145
+
146
+ describe "Prime#each with Prime.new" do
147
+ before :each do
148
+ @object = Prime.new
149
+ end
150
+
151
+ it_behaves_like :prime_each, :each
152
+
153
+ it "does not rewind the enumerator with each call" do
154
+ @object.each { |prime| break if prime > 10 }
155
+ @object.each { |prime| break prime }.should == 13
156
+ end
157
+ end
@@ -0,0 +1,21 @@
1
+ require 'prime'
2
+
3
+ describe "Prime.instance" do
4
+ it "returns a object representing the set of prime numbers" do
5
+ Prime.instance.should be_kind_of(Prime)
6
+ end
7
+
8
+ it "returns a object with no obsolete features" do
9
+ Prime.instance.should_not be_kind_of(Prime::OldCompatibility)
10
+ Prime.instance.should_not respond_to(:succ)
11
+ Prime.instance.should_not respond_to(:next)
12
+ end
13
+
14
+ it "does not complain anything" do
15
+ lambda { Prime.instance }.should_not complain
16
+ end
17
+
18
+ it "raises a ArgumentError when is called with some arguments" do
19
+ lambda { Prime.instance(1) }.should raise_error(ArgumentError)
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ require 'prime'
2
+
3
+ describe "Prime.int_from_prime_division" do
4
+ it "returns the product of the given factorization" do
5
+ Prime.int_from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]).
6
+ should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3
7
+ end
8
+
9
+ it "returns 1 for an empty factorization" do
10
+ Prime.int_from_prime_division([]).should == 1
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'prime'
2
+
3
+ describe "Integer.each_prime" do
4
+ it "is transferred to Prime.each" do
5
+ Prime.should_receive(:each).with(100).and_yield(2).and_yield(3).and_yield(5)
6
+ yielded = []
7
+ Integer.each_prime(100) do |prime|
8
+ yielded << prime
9
+ end
10
+ yielded.should == [2,3,5]
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'prime'
2
+
3
+ describe "Integer.from_prime_division" do
4
+ it "returns the product of the given factorization" do
5
+ Integer.from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]).
6
+ should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3
7
+ end
8
+
9
+ it "returns 1 for an empty factorization" do
10
+ Integer.from_prime_division([]).should == 1
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ require 'prime'
2
+
3
+ describe "Integer#prime_division" do
4
+ it "returns an array of a prime factor and a corresponding exponent" do
5
+ (2*3*5*7*11*13*17).prime_division.should ==
6
+ [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]]
7
+ end
8
+
9
+ it "returns an empty array for 1" do
10
+ 1.prime_division.should == []
11
+ end
12
+ it "returns an empty array for -1" do
13
+ -1.prime_division.should == [[-1, 1]]
14
+ end
15
+ it "raises ZeroDivisionError for 0" do
16
+ lambda { 0.prime_division }.should raise_error(ZeroDivisionError)
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ require 'prime'
2
+
3
+ describe "Integer#prime?" do
4
+ it "returns a true value for prime numbers" do
5
+ 2.prime?.should be_true
6
+ 3.prime?.should be_true
7
+ (2**31-1).prime?.should be_true # 8th Mersenne prime (M8)
8
+ end
9
+
10
+ it "returns a false value for composite numbers" do
11
+ 4.prime?.should be_false
12
+ 15.prime?.should be_false
13
+ (2**32-1).prime?.should be_false
14
+ ( (2**17-1)*(2**19-1) ).prime?.should be_false # M6*M7
15
+ end
16
+ end
data/spec/new_spec.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'prime'
2
+
3
+ describe "Prime.new" do
4
+ it "returns a new object representing the set of prime numbers" do
5
+ Prime.new.should be_kind_of(Prime)
6
+ end
7
+
8
+ it "returns a object with obsolete featrues" do
9
+ Prime.new.should be_kind_of(Prime::OldCompatibility)
10
+ Prime.new.should respond_to(:succ)
11
+ Prime.new.should respond_to(:next)
12
+ end
13
+
14
+ it "complains that the method is obsolete" do
15
+ lambda { Prime.new }.should complain(/obsolete.*use.*Prime::instance/)
16
+ end
17
+
18
+ it "raises a ArgumentError when is called with some arguments" do
19
+ lambda { Prime.new(1) }.should raise_error(ArgumentError)
20
+ end
21
+ end
data/spec/next_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require File.expand_path('../shared/next', __FILE__)
2
+ require 'prime'
3
+
4
+ describe "Prime#next" do
5
+ it_behaves_like :prime_next, :next
6
+ end
7
+
8
+
@@ -0,0 +1,24 @@
1
+ require 'prime'
2
+
3
+ describe "Prime.prime_division" do
4
+ it "returns an array of a prime factor and a corresponding exponent" do
5
+ Prime.prime_division(2*3*5*7*11*13*17).should ==
6
+ [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]]
7
+ end
8
+
9
+ it "returns an empty array for 1" do
10
+ Prime.prime_division(1).should == []
11
+ end
12
+
13
+ it "returns [[-1, 1]] for -1" do
14
+ Prime.prime_division(-1).should == [[-1, 1]]
15
+ end
16
+
17
+ it "includes [[-1, 1]] in the divisors of a negative number" do
18
+ Prime.prime_division(-10).should include([-1, 1])
19
+ end
20
+
21
+ it "raises ZeroDivisionError for 0" do
22
+ lambda { Prime.prime_division(0) }.should raise_error(ZeroDivisionError)
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require 'prime'
2
+
3
+ describe "Prime#prime?" do
4
+ it "returns a true value for prime numbers" do
5
+ Prime.prime?(2).should be_true
6
+ Prime.prime?(3).should be_true
7
+ Prime.prime?(2**31-1).should be_true # 8th Mersenne prime (M8)
8
+ end
9
+
10
+ it "returns a false value for composite numbers" do
11
+ Prime.prime?(4).should be_false
12
+ Prime.prime?(15).should be_false
13
+ Prime.prime?(2**32-1).should be_false
14
+ Prime.prime?( (2**17-1)*(2**19-1) ).should be_false # M6*M7
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'stringio'
2
+
3
+ describe :prime_next, :shared => true do
4
+ before(:all) do
5
+ @orig_stderr = $stderr
6
+ $stderr = StringIO.new('', 'w') # suppress warning
7
+ end
8
+ after(:all) do
9
+ $stderr = @orig_stderr
10
+ end
11
+
12
+ it "returns the element at the current position and moves forward" do
13
+ p = Prime.new
14
+ p.next.should == 2
15
+ p.next.should == 3
16
+ p.next.next.should == 6
17
+ end
18
+ end
data/spec/succ_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require File.expand_path('../shared/next', __FILE__)
2
+ require 'prime'
3
+
4
+ describe "Prime#succ" do
5
+ it_behaves_like :prime_next, :succ
6
+ end
7
+
8
+
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubysl-prime
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Shirai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ description: Ruby standard library prime.
56
+ email:
57
+ - brixen@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .travis.yml
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - Rakefile
68
+ - lib/prime.rb
69
+ - lib/rubysl/prime.rb
70
+ - lib/rubysl/prime/prime.rb
71
+ - lib/rubysl/prime/version.rb
72
+ - rubysl-prime.gemspec
73
+ - spec/each_spec.rb
74
+ - spec/instance_spec.rb
75
+ - spec/int_from_prime_division_spec.rb
76
+ - spec/integer/each_prime_spec.rb
77
+ - spec/integer/from_prime_division_spec.rb
78
+ - spec/integer/prime_division_spec.rb
79
+ - spec/integer/prime_spec.rb
80
+ - spec/new_spec.rb
81
+ - spec/next_spec.rb
82
+ - spec/prime_division_spec.rb
83
+ - spec/prime_spec.rb
84
+ - spec/shared/next.rb
85
+ - spec/succ_spec.rb
86
+ homepage: https://github.com/rubysl/rubysl-prime
87
+ licenses:
88
+ - BSD
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.0.7
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Ruby standard library prime.
110
+ test_files:
111
+ - spec/each_spec.rb
112
+ - spec/instance_spec.rb
113
+ - spec/int_from_prime_division_spec.rb
114
+ - spec/integer/each_prime_spec.rb
115
+ - spec/integer/from_prime_division_spec.rb
116
+ - spec/integer/prime_division_spec.rb
117
+ - spec/integer/prime_spec.rb
118
+ - spec/new_spec.rb
119
+ - spec/next_spec.rb
120
+ - spec/prime_division_spec.rb
121
+ - spec/prime_spec.rb
122
+ - spec/shared/next.rb
123
+ - spec/succ_spec.rb