summaryrefslogtreecommitdiff
path: root/spec/ruby/core/numeric
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/numeric')
-rw-r--r--spec/ruby/core/numeric/abs2_spec.rb34
-rw-r--r--spec/ruby/core/numeric/abs_spec.rb6
-rw-r--r--spec/ruby/core/numeric/angle_spec.rb6
-rw-r--r--spec/ruby/core/numeric/arg_spec.rb6
-rw-r--r--spec/ruby/core/numeric/ceil_spec.rb15
-rw-r--r--spec/ruby/core/numeric/clone_spec.rb30
-rw-r--r--spec/ruby/core/numeric/coerce_spec.rb59
-rw-r--r--spec/ruby/core/numeric/comparison_spec.rb48
-rw-r--r--spec/ruby/core/numeric/conj_spec.rb6
-rw-r--r--spec/ruby/core/numeric/conjugate_spec.rb6
-rw-r--r--spec/ruby/core/numeric/denominator_spec.rb24
-rw-r--r--spec/ruby/core/numeric/div_spec.rb22
-rw-r--r--spec/ruby/core/numeric/divmod_spec.rb15
-rw-r--r--spec/ruby/core/numeric/dup_spec.rb16
-rw-r--r--spec/ruby/core/numeric/eql_spec.rb22
-rw-r--r--spec/ruby/core/numeric/fdiv_spec.rb31
-rw-r--r--spec/ruby/core/numeric/finite_spec.rb8
-rw-r--r--spec/ruby/core/numeric/fixtures/classes.rb17
-rw-r--r--spec/ruby/core/numeric/floor_spec.rb14
-rw-r--r--spec/ruby/core/numeric/i_spec.rb15
-rw-r--r--spec/ruby/core/numeric/imag_spec.rb6
-rw-r--r--spec/ruby/core/numeric/imaginary_spec.rb6
-rw-r--r--spec/ruby/core/numeric/infinite_spec.rb8
-rw-r--r--spec/ruby/core/numeric/integer_spec.rb8
-rw-r--r--spec/ruby/core/numeric/magnitude_spec.rb6
-rw-r--r--spec/ruby/core/numeric/modulo_spec.rb24
-rw-r--r--spec/ruby/core/numeric/negative_spec.rb41
-rw-r--r--spec/ruby/core/numeric/nonzero_spec.rb18
-rw-r--r--spec/ruby/core/numeric/numerator_spec.rb33
-rw-r--r--spec/ruby/core/numeric/numeric_spec.rb7
-rw-r--r--spec/ruby/core/numeric/phase_spec.rb6
-rw-r--r--spec/ruby/core/numeric/polar_spec.rb50
-rw-r--r--spec/ruby/core/numeric/positive_spec.rb41
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb63
-rw-r--r--spec/ruby/core/numeric/real_spec.rb37
-rw-r--r--spec/ruby/core/numeric/rect_spec.rb6
-rw-r--r--spec/ruby/core/numeric/rectangular_spec.rb6
-rw-r--r--spec/ruby/core/numeric/remainder_spec.rb70
-rw-r--r--spec/ruby/core/numeric/round_spec.rb14
-rw-r--r--spec/ruby/core/numeric/shared/abs.rb19
-rw-r--r--spec/ruby/core/numeric/shared/arg.rb38
-rw-r--r--spec/ruby/core/numeric/shared/conj.rb20
-rw-r--r--spec/ruby/core/numeric/shared/imag.rb26
-rw-r--r--spec/ruby/core/numeric/shared/rect.rb48
-rw-r--r--spec/ruby/core/numeric/shared/step.rb410
-rw-r--r--spec/ruby/core/numeric/singleton_method_added_spec.rb41
-rw-r--r--spec/ruby/core/numeric/step_spec.rb121
-rw-r--r--spec/ruby/core/numeric/to_c_spec.rb45
-rw-r--r--spec/ruby/core/numeric/to_int_spec.rb10
-rw-r--r--spec/ruby/core/numeric/truncate_spec.rb14
-rw-r--r--spec/ruby/core/numeric/uminus_spec.rb31
-rw-r--r--spec/ruby/core/numeric/uplus_spec.rb9
-rw-r--r--spec/ruby/core/numeric/zero_spec.rb18
53 files changed, 1700 insertions, 0 deletions
diff --git a/spec/ruby/core/numeric/abs2_spec.rb b/spec/ruby/core/numeric/abs2_spec.rb
new file mode 100644
index 0000000000..0e60cd0ae7
--- /dev/null
+++ b/spec/ruby/core/numeric/abs2_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#abs2" do
+ before :each do
+ @numbers = [
+ 0,
+ 0.0,
+ 1,
+ 20,
+ bignum_value,
+ 278202.292871,
+ 72829,
+ 3.333333333333,
+ 0.1,
+ infinity_value
+ ].map { |n| [-n, n] }.flatten
+ end
+
+ it "returns the square of the absolute value of self" do
+ @numbers.each do |number|
+ number.abs2.should eql(number.abs ** 2)
+ end
+ end
+
+ it "calls #* on self" do
+ number = mock_numeric('numeric')
+ number.should_receive(:*).and_return(:result)
+ number.abs2.should == :result
+ end
+
+ it "returns NaN when self is NaN" do
+ nan_value.abs2.nan?.should be_true
+ end
+end
diff --git a/spec/ruby/core/numeric/abs_spec.rb b/spec/ruby/core/numeric/abs_spec.rb
new file mode 100644
index 0000000000..8bec50e337
--- /dev/null
+++ b/spec/ruby/core/numeric/abs_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/abs'
+
+describe "Numeric#abs" do
+ it_behaves_like :numeric_abs, :abs
+end
diff --git a/spec/ruby/core/numeric/angle_spec.rb b/spec/ruby/core/numeric/angle_spec.rb
new file mode 100644
index 0000000000..bb38165777
--- /dev/null
+++ b/spec/ruby/core/numeric/angle_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/arg'
+
+describe "Numeric#angle" do
+ it_behaves_like :numeric_arg, :angle
+end
diff --git a/spec/ruby/core/numeric/arg_spec.rb b/spec/ruby/core/numeric/arg_spec.rb
new file mode 100644
index 0000000000..ba3b57c687
--- /dev/null
+++ b/spec/ruby/core/numeric/arg_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/arg'
+
+describe "Numeric#arg" do
+ it_behaves_like :numeric_arg, :arg
+end
diff --git a/spec/ruby/core/numeric/ceil_spec.rb b/spec/ruby/core/numeric/ceil_spec.rb
new file mode 100644
index 0000000000..00c856e79b
--- /dev/null
+++ b/spec/ruby/core/numeric/ceil_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#ceil" do
+ it "converts self to a Float (using #to_f) and returns the #ceil'ed result" do
+ o = mock_numeric("ceil")
+ o.should_receive(:to_f).and_return(1 + TOLERANCE)
+ o.ceil.should == 2
+
+ o2 = mock_numeric("ceil")
+ v = -1 - TOLERANCE
+ o2.should_receive(:to_f).and_return(v)
+ o2.ceil.should == -1
+ end
+end
diff --git a/spec/ruby/core/numeric/clone_spec.rb b/spec/ruby/core/numeric/clone_spec.rb
new file mode 100644
index 0000000000..423cec85dd
--- /dev/null
+++ b/spec/ruby/core/numeric/clone_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#clone" do
+ it "returns self" do
+ value = 1
+ value.clone.should equal(value)
+
+ subclass = Class.new(Numeric)
+ value = subclass.new
+ value.clone.should equal(value)
+ end
+
+ it "does not change frozen status" do
+ 1.clone.frozen?.should == true
+ end
+
+ it "accepts optional keyword argument :freeze" do
+ value = 1
+ value.clone(freeze: true).should equal(value)
+ end
+
+ it "raises ArgumentError if passed freeze: false" do
+ -> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/)
+ end
+
+ it "does not change frozen status if passed freeze: nil" do
+ value = 1
+ value.clone(freeze: nil).should equal(value)
+ end
+end
diff --git a/spec/ruby/core/numeric/coerce_spec.rb b/spec/ruby/core/numeric/coerce_spec.rb
new file mode 100644
index 0000000000..4c4416d30b
--- /dev/null
+++ b/spec/ruby/core/numeric/coerce_spec.rb
@@ -0,0 +1,59 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#coerce" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ @obj.should_receive(:to_f).any_number_of_times.and_return(10.5)
+ end
+
+ it "returns [other, self] if self and other are instances of the same class" do
+ a = NumericSpecs::Subclass.new
+ b = NumericSpecs::Subclass.new
+
+ a.coerce(b).should == [b, a]
+ end
+
+ # I (emp) think that this behavior is actually a bug in MRI. It's here as documentation
+ # of the behavior until we find out if it's a bug.
+ quarantine! do
+ it "considers the presence of a metaclass when checking the class of the objects" do
+ a = NumericSpecs::Subclass.new
+ b = NumericSpecs::Subclass.new
+
+ # inject a metaclass on a
+ class << a; true; end
+
+ # watch it explode
+ -> { a.coerce(b) }.should raise_error(TypeError)
+ end
+ end
+
+ it "returns [other.to_f, self.to_f] if self and other are instances of different classes" do
+ @obj.coerce(2.5).should == [2.5, 10.5]
+ @obj.coerce(3).should == [3.0, 10.5]
+ @obj.coerce("4.4").should == [4.4, 10.5]
+ @obj.coerce(bignum_value).should == [bignum_value.to_f, 10.5]
+ end
+
+ it "raise TypeError if they are instances of different classes and other does not respond to #to_f" do
+ other = mock("numeric")
+ -> { @obj.coerce(other) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed nil" do
+ -> { @obj.coerce(nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a boolean" do
+ -> { @obj.coerce(false) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a Symbol" do
+ -> { @obj.coerce(:symbol) }.should raise_error(TypeError)
+ end
+
+ it "raises an ArgumentError when passed a non-numeric String" do
+ -> { @obj.coerce("test") }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/numeric/comparison_spec.rb b/spec/ruby/core/numeric/comparison_spec.rb
new file mode 100644
index 0000000000..4b4d52501a
--- /dev/null
+++ b/spec/ruby/core/numeric/comparison_spec.rb
@@ -0,0 +1,48 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#<=>" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns 0 if self equals other" do
+ (@obj <=> @obj).should == 0
+ end
+
+ it "returns nil if self does not equal other" do
+ (@obj <=> NumericSpecs::Subclass.new).should == nil
+ (@obj <=> 10).should == nil
+ (@obj <=> -3.5).should == nil
+ (@obj <=> bignum_value).should == nil
+ end
+
+ describe "with subclasses of Numeric" do
+ before :each do
+ @a = NumericSpecs::Comparison.new
+ @b = NumericSpecs::Comparison.new
+
+ ScratchPad.clear
+ end
+
+ it "is called when instances are compared with #<" do
+ (@a < @b).should be_false
+ ScratchPad.recorded.should == :numeric_comparison
+ end
+
+ it "is called when instances are compared with #<=" do
+ (@a <= @b).should be_false
+ ScratchPad.recorded.should == :numeric_comparison
+ end
+
+ it "is called when instances are compared with #>" do
+ (@a > @b).should be_true
+ ScratchPad.recorded.should == :numeric_comparison
+ end
+
+ it "is called when instances are compared with #>=" do
+ (@a >= @b).should be_true
+ ScratchPad.recorded.should == :numeric_comparison
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/conj_spec.rb b/spec/ruby/core/numeric/conj_spec.rb
new file mode 100644
index 0000000000..7d4777ca60
--- /dev/null
+++ b/spec/ruby/core/numeric/conj_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/conj'
+
+describe "Numeric#conj" do
+ it_behaves_like :numeric_conj, :conj
+end
diff --git a/spec/ruby/core/numeric/conjugate_spec.rb b/spec/ruby/core/numeric/conjugate_spec.rb
new file mode 100644
index 0000000000..99854766e7
--- /dev/null
+++ b/spec/ruby/core/numeric/conjugate_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/conj'
+
+describe "Numeric#conjugate" do
+ it_behaves_like :numeric_conj, :conjugate
+end
diff --git a/spec/ruby/core/numeric/denominator_spec.rb b/spec/ruby/core/numeric/denominator_spec.rb
new file mode 100644
index 0000000000..34729446a2
--- /dev/null
+++ b/spec/ruby/core/numeric/denominator_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#denominator" do
+ # The Numeric child classes override this method, so their behaviour is
+ # specified in the appropriate place
+ before :each do
+ @numbers = [
+ 20, # Integer
+ 99999999**99, # Bignum
+ ]
+ end
+
+ it "returns 1" do
+ @numbers.each {|number| number.denominator.should == 1}
+ end
+
+ it "works with Numeric subclasses" do
+ rational = mock_numeric('rational')
+ rational.should_receive(:denominator).and_return(:denominator)
+ numeric = mock_numeric('numeric')
+ numeric.should_receive(:to_r).and_return(rational)
+ numeric.denominator.should == :denominator
+ end
+end
diff --git a/spec/ruby/core/numeric/div_spec.rb b/spec/ruby/core/numeric/div_spec.rb
new file mode 100644
index 0000000000..53917b84c9
--- /dev/null
+++ b/spec/ruby/core/numeric/div_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#div" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "calls self#/ with other, then returns the #floor'ed result" do
+ result = mock("Numeric#div result")
+ result.should_receive(:floor).and_return(12)
+ @obj.should_receive(:/).with(10).and_return(result)
+
+ @obj.div(10).should == 12
+ end
+
+ it "raises ZeroDivisionError for 0" do
+ -> { @obj.div(0) }.should raise_error(ZeroDivisionError)
+ -> { @obj.div(0.0) }.should raise_error(ZeroDivisionError)
+ -> { @obj.div(Complex(0,0)) }.should raise_error(ZeroDivisionError)
+ end
+end
diff --git a/spec/ruby/core/numeric/divmod_spec.rb b/spec/ruby/core/numeric/divmod_spec.rb
new file mode 100644
index 0000000000..8d5259bbcd
--- /dev/null
+++ b/spec/ruby/core/numeric/divmod_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#divmod" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns [quotient, modulus], with quotient being obtained as in Numeric#div then #floor and modulus being obtained by calling self#- with quotient * other" do
+ @obj.should_receive(:/).twice.with(10).and_return(13 - TOLERANCE, 13 - TOLERANCE)
+ @obj.should_receive(:-).with(120).and_return(3)
+
+ @obj.divmod(10).should == [12, 3]
+ end
+end
diff --git a/spec/ruby/core/numeric/dup_spec.rb b/spec/ruby/core/numeric/dup_spec.rb
new file mode 100644
index 0000000000..189a7ef44d
--- /dev/null
+++ b/spec/ruby/core/numeric/dup_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#dup" do
+ it "returns self" do
+ value = 1
+ value.dup.should equal(value)
+
+ subclass = Class.new(Numeric)
+ value = subclass.new
+ value.dup.should equal(value)
+ end
+
+ it "does not change frozen status" do
+ 1.dup.frozen?.should == true
+ end
+end
diff --git a/spec/ruby/core/numeric/eql_spec.rb b/spec/ruby/core/numeric/eql_spec.rb
new file mode 100644
index 0000000000..b33e00e51f
--- /dev/null
+++ b/spec/ruby/core/numeric/eql_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#eql?" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns false if self's and other's types don't match" do
+ @obj.should_not eql(1)
+ @obj.should_not eql(-1.5)
+ @obj.should_not eql(bignum_value)
+ @obj.should_not eql(:sym)
+ end
+
+ it "returns the result of calling self#== with other when self's and other's types match" do
+ other = NumericSpecs::Subclass.new
+ @obj.should_receive(:==).with(other).and_return("result", nil)
+ @obj.should eql(other)
+ @obj.should_not eql(other)
+ end
+end
diff --git a/spec/ruby/core/numeric/fdiv_spec.rb b/spec/ruby/core/numeric/fdiv_spec.rb
new file mode 100644
index 0000000000..e97fa77f79
--- /dev/null
+++ b/spec/ruby/core/numeric/fdiv_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#fdiv" do
+ it "coerces self with #to_f" do
+ numeric = mock_numeric('numeric')
+ numeric.should_receive(:to_f).and_return(3.0)
+ numeric.fdiv(0.5).should == 6.0
+ end
+
+ it "coerces other with #to_f" do
+ numeric = mock_numeric('numeric')
+ numeric.should_receive(:to_f).and_return(3.0)
+ 6.fdiv(numeric).should == 2.0
+ end
+
+ it "performs floating-point division" do
+ 3.fdiv(2).should == 1.5
+ end
+
+ it "returns a Float" do
+ bignum_value.fdiv(Float::MAX).should be_an_instance_of(Float)
+ end
+
+ it "returns Infinity if other is 0" do
+ 8121.92821.fdiv(0).infinite?.should == 1
+ end
+
+ it "returns NaN if other is NaN" do
+ 3334.fdiv(nan_value).nan?.should be_true
+ end
+end
diff --git a/spec/ruby/core/numeric/finite_spec.rb b/spec/ruby/core/numeric/finite_spec.rb
new file mode 100644
index 0000000000..05b5eebbd6
--- /dev/null
+++ b/spec/ruby/core/numeric/finite_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#finite?" do
+ it "returns true by default" do
+ o = mock_numeric("finite")
+ o.finite?.should be_true
+ end
+end
diff --git a/spec/ruby/core/numeric/fixtures/classes.rb b/spec/ruby/core/numeric/fixtures/classes.rb
new file mode 100644
index 0000000000..1505584889
--- /dev/null
+++ b/spec/ruby/core/numeric/fixtures/classes.rb
@@ -0,0 +1,17 @@
+module NumericSpecs
+ class Comparison < Numeric
+ # This method is used because we cannot define
+ # singleton methods on subclasses of Numeric,
+ # which is needed for a.should_receive to work.
+ def <=>(other)
+ ScratchPad.record :numeric_comparison
+ 1
+ end
+ end
+
+ class Subclass < Numeric
+ # Allow methods to be mocked
+ def singleton_method_added(val)
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/floor_spec.rb b/spec/ruby/core/numeric/floor_spec.rb
new file mode 100644
index 0000000000..80a4868e4d
--- /dev/null
+++ b/spec/ruby/core/numeric/floor_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#floor" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "converts self to a Float (using #to_f) and returns the #floor'ed result" do
+ @obj.should_receive(:to_f).and_return(2 - TOLERANCE, TOLERANCE - 2)
+ @obj.floor.should == 1
+ @obj.floor.should == -2
+ end
+end
diff --git a/spec/ruby/core/numeric/i_spec.rb b/spec/ruby/core/numeric/i_spec.rb
new file mode 100644
index 0000000000..621ecc09ec
--- /dev/null
+++ b/spec/ruby/core/numeric/i_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#i" do
+ it "returns a Complex object" do
+ 34.i.should be_an_instance_of(Complex)
+ end
+
+ it "sets the real part to 0" do
+ 7342.i.real.should == 0
+ end
+
+ it "sets the imaginary part to self" do
+ 62.81.i.imag.should == 62.81
+ end
+end
diff --git a/spec/ruby/core/numeric/imag_spec.rb b/spec/ruby/core/numeric/imag_spec.rb
new file mode 100644
index 0000000000..b9e343cee9
--- /dev/null
+++ b/spec/ruby/core/numeric/imag_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/imag'
+
+describe "Numeric#imag" do
+ it_behaves_like :numeric_imag, :imag
+end
diff --git a/spec/ruby/core/numeric/imaginary_spec.rb b/spec/ruby/core/numeric/imaginary_spec.rb
new file mode 100644
index 0000000000..ec708cb505
--- /dev/null
+++ b/spec/ruby/core/numeric/imaginary_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/imag'
+
+describe "Numeric#imaginary" do
+ it_behaves_like :numeric_imag, :imaginary
+end
diff --git a/spec/ruby/core/numeric/infinite_spec.rb b/spec/ruby/core/numeric/infinite_spec.rb
new file mode 100644
index 0000000000..3ea7825c8c
--- /dev/null
+++ b/spec/ruby/core/numeric/infinite_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#infinite?" do
+ it "returns nil by default" do
+ o = mock_numeric("infinite")
+ o.infinite?.should == nil
+ end
+end
diff --git a/spec/ruby/core/numeric/integer_spec.rb b/spec/ruby/core/numeric/integer_spec.rb
new file mode 100644
index 0000000000..adbac4d7aa
--- /dev/null
+++ b/spec/ruby/core/numeric/integer_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#integer?" do
+ it "returns false" do
+ NumericSpecs::Subclass.new.should_not.integer?
+ end
+end
diff --git a/spec/ruby/core/numeric/magnitude_spec.rb b/spec/ruby/core/numeric/magnitude_spec.rb
new file mode 100644
index 0000000000..1371dff21f
--- /dev/null
+++ b/spec/ruby/core/numeric/magnitude_spec.rb
@@ -0,0 +1,6 @@
+require_relative "../../spec_helper"
+require_relative 'shared/abs'
+
+describe "Numeric#magnitude" do
+ it_behaves_like :numeric_abs, :magnitude
+end
diff --git a/spec/ruby/core/numeric/modulo_spec.rb b/spec/ruby/core/numeric/modulo_spec.rb
new file mode 100644
index 0000000000..e3dc7e56f3
--- /dev/null
+++ b/spec/ruby/core/numeric/modulo_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe :numeric_modulo_19, shared: true do
+ it "returns self - other * self.div(other)" do
+ s = mock_numeric('self')
+ o = mock_numeric('other')
+ n3 = mock_numeric('n3')
+ n4 = mock_numeric('n4')
+ n5 = mock_numeric('n5')
+ s.should_receive(:div).with(o).and_return(n3)
+ o.should_receive(:*).with(n3).and_return(n4)
+ s.should_receive(:-).with(n4).and_return(n5)
+ s.send(@method, o).should == n5
+ end
+end
+
+describe "Numeric#modulo" do
+ it_behaves_like :numeric_modulo_19, :modulo
+end
+
+describe "Numeric#%" do
+ it_behaves_like :numeric_modulo_19, :%
+end
diff --git a/spec/ruby/core/numeric/negative_spec.rb b/spec/ruby/core/numeric/negative_spec.rb
new file mode 100644
index 0000000000..9c6f95fd87
--- /dev/null
+++ b/spec/ruby/core/numeric/negative_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#negative?" do
+ describe "on positive numbers" do
+ it "returns false" do
+ 1.negative?.should be_false
+ 0.1.negative?.should be_false
+ end
+ end
+
+ describe "on zero" do
+ it "returns false" do
+ 0.negative?.should be_false
+ 0.0.negative?.should be_false
+ end
+ end
+
+ describe "on negative numbers" do
+ it "returns true" do
+ -1.negative?.should be_true
+ -0.1.negative?.should be_true
+ end
+ end
+end
+
+describe "Numeric#negative?" do
+ before(:each) do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns true if self is less than 0" do
+ @obj.should_receive(:<).with(0).and_return(true)
+ @obj.should.negative?
+ end
+
+ it "returns false if self is greater than 0" do
+ @obj.should_receive(:<).with(0).and_return(false)
+ @obj.should_not.negative?
+ end
+end
diff --git a/spec/ruby/core/numeric/nonzero_spec.rb b/spec/ruby/core/numeric/nonzero_spec.rb
new file mode 100644
index 0000000000..464ed4f4f8
--- /dev/null
+++ b/spec/ruby/core/numeric/nonzero_spec.rb
@@ -0,0 +1,18 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#nonzero?" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns self if self#zero? is false" do
+ @obj.should_receive(:zero?).and_return(false)
+ @obj.nonzero?.should == @obj
+ end
+
+ it "returns nil if self#zero? is true" do
+ @obj.should_receive(:zero?).and_return(true)
+ @obj.nonzero?.should == nil
+ end
+end
diff --git a/spec/ruby/core/numeric/numerator_spec.rb b/spec/ruby/core/numeric/numerator_spec.rb
new file mode 100644
index 0000000000..668df8b797
--- /dev/null
+++ b/spec/ruby/core/numeric/numerator_spec.rb
@@ -0,0 +1,33 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#numerator" do
+ before :all do
+ @numbers = [
+ 0,
+ 29871,
+ 99999999999999**99,
+ -72628191273,
+ 29282.2827,
+ -2927.00091,
+ 0.0,
+ 12.0,
+ Float::MAX,
+ ]
+ end
+
+ # This isn't entirely true, as NaN.numerator works, whereas
+ # Rational(NaN) raises an exception, but we test this in Float#numerator
+ it "converts self to a Rational object then returns its numerator" do
+ @numbers.each do |number|
+ number.numerator.should == Rational(number).numerator
+ end
+ end
+
+ it "works with Numeric subclasses" do
+ rational = mock_numeric('rational')
+ rational.should_receive(:numerator).and_return(:numerator)
+ numeric = mock_numeric('numeric')
+ numeric.should_receive(:to_r).and_return(rational)
+ numeric.numerator.should == :numerator
+ end
+end
diff --git a/spec/ruby/core/numeric/numeric_spec.rb b/spec/ruby/core/numeric/numeric_spec.rb
new file mode 100644
index 0000000000..2bcf2a1175
--- /dev/null
+++ b/spec/ruby/core/numeric/numeric_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../spec_helper'
+
+describe "Numeric" do
+ it "includes Comparable" do
+ Numeric.include?(Comparable).should == true
+ end
+end
diff --git a/spec/ruby/core/numeric/phase_spec.rb b/spec/ruby/core/numeric/phase_spec.rb
new file mode 100644
index 0000000000..bc1995303f
--- /dev/null
+++ b/spec/ruby/core/numeric/phase_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/arg'
+
+describe "Numeric#phase" do
+ it_behaves_like :numeric_arg, :phase
+end
diff --git a/spec/ruby/core/numeric/polar_spec.rb b/spec/ruby/core/numeric/polar_spec.rb
new file mode 100644
index 0000000000..b594e408b2
--- /dev/null
+++ b/spec/ruby/core/numeric/polar_spec.rb
@@ -0,0 +1,50 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#polar" do
+ before :each do
+ @pos_numbers = [
+ 1,
+ 3898172610**9,
+ 987.18273,
+ Float::MAX,
+ Rational(13,7),
+ infinity_value,
+ ]
+ @neg_numbers = @pos_numbers.map {|n| -n}
+ @numbers = @pos_numbers + @neg_numbers
+ @numbers.push(0, 0.0)
+ end
+
+ it "returns a two-element Array" do
+ @numbers.each do |number|
+ number.polar.should be_an_instance_of(Array)
+ number.polar.size.should == 2
+ end
+ end
+
+ it "sets the first value to the absolute value of self" do
+ @numbers.each do |number|
+ number.polar.first.should == number.abs
+ end
+ end
+
+ it "sets the last value to 0 if self is positive" do
+ (@numbers - @neg_numbers).each do |number|
+ number.should >= 0
+ number.polar.last.should == 0
+ end
+ end
+
+ it "sets the last value to Pi if self is negative" do
+ @neg_numbers.each do |number|
+ number.should < 0
+ number.polar.last.should == Math::PI
+ end
+ end
+
+ it "returns [NaN, NaN] if self is NaN" do
+ nan_value.polar.size.should == 2
+ nan_value.polar.first.nan?.should be_true
+ nan_value.polar.last.nan?.should be_true
+ end
+end
diff --git a/spec/ruby/core/numeric/positive_spec.rb b/spec/ruby/core/numeric/positive_spec.rb
new file mode 100644
index 0000000000..3b831b4d34
--- /dev/null
+++ b/spec/ruby/core/numeric/positive_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#positive?" do
+ describe "on positive numbers" do
+ it "returns true" do
+ 1.positive?.should be_true
+ 0.1.positive?.should be_true
+ end
+ end
+
+ describe "on zero" do
+ it "returns false" do
+ 0.positive?.should be_false
+ 0.0.positive?.should be_false
+ end
+ end
+
+ describe "on negative numbers" do
+ it "returns false" do
+ -1.positive?.should be_false
+ -0.1.positive?.should be_false
+ end
+ end
+end
+
+describe "Numeric#positive?" do
+ before(:each) do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns true if self is greater than 0" do
+ @obj.should_receive(:>).with(0).and_return(true)
+ @obj.should.positive?
+ end
+
+ it "returns false if self is less than 0" do
+ @obj.should_receive(:>).with(0).and_return(false)
+ @obj.should_not.positive?
+ end
+end
diff --git a/spec/ruby/core/numeric/quo_spec.rb b/spec/ruby/core/numeric/quo_spec.rb
new file mode 100644
index 0000000000..6e3ce7a374
--- /dev/null
+++ b/spec/ruby/core/numeric/quo_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#quo" do
+ it "returns the result of self divided by the given Integer as a Rational" do
+ 5.quo(2).should eql(Rational(5,2))
+ end
+
+ it "returns the result of self divided by the given Float as a Float" do
+ 2.quo(2.5).should eql(0.8)
+ end
+
+ it "returns the result of self divided by the given Bignum as a Float" do
+ 45.quo(bignum_value).should be_close(1.04773789668636e-08, TOLERANCE)
+ end
+
+ it "raises a ZeroDivisionError when the given Integer is 0" do
+ -> { 0.quo(0) }.should raise_error(ZeroDivisionError)
+ -> { 10.quo(0) }.should raise_error(ZeroDivisionError)
+ -> { -10.quo(0) }.should raise_error(ZeroDivisionError)
+ -> { bignum_value.quo(0) }.should raise_error(ZeroDivisionError)
+ -> { (-bignum_value).quo(0) }.should raise_error(ZeroDivisionError)
+ end
+
+ it "calls #to_r to convert the object to a Rational" do
+ obj = NumericSpecs::Subclass.new
+ obj.should_receive(:to_r).and_return(Rational(1))
+
+ obj.quo(19).should == Rational(1, 19)
+ end
+
+ it "raises a TypeError of #to_r does not return a Rational" do
+ obj = NumericSpecs::Subclass.new
+ obj.should_receive(:to_r).and_return(1)
+
+ -> { obj.quo(19) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when given a non-Integer" do
+ -> {
+ (obj = mock('x')).should_not_receive(:to_int)
+ 13.quo(obj)
+ }.should raise_error(TypeError)
+ -> { 13.quo("10") }.should raise_error(TypeError)
+ -> { 13.quo(:symbol) }.should raise_error(TypeError)
+ end
+
+ it "returns the result of calling self#/ with other" do
+ obj = NumericSpecs::Subclass.new
+ obj.should_receive(:to_r).and_return(19.quo(20))
+
+ obj.quo(19).should == 1.quo(20)
+ end
+
+ it "raises a ZeroDivisionError if the given argument is zero and not a Float" do
+ -> { 1.quo(0) }.should raise_error(ZeroDivisionError)
+ end
+
+ it "returns infinity if the given argument is zero and is a Float" do
+ (1.quo(0.0)).to_s.should == 'Infinity'
+ (-1.quo(0.0)).to_s.should == '-Infinity'
+ end
+end
diff --git a/spec/ruby/core/numeric/real_spec.rb b/spec/ruby/core/numeric/real_spec.rb
new file mode 100644
index 0000000000..2d2499bcce
--- /dev/null
+++ b/spec/ruby/core/numeric/real_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#real" do
+ before :each do
+ @numbers = [
+ 20, # Integer
+ 398.72, # Float
+ Rational(3, 4), # Rational
+ bignum_value, # Bignum
+ infinity_value,
+ nan_value
+ ].map{ |n| [n, -n] }.flatten
+ end
+
+ it "returns self" do
+ @numbers.each do |number|
+ if number.to_f.nan?
+ number.real.nan?.should be_true
+ else
+ number.real.should == number
+ end
+ end
+ end
+
+ it "raises an ArgumentError if given any arguments" do
+ @numbers.each do |number|
+ -> { number.real(number) }.should raise_error(ArgumentError)
+ end
+ end
+end
+
+describe "Numeric#real?" do
+ it "returns true" do
+ NumericSpecs::Subclass.new.should.real?
+ end
+end
diff --git a/spec/ruby/core/numeric/rect_spec.rb b/spec/ruby/core/numeric/rect_spec.rb
new file mode 100644
index 0000000000..79a144c5a4
--- /dev/null
+++ b/spec/ruby/core/numeric/rect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/rect'
+
+describe "Numeric#rect" do
+ it_behaves_like :numeric_rect, :rect
+end
diff --git a/spec/ruby/core/numeric/rectangular_spec.rb b/spec/ruby/core/numeric/rectangular_spec.rb
new file mode 100644
index 0000000000..2c68985a16
--- /dev/null
+++ b/spec/ruby/core/numeric/rectangular_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/rect'
+
+describe "Numeric#rectangular" do
+ it_behaves_like :numeric_rect, :rectangular
+end
diff --git a/spec/ruby/core/numeric/remainder_spec.rb b/spec/ruby/core/numeric/remainder_spec.rb
new file mode 100644
index 0000000000..674fa22d8e
--- /dev/null
+++ b/spec/ruby/core/numeric/remainder_spec.rb
@@ -0,0 +1,70 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#remainder" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ @result = mock("Numeric#% result")
+ @other = mock("Passed Object")
+ ruby_version_is "3.3" do
+ @other.should_receive(:coerce).with(@obj).and_return([@obj, @other])
+ end
+ end
+
+ it "returns the result of calling self#% with other if self is 0" do
+ @obj.should_receive(:%).with(@other).and_return(@result)
+ @result.should_receive(:==).with(0).and_return(true)
+
+ @obj.remainder(@other).should equal(@result)
+ end
+
+ it "returns the result of calling self#% with other if self and other are greater than 0" do
+ @obj.should_receive(:%).with(@other).and_return(@result)
+ @result.should_receive(:==).with(0).and_return(false)
+
+ @obj.should_receive(:<).with(0).and_return(false)
+
+ @obj.should_receive(:>).with(0).and_return(true)
+ @other.should_receive(:<).with(0).and_return(false)
+
+ @obj.remainder(@other).should equal(@result)
+ end
+
+ it "returns the result of calling self#% with other if self and other are less than 0" do
+ @obj.should_receive(:%).with(@other).and_return(@result)
+ @result.should_receive(:==).with(0).and_return(false)
+
+ @obj.should_receive(:<).with(0).and_return(true)
+ @other.should_receive(:>).with(0).and_return(false)
+
+ @obj.should_receive(:>).with(0).and_return(false)
+
+ @obj.remainder(@other).should equal(@result)
+ end
+
+ it "returns the result of calling self#% with other - other if self is greater than 0 and other is less than 0" do
+ @obj.should_receive(:%).with(@other).and_return(@result)
+ @result.should_receive(:==).with(0).and_return(false)
+
+ @obj.should_receive(:<).with(0).and_return(false)
+
+ @obj.should_receive(:>).with(0).and_return(true)
+ @other.should_receive(:<).with(0).and_return(true)
+
+ @result.should_receive(:-).with(@other).and_return(:result)
+
+ @obj.remainder(@other).should == :result
+ end
+
+ it "returns the result of calling self#% with other - other if self is less than 0 and other is greater than 0" do
+ @obj.should_receive(:%).with(@other).and_return(@result)
+ @result.should_receive(:==).with(0).and_return(false)
+
+ @obj.should_receive(:<).with(0).and_return(true)
+ @other.should_receive(:>).with(0).and_return(true)
+
+ @result.should_receive(:-).with(@other).and_return(:result)
+
+ @obj.remainder(@other).should == :result
+ end
+end
diff --git a/spec/ruby/core/numeric/round_spec.rb b/spec/ruby/core/numeric/round_spec.rb
new file mode 100644
index 0000000000..47c5837693
--- /dev/null
+++ b/spec/ruby/core/numeric/round_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#round" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "converts self to a Float (using #to_f) and returns the #round'ed result" do
+ @obj.should_receive(:to_f).and_return(2 - TOLERANCE, TOLERANCE - 2)
+ @obj.round.should == 2
+ @obj.round.should == -2
+ end
+end
diff --git a/spec/ruby/core/numeric/shared/abs.rb b/spec/ruby/core/numeric/shared/abs.rb
new file mode 100644
index 0000000000..c3dadccfd6
--- /dev/null
+++ b/spec/ruby/core/numeric/shared/abs.rb
@@ -0,0 +1,19 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+
+describe :numeric_abs, shared: true do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns self when self is greater than 0" do
+ @obj.should_receive(:<).with(0).and_return(false)
+ @obj.send(@method).should == @obj
+ end
+
+ it "returns self\#@- when self is less than 0" do
+ @obj.should_receive(:<).with(0).and_return(true)
+ @obj.should_receive(:-@).and_return(:absolute_value)
+ @obj.send(@method).should == :absolute_value
+ end
+end
diff --git a/spec/ruby/core/numeric/shared/arg.rb b/spec/ruby/core/numeric/shared/arg.rb
new file mode 100644
index 0000000000..c8e7ad8333
--- /dev/null
+++ b/spec/ruby/core/numeric/shared/arg.rb
@@ -0,0 +1,38 @@
+require_relative '../../../spec_helper'
+
+describe :numeric_arg, shared: true do
+ before :each do
+ @numbers = [
+ 20,
+ Rational(3, 4),
+ bignum_value,
+ infinity_value
+ ]
+ end
+
+ it "returns 0 if positive" do
+ @numbers.each do |number|
+ number.send(@method).should == 0
+ end
+ end
+
+ it "returns Pi if negative" do
+ @numbers.each do |number|
+ (0-number).send(@method).should == Math::PI
+ end
+ end
+
+ describe "with a Numeric subclass" do
+ it "returns 0 if self#<(0) returns false" do
+ numeric = mock_numeric('positive')
+ numeric.should_receive(:<).with(0).and_return(false)
+ numeric.send(@method).should == 0
+ end
+
+ it "returns Pi if self#<(0) returns true" do
+ numeric = mock_numeric('positive')
+ numeric.should_receive(:<).with(0).and_return(true)
+ numeric.send(@method).should == Math::PI
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/shared/conj.rb b/spec/ruby/core/numeric/shared/conj.rb
new file mode 100644
index 0000000000..6d5197ecab
--- /dev/null
+++ b/spec/ruby/core/numeric/shared/conj.rb
@@ -0,0 +1,20 @@
+require_relative '../../../spec_helper'
+
+describe :numeric_conj, shared: true do
+ before :each do
+ @numbers = [
+ 20, # Integer
+ 398.72, # Float
+ Rational(3, 4), # Rational
+ bignum_value,
+ infinity_value,
+ nan_value
+ ]
+ end
+
+ it "returns self" do
+ @numbers.each do |number|
+ number.send(@method).should equal(number)
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/shared/imag.rb b/spec/ruby/core/numeric/shared/imag.rb
new file mode 100644
index 0000000000..4f117e243a
--- /dev/null
+++ b/spec/ruby/core/numeric/shared/imag.rb
@@ -0,0 +1,26 @@
+require_relative '../../../spec_helper'
+
+describe :numeric_imag, shared: true do
+ before :each do
+ @numbers = [
+ 20, # Integer
+ 398.72, # Float
+ Rational(3, 4), # Rational
+ bignum_value, # Bignum
+ infinity_value,
+ nan_value
+ ].map{|n| [n,-n]}.flatten
+ end
+
+ it "returns 0" do
+ @numbers.each do |number|
+ number.send(@method).should == 0
+ end
+ end
+
+ it "raises an ArgumentError if given any arguments" do
+ @numbers.each do |number|
+ -> { number.send(@method, number) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/shared/rect.rb b/spec/ruby/core/numeric/shared/rect.rb
new file mode 100644
index 0000000000..120a69b1c4
--- /dev/null
+++ b/spec/ruby/core/numeric/shared/rect.rb
@@ -0,0 +1,48 @@
+require_relative '../../../spec_helper'
+
+describe :numeric_rect, shared: true do
+ before :each do
+ @numbers = [
+ 20, # Integer
+ 398.72, # Float
+ Rational(3, 4), # Rational
+ 99999999**99, # Bignum
+ infinity_value,
+ nan_value
+ ]
+ end
+
+ it "returns an Array" do
+ @numbers.each do |number|
+ number.send(@method).should be_an_instance_of(Array)
+ end
+ end
+
+ it "returns a two-element Array" do
+ @numbers.each do |number|
+ number.send(@method).size.should == 2
+ end
+ end
+
+ it "returns self as the first element" do
+ @numbers.each do |number|
+ if Float === number and number.nan?
+ number.send(@method).first.nan?.should be_true
+ else
+ number.send(@method).first.should == number
+ end
+ end
+ end
+
+ it "returns 0 as the last element" do
+ @numbers.each do |number|
+ number.send(@method).last.should == 0
+ end
+ end
+
+ it "raises an ArgumentError if given any arguments" do
+ @numbers.each do |number|
+ -> { number.send(@method, number) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/shared/step.rb b/spec/ruby/core/numeric/shared/step.rb
new file mode 100644
index 0000000000..977ec6de02
--- /dev/null
+++ b/spec/ruby/core/numeric/shared/step.rb
@@ -0,0 +1,410 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+
+# Describes Numeric#step shared specs between different argument styles.
+# To be able to do it, the @step ivar must contain a Proc that transforms
+# the step call arguments passed as positional arguments to the style of
+# arguments pretended to test.
+describe :numeric_step, shared: true do
+ before :each do
+ ScratchPad.record []
+ @prc = -> x { ScratchPad << x }
+ end
+
+ it "defaults to step = 1" do
+ @step.call(1, 5, &@prc)
+ ScratchPad.recorded.should eql [1, 2, 3, 4, 5]
+ end
+
+ it "defaults to an infinite limit with a step size of 1 for Integers" do
+ 1.step.first(5).should == [1, 2, 3, 4, 5]
+ end
+
+ it "defaults to an infinite limit with a step size of 1.0 for Floats" do
+ 1.0.step.first(5).should == [1.0, 2.0, 3.0, 4.0, 5.0]
+ end
+
+ describe "when self, stop and step are Integers" do
+ it "yields only Integers" do
+ @step.call(1, 5, 1) { |x| x.should be_an_instance_of(Integer) }
+ end
+
+ describe "with a positive step" do
+ it "yields while increasing self by step until stop is reached" do
+ @step.call(1, 5, 1, &@prc)
+ ScratchPad.recorded.should eql [1, 2, 3, 4, 5]
+ end
+
+ it "yields once when self equals stop" do
+ @step.call(1, 1, 1, &@prc)
+ ScratchPad.recorded.should eql [1]
+ end
+
+ it "does not yield when self is greater than stop" do
+ @step.call(2, 1, 1, &@prc)
+ ScratchPad.recorded.should eql []
+ end
+ end
+
+ describe "with a negative step" do
+ it "yields while decreasing self by step until stop is reached" do
+ @step.call(5, 1, -1, &@prc)
+ ScratchPad.recorded.should eql [5, 4, 3, 2, 1]
+ end
+
+ it "yields once when self equals stop" do
+ @step.call(5, 5, -1, &@prc)
+ ScratchPad.recorded.should eql [5]
+ end
+
+ it "does not yield when self is less than stop" do
+ @step.call(1, 5, -1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+ end
+
+ describe "when at least one of self, stop or step is a Float" do
+ it "yields Floats even if only self is a Float" do
+ @step.call(1.5, 5, 1) { |x| x.should be_an_instance_of(Float) }
+ end
+
+ it "yields Floats even if only stop is a Float" do
+ @step.call(1, 5.0, 1) { |x| x.should be_an_instance_of(Float) }
+ end
+
+ it "yields Floats even if only step is a Float" do
+ @step.call(1, 5, 1.0) { |x| x.should be_an_instance_of(Float) }
+ end
+
+ describe "with a positive step" do
+ it "yields while increasing self by step while < stop" do
+ @step.call(1.5, 5, 1, &@prc)
+ ScratchPad.recorded.should eql [1.5, 2.5, 3.5, 4.5]
+ end
+
+ it "yields once when self equals stop" do
+ @step.call(1.5, 1.5, 1, &@prc)
+ ScratchPad.recorded.should eql [1.5]
+ end
+
+ it "does not yield when self is greater than stop" do
+ @step.call(2.5, 1.5, 1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+
+ it "is careful about not yielding a value greater than limit" do
+ # As 9*1.3+1.0 == 12.700000000000001 > 12.7, we test:
+ @step.call(1.0, 12.7, 1.3, &@prc)
+ ScratchPad.recorded.should eql [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]
+ end
+ end
+
+ describe "with a negative step" do
+ it "yields while decreasing self by step while self > stop" do
+ @step.call(5, 1.5, -1, &@prc)
+ ScratchPad.recorded.should eql [5.0, 4.0, 3.0, 2.0]
+ end
+
+ it "yields once when self equals stop" do
+ @step.call(1.5, 1.5, -1, &@prc)
+ ScratchPad.recorded.should eql [1.5]
+ end
+
+ it "does not yield when self is less than stop" do
+ @step.call(1, 5, -1.5, &@prc)
+ ScratchPad.recorded.should == []
+ end
+
+ it "is careful about not yielding a value smaller than limit" do
+ # As -9*1.3-1.0 == -12.700000000000001 < -12.7, we test:
+ @step.call(-1.0, -12.7, -1.3, &@prc)
+ ScratchPad.recorded.should eql [-1.0, -2.3, -3.6, -4.9, -6.2, -7.5, -8.8, -10.1, -11.4, -12.7]
+ end
+ end
+
+ describe "with a positive Infinity step" do
+ it "yields once if self < stop" do
+ @step.call(42, 100, infinity_value, &@prc)
+ ScratchPad.recorded.should eql [42.0]
+ end
+
+ it "yields once when stop is Infinity" do
+ @step.call(42, infinity_value, infinity_value, &@prc)
+ ScratchPad.recorded.should eql [42.0]
+ end
+
+ it "yields once when self equals stop" do
+ @step.call(42, 42, infinity_value, &@prc)
+ ScratchPad.recorded.should eql [42.0]
+ end
+
+ it "yields once when self and stop are Infinity" do
+ # @step.call(infinity_value, infinity_value, infinity_value, &@prc)
+ @step.call(infinity_value, infinity_value, infinity_value, &@prc)
+ ScratchPad.recorded.should == [infinity_value]
+ end
+
+ it "does not yield when self > stop" do
+ @step.call(100, 42, infinity_value, &@prc)
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not yield when stop is -Infinity" do
+ @step.call(42, -infinity_value, infinity_value, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "with a negative Infinity step" do
+ it "yields once if self > stop" do
+ @step.call(42, 6, -infinity_value, &@prc)
+ ScratchPad.recorded.should eql [42.0]
+ end
+
+ it "yields once if stop is -Infinity" do
+ @step.call(42, -infinity_value, -infinity_value, &@prc)
+ ScratchPad.recorded.should eql [42.0]
+ end
+
+ it "yields once when self equals stop" do
+ @step.call(42, 42, -infinity_value, &@prc)
+ ScratchPad.recorded.should eql [42.0]
+ end
+
+ it "yields once when self and stop are Infinity" do
+ @step.call(infinity_value, infinity_value, -infinity_value, &@prc)
+ ScratchPad.recorded.should == [infinity_value]
+ end
+
+ it "does not yield when self > stop" do
+ @step.call(42, 100, -infinity_value, &@prc)
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not yield when stop is Infinity" do
+ @step.call(42, infinity_value, -infinity_value, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "with a Infinity stop and a positive step" do
+ it "does not yield when self is infinity" do
+ @step.call(infinity_value, infinity_value, 1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "with a Infinity stop and a negative step" do
+ it "does not yield when self is negative infinity" do
+ @step.call(-infinity_value, infinity_value, -1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+
+ it "does not yield when self is positive infinity" do
+ @step.call(infinity_value, infinity_value, -1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "with a negative Infinity stop and a positive step" do
+ it "does not yield when self is negative infinity" do
+ @step.call(-infinity_value, -infinity_value, 1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ describe "with a negative Infinity stop and a negative step" do
+ it "does not yield when self is negative infinity" do
+ @step.call(-infinity_value, -infinity_value, -1, &@prc)
+ ScratchPad.recorded.should == []
+ end
+ end
+
+ end
+
+ describe "when step is a String" do
+ describe "with self and stop as Integers" do
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1, 5, "1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "0.1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "1/3") {} }.should raise_error(ArgumentError)
+ end
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1, 5, "foo") {} }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "with self and stop as Floats" do
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1.1, 5.1, "1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "0.1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1/3") {} }.should raise_error(ArgumentError)
+ end
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1.1, 5.1, "foo") {} }.should raise_error(ArgumentError)
+ end
+ end
+ end
+
+ it "does not rescue ArgumentError exceptions" do
+ -> { @step.call(1, 2) { raise ArgumentError, "" }}.should raise_error(ArgumentError)
+ end
+
+ it "does not rescue TypeError exceptions" do
+ -> { @step.call(1, 2) { raise TypeError, "" } }.should raise_error(TypeError)
+ end
+
+ describe "when no block is given" do
+ step_enum_class = Enumerator::ArithmeticSequence
+
+ it "returns an #{step_enum_class} when not passed a block and self > stop" do
+ @step.call(1, 0, 2).should be_an_instance_of(step_enum_class)
+ end
+
+ it "returns an #{step_enum_class} when not passed a block and self < stop" do
+ @step.call(1, 2, 3).should be_an_instance_of(step_enum_class)
+ end
+
+ it "returns an #{step_enum_class} that uses the given step" do
+ @step.call(0, 5, 2).to_a.should eql [0, 2, 4]
+ end
+
+ describe "when step is a String" do
+ describe "with self and stop as Integers" do
+ it "returns an Enumerator" do
+ @step.call(1, 5, "foo").should be_an_instance_of(Enumerator)
+ end
+ end
+
+ describe "with self and stop as Floats" do
+ it "returns an Enumerator" do
+ @step.call(1.1, 5.1, "foo").should be_an_instance_of(Enumerator)
+ end
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ describe "when step is a String" do
+ describe "with self and stop as Integers" do
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1, 5, "1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "0.1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "1/3").size }.should raise_error(ArgumentError)
+ end
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1, 5, "foo").size }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "with self and stop as Floats" do
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1.1, 5.1, "1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "0.1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1/3").size }.should raise_error(ArgumentError)
+ end
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1.1, 5.1, "foo").size }.should raise_error(ArgumentError)
+ end
+ end
+ end
+
+ describe "when self, stop and step are Integers and step is positive" do
+ it "returns the difference between self and stop divided by the number of steps" do
+ @step.call(5, 10, 11).size.should == 1
+ @step.call(5, 10, 6).size.should == 1
+ @step.call(5, 10, 5).size.should == 2
+ @step.call(5, 10, 4).size.should == 2
+ @step.call(5, 10, 2).size.should == 3
+ @step.call(5, 10, 1).size.should == 6
+ @step.call(5, 10).size.should == 6
+ @step.call(10, 10, 1).size.should == 1
+ end
+
+ it "returns 0 if value > limit" do
+ @step.call(11, 10, 1).size.should == 0
+ end
+ end
+
+ describe "when self, stop and step are Integers and step is negative" do
+ it "returns the difference between self and stop divided by the number of steps" do
+ @step.call(10, 5, -11).size.should == 1
+ @step.call(10, 5, -6).size.should == 1
+ @step.call(10, 5, -5).size.should == 2
+ @step.call(10, 5, -4).size.should == 2
+ @step.call(10, 5, -2).size.should == 3
+ @step.call(10, 5, -1).size.should == 6
+ @step.call(10, 10, -1).size.should == 1
+ end
+
+ it "returns 0 if value < limit" do
+ @step.call(10, 11, -1).size.should == 0
+ end
+ end
+
+ describe "when self, stop or step is a Float" do
+ describe "and step is positive" do
+ it "returns the difference between self and stop divided by the number of steps" do
+ @step.call(5, 10, 11.0).size.should == 1
+ @step.call(5, 10, 6.0).size.should == 1
+ @step.call(5, 10, 5.0).size.should == 2
+ @step.call(5, 10, 4.0).size.should == 2
+ @step.call(5, 10, 2.0).size.should == 3
+ @step.call(5, 10, 0.5).size.should == 11
+ @step.call(5, 10, 1.0).size.should == 6
+ @step.call(5, 10.5).size.should == 6
+ @step.call(10, 10, 1.0).size.should == 1
+ end
+
+ it "returns 0 if value > limit" do
+ @step.call(10, 5.5).size.should == 0
+ @step.call(11, 10, 1.0).size.should == 0
+ @step.call(11, 10, 1.5).size.should == 0
+ @step.call(10, 5, infinity_value).size.should == 0
+ end
+
+ it "returns 1 if step is infinity_value" do
+ @step.call(5, 10, infinity_value).size.should == 1
+ end
+ end
+
+ describe "and step is negative" do
+ it "returns the difference between self and stop divided by the number of steps" do
+ @step.call(10, 5, -11.0).size.should == 1
+ @step.call(10, 5, -6.0).size.should == 1
+ @step.call(10, 5, -5.0).size.should == 2
+ @step.call(10, 5, -4.0).size.should == 2
+ @step.call(10, 5, -2.0).size.should == 3
+ @step.call(10, 5, -0.5).size.should == 11
+ @step.call(10, 5, -1.0).size.should == 6
+ @step.call(10, 10, -1.0).size.should == 1
+ end
+
+ it "returns 0 if value < limit" do
+ @step.call(10, 11, -1.0).size.should == 0
+ @step.call(10, 11, -1.5).size.should == 0
+ @step.call(5, 10, -infinity_value).size.should == 0
+ end
+
+ it "returns 1 if step is infinity_value" do
+ @step.call(10, 5, -infinity_value).size.should == 1
+ end
+ end
+ end
+
+ describe "when stop is not passed" do
+ it "returns infinity_value" do
+ @step.call(1).size.should == infinity_value
+ end
+ end
+
+ describe "when stop is nil" do
+ it "returns infinity_value" do
+ @step.call(1, nil, 5).size.should == infinity_value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/singleton_method_added_spec.rb b/spec/ruby/core/numeric/singleton_method_added_spec.rb
new file mode 100644
index 0000000000..2091398e5d
--- /dev/null
+++ b/spec/ruby/core/numeric/singleton_method_added_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#singleton_method_added" do
+ before :all do
+ class ::NumericSpecs::Subclass
+ # We want restore default Numeric behaviour for this particular test
+ remove_method :singleton_method_added
+ end
+ end
+
+ after :all do
+ class ::NumericSpecs::Subclass
+ # Allow mocking methods again
+ def singleton_method_added(val)
+ end
+ end
+ end
+
+ it "raises a TypeError when trying to define a singleton method on a Numeric" do
+ -> do
+ a = NumericSpecs::Subclass.new
+ def a.test; end
+ end.should raise_error(TypeError)
+
+ -> do
+ a = 1
+ def a.test; end
+ end.should raise_error(TypeError)
+
+ -> do
+ a = 1.5
+ def a.test; end
+ end.should raise_error(TypeError)
+
+ -> do
+ a = bignum_value
+ def a.test; end
+ end.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb
new file mode 100644
index 0000000000..1705fb1b4e
--- /dev/null
+++ b/spec/ruby/core/numeric/step_spec.rb
@@ -0,0 +1,121 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/step'
+
+describe "Numeric#step" do
+
+ describe 'with positional args' do
+ it "raises an ArgumentError when step is 0" do
+ -> { 1.step(5, 0) {} }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when step is 0.0" do
+ -> { 1.step(2, 0.0) {} }.should raise_error(ArgumentError)
+ end
+
+ before :all do
+ # This lambda definition limits to return the arguments it receives.
+ # It's needed to test numeric_step behaviour with positional arguments.
+ @step = -> receiver, *args, &block { receiver.step(*args, &block) }
+ end
+ it_behaves_like :numeric_step, :step
+
+ describe "when no block is given" do
+ step_enum_class = Enumerator::ArithmeticSequence
+
+ describe "returned #{step_enum_class}" do
+ describe "size" do
+ it "defaults to an infinite size" do
+ enum = 1.step
+ enum.size.should == Float::INFINITY
+ end
+ end
+
+ describe "type" do
+ it "returns an instance of Enumerator::ArithmeticSequence" do
+ 1.step(10).class.should == Enumerator::ArithmeticSequence
+ end
+ end
+ end
+ end
+ end
+
+ describe 'with keyword arguments' do
+ describe "when no block is given" do
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return infinity_value when limit is nil" do
+ 1.step(by: 42).size.should == infinity_value
+ end
+
+ it "should return infinity_value when ascending towards a limit of Float::INFINITY" do
+ 1.step(to: Float::INFINITY, by: 42).size.should == infinity_value
+ end
+
+ it "should return infinity_value when descending towards a limit of -Float::INFINITY" do
+ 1.step(to: -Float::INFINITY, by: -42).size.should == infinity_value
+ end
+
+ it "should return 1 when the both limit and step are Float::INFINITY" do
+ 1.step(to: Float::INFINITY, by: Float::INFINITY).size.should == 1
+ end
+
+ it "should return 1 when the both limit and step are -Float::INFINITY" do
+ 1.step(to: -Float::INFINITY, by: -Float::INFINITY).size.should == 1
+ end
+ end
+ end
+ end
+
+ before :all do
+ # This lambda transforms a positional step method args into keyword arguments.
+ # It's needed to test numeric_step behaviour with keyword arguments.
+ @step = -> receiver, *args, &block do
+ kw_args = { to: args[0] }
+ kw_args[:by] = args[1] if args.size == 2
+ receiver.step(**kw_args, &block)
+ end
+ end
+ it_behaves_like :numeric_step, :step
+ end
+
+ describe 'with mixed arguments' do
+ it " raises an ArgumentError when step is 0" do
+ -> { 1.step(5, by: 0) { break } }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when step is 0.0" do
+ -> { 1.step(2, by: 0.0) { break } }.should raise_error(ArgumentError)
+ end
+
+ it "raises a ArgumentError when limit and to are defined" do
+ -> { 1.step(5, 1, to: 5) { break } }.should raise_error(ArgumentError)
+ end
+
+ it "raises a ArgumentError when step and by are defined" do
+ -> { 1.step(5, 1, by: 5) { break } }.should raise_error(ArgumentError)
+ end
+
+ describe "when no block is given" do
+ describe "returned Enumerator" do
+ describe "size" do
+ end
+ end
+ end
+
+ before :all do
+ # This lambda definition transforms a positional step method args into
+ # a mix of positional and keyword arguments.
+ # It's needed to test numeric_step behaviour with positional mixed with
+ # keyword arguments.
+ @step = -> receiver, *args, &block do
+ if args.size == 2
+ receiver.step(args[0], by: args[1], &block)
+ else
+ receiver.step(*args, &block)
+ end
+ end
+ end
+ it_behaves_like :numeric_step, :step
+ end
+end
diff --git a/spec/ruby/core/numeric/to_c_spec.rb b/spec/ruby/core/numeric/to_c_spec.rb
new file mode 100644
index 0000000000..75245a612e
--- /dev/null
+++ b/spec/ruby/core/numeric/to_c_spec.rb
@@ -0,0 +1,45 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#to_c" do
+ before :all do
+ @numbers = [
+ 0,
+ 29871,
+ 99999999999999**99,
+ -72628191273,
+ Rational(2,3),
+ Rational(1.898),
+ Rational(-238),
+ 29282.2827,
+ -2927.00091,
+ 0.0,
+ 12.0,
+ Float::MAX,
+ infinity_value,
+ nan_value
+ ]
+ end
+
+ it "returns a Complex object" do
+ @numbers.each do |number|
+ number.to_c.should be_an_instance_of(Complex)
+ end
+ end
+
+ it "uses self as the real component" do
+ @numbers.each do |number|
+ real = number.to_c.real
+ if Float === number and number.nan?
+ real.nan?.should be_true
+ else
+ real.should == number
+ end
+ end
+ end
+
+ it "uses 0 as the imaginary component" do
+ @numbers.each do |number|
+ number.to_c.imag.should == 0
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/to_int_spec.rb b/spec/ruby/core/numeric/to_int_spec.rb
new file mode 100644
index 0000000000..3cc39a6d40
--- /dev/null
+++ b/spec/ruby/core/numeric/to_int_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#to_int" do
+ it "returns self#to_i" do
+ obj = NumericSpecs::Subclass.new
+ obj.should_receive(:to_i).and_return(:result)
+ obj.to_int.should == :result
+ end
+end
diff --git a/spec/ruby/core/numeric/truncate_spec.rb b/spec/ruby/core/numeric/truncate_spec.rb
new file mode 100644
index 0000000000..f1592334c5
--- /dev/null
+++ b/spec/ruby/core/numeric/truncate_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#truncate" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "converts self to a Float (using #to_f) and returns the #truncate'd result" do
+ @obj.should_receive(:to_f).and_return(2.5555, -2.3333)
+ @obj.truncate.should == 2
+ @obj.truncate.should == -2
+ end
+end
diff --git a/spec/ruby/core/numeric/uminus_spec.rb b/spec/ruby/core/numeric/uminus_spec.rb
new file mode 100644
index 0000000000..39065fa392
--- /dev/null
+++ b/spec/ruby/core/numeric/uminus_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#-@" do
+ it "returns the same value with opposite sign (integers)" do
+ 0.send(:-@).should == 0
+ 100.send(:-@).should == -100
+ -100.send(:-@).should == 100
+ end
+
+ it "returns the same value with opposite sign (floats)" do
+ 34.56.send(:-@).should == -34.56
+ -34.56.send(:-@).should == 34.56
+ end
+
+ it "returns the same value with opposite sign (two complement)" do
+ 2147483648.send(:-@).should == -2147483648
+ -2147483648.send(:-@).should == 2147483648
+ 9223372036854775808.send(:-@).should == -9223372036854775808
+ -9223372036854775808.send(:-@).should == 9223372036854775808
+ end
+
+ describe "with a Numeric subclass" do
+ it "calls #coerce(0) on self, then subtracts the second element of the result from the first" do
+ ten = mock_numeric('10')
+ zero = mock_numeric('0')
+ ten.should_receive(:coerce).with(0).and_return([zero, ten])
+ zero.should_receive(:-).with(ten).and_return(-10)
+ ten.send(:-@).should == -10
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/uplus_spec.rb b/spec/ruby/core/numeric/uplus_spec.rb
new file mode 100644
index 0000000000..88cf5e037b
--- /dev/null
+++ b/spec/ruby/core/numeric/uplus_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#+@" do
+ it "returns self" do
+ obj = NumericSpecs::Subclass.new
+ obj.send(:+@).should == obj
+ end
+end
diff --git a/spec/ruby/core/numeric/zero_spec.rb b/spec/ruby/core/numeric/zero_spec.rb
new file mode 100644
index 0000000000..0fb7619bcd
--- /dev/null
+++ b/spec/ruby/core/numeric/zero_spec.rb
@@ -0,0 +1,18 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Numeric#zero?" do
+ before :each do
+ @obj = NumericSpecs::Subclass.new
+ end
+
+ it "returns true if self is 0" do
+ @obj.should_receive(:==).with(0).and_return(true)
+ @obj.should.zero?
+ end
+
+ it "returns false if self is not 0" do
+ @obj.should_receive(:==).with(0).and_return(false)
+ @obj.should_not.zero?
+ end
+end