rubysl-prime 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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