rubysl-bigdecimal 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/ext/rubysl/bigdecimal/bigdecimal.c +4760 -0
- data/ext/rubysl/bigdecimal/bigdecimal.h +220 -0
- data/ext/rubysl/bigdecimal/extconf.rb +6 -0
- data/lib/bigdecimal.rb +1 -0
- data/lib/bigdecimal/README +60 -0
- data/lib/bigdecimal/bigdecimal_en.html +796 -0
- data/lib/bigdecimal/bigdecimal_ja.html +799 -0
- data/lib/bigdecimal/jacobian.rb +85 -0
- data/lib/bigdecimal/ludcmp.rb +84 -0
- data/lib/bigdecimal/math.rb +235 -0
- data/lib/bigdecimal/newton.rb +77 -0
- data/lib/bigdecimal/sample/linear.rb +71 -0
- data/lib/bigdecimal/sample/nlsolve.rb +38 -0
- data/lib/bigdecimal/sample/pi.rb +20 -0
- data/lib/bigdecimal/util.rb +65 -0
- data/lib/rubysl/bigdecimal.rb +2 -0
- data/lib/rubysl/bigdecimal/version.rb +5 -0
- data/rubysl-bigdecimal.gemspec +24 -0
- data/spec/abs_spec.rb +49 -0
- data/spec/add_spec.rb +178 -0
- data/spec/case_compare_spec.rb +6 -0
- data/spec/ceil_spec.rb +122 -0
- data/spec/coerce_spec.rb +25 -0
- data/spec/comparison_spec.rb +80 -0
- data/spec/div_spec.rb +143 -0
- data/spec/divide_spec.rb +6 -0
- data/spec/divmod_spec.rb +233 -0
- data/spec/double_fig_spec.rb +8 -0
- data/spec/eql_spec.rb +5 -0
- data/spec/equal_value_spec.rb +6 -0
- data/spec/exponent_spec.rb +37 -0
- data/spec/finite_spec.rb +34 -0
- data/spec/fix_spec.rb +56 -0
- data/spec/fixtures/classes.rb +17 -0
- data/spec/floor_spec.rb +109 -0
- data/spec/frac_spec.rb +47 -0
- data/spec/gt_spec.rb +86 -0
- data/spec/gte_spec.rb +90 -0
- data/spec/induced_from_spec.rb +36 -0
- data/spec/infinite_spec.rb +31 -0
- data/spec/inspect_spec.rb +40 -0
- data/spec/limit_spec.rb +29 -0
- data/spec/lt_spec.rb +84 -0
- data/spec/lte_spec.rb +90 -0
- data/spec/minus_spec.rb +57 -0
- data/spec/mode_spec.rb +64 -0
- data/spec/modulo_spec.rb +11 -0
- data/spec/mult_spec.rb +23 -0
- data/spec/multiply_spec.rb +25 -0
- data/spec/nan_spec.rb +22 -0
- data/spec/new_spec.rb +120 -0
- data/spec/nonzero_spec.rb +28 -0
- data/spec/plus_spec.rb +49 -0
- data/spec/power_spec.rb +5 -0
- data/spec/precs_spec.rb +48 -0
- data/spec/quo_spec.rb +12 -0
- data/spec/remainder_spec.rb +83 -0
- data/spec/round_spec.rb +193 -0
- data/spec/shared/eql.rb +65 -0
- data/spec/shared/modulo.rb +146 -0
- data/spec/shared/mult.rb +97 -0
- data/spec/shared/power.rb +83 -0
- data/spec/shared/quo.rb +59 -0
- data/spec/shared/to_int.rb +27 -0
- data/spec/sign_spec.rb +46 -0
- data/spec/split_spec.rb +87 -0
- data/spec/sqrt_spec.rb +111 -0
- data/spec/sub_spec.rb +52 -0
- data/spec/to_f_spec.rb +54 -0
- data/spec/to_i_spec.rb +6 -0
- data/spec/to_int_spec.rb +7 -0
- data/spec/to_s_spec.rb +71 -0
- data/spec/truncate_spec.rb +100 -0
- data/spec/uminus_spec.rb +57 -0
- data/spec/uplus_spec.rb +19 -0
- data/spec/ver_spec.rb +10 -0
- data/spec/zero_spec.rb +27 -0
- metadata +243 -0
data/spec/ceil_spec.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
describe "BigDecimal#ceil" do
|
4
|
+
before(:each) do
|
5
|
+
@zero = BigDecimal("0")
|
6
|
+
@one = BigDecimal("1")
|
7
|
+
@three = BigDecimal("3")
|
8
|
+
@four = BigDecimal("4")
|
9
|
+
@mixed = BigDecimal("1.23456789")
|
10
|
+
@mixed_big = BigDecimal("1.23456789E100")
|
11
|
+
@pos_int = BigDecimal("2E5555")
|
12
|
+
@neg_int = BigDecimal("-2E5555")
|
13
|
+
@pos_frac = BigDecimal("2E-9999")
|
14
|
+
@neg_frac = BigDecimal("-2E-9999")
|
15
|
+
|
16
|
+
@infinity = BigDecimal("Infinity")
|
17
|
+
@infinity_neg = BigDecimal("-Infinity")
|
18
|
+
@nan = BigDecimal("NaN")
|
19
|
+
@zero_pos = BigDecimal("+0")
|
20
|
+
@zero_neg = BigDecimal("-0")
|
21
|
+
end
|
22
|
+
|
23
|
+
ruby_version_is "" ... "1.9" do
|
24
|
+
it "returns a BigDecimal" do
|
25
|
+
@mixed.ceil.kind_of?(BigDecimal).should == true
|
26
|
+
@pos_int.ceil(2).kind_of?(BigDecimal).should == true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ruby_version_is "1.9" do
|
31
|
+
it "returns an Integer, if n is unspecified" do
|
32
|
+
@mixed.ceil.kind_of?(Integer).should == true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns a BigDecimal, if n is specified" do
|
36
|
+
@pos_int.ceil(2).kind_of?(BigDecimal).should == true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the smallest integer greater or equal to self, if n is unspecified" do
|
41
|
+
@pos_int.ceil.should == @pos_int
|
42
|
+
@neg_int.ceil.should == @neg_int
|
43
|
+
@pos_frac.ceil.should == BigDecimal("1")
|
44
|
+
@neg_frac.ceil.should == @zero
|
45
|
+
@zero.ceil.should == 0
|
46
|
+
@zero_pos.ceil.should == @zero_pos
|
47
|
+
@zero_neg.ceil.should == @zero_neg
|
48
|
+
|
49
|
+
|
50
|
+
BigDecimal('2.3').ceil.should == 3
|
51
|
+
BigDecimal('2.5').ceil.should == 3
|
52
|
+
BigDecimal('2.9999').ceil.should == 3
|
53
|
+
BigDecimal('-2.3').ceil.should == -2
|
54
|
+
BigDecimal('-2.5').ceil.should == -2
|
55
|
+
BigDecimal('-2.9999').ceil.should == -2
|
56
|
+
end
|
57
|
+
|
58
|
+
ruby_version_is "" ... "1.9" do
|
59
|
+
it "returns the same value, if self is special value" do
|
60
|
+
@infinity.ceil.should == @infinity
|
61
|
+
@infinity_neg.ceil.should == @infinity_neg
|
62
|
+
@nan.ceil.nan?.should == true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
ruby_version_is "1.9" do
|
67
|
+
it "raise exception, if self is special value" do
|
68
|
+
lambda { @infinity.ceil }.should raise_error(FloatDomainError)
|
69
|
+
lambda { @infinity_neg.ceil }.should raise_error(FloatDomainError)
|
70
|
+
lambda { @nan.ceil }.should raise_error(FloatDomainError)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns n digits right of the decimal point if given n > 0" do
|
75
|
+
@mixed.ceil(1).should == BigDecimal("1.3")
|
76
|
+
@mixed.ceil(5).should == BigDecimal("1.23457")
|
77
|
+
|
78
|
+
BigDecimal("-0.03").ceil(1).should == BigDecimal("0")
|
79
|
+
BigDecimal("0.03").ceil(1).should == BigDecimal("0.1")
|
80
|
+
|
81
|
+
BigDecimal("23.45").ceil(0).should == BigDecimal('24')
|
82
|
+
BigDecimal("23.45").ceil(1).should == BigDecimal('23.5')
|
83
|
+
BigDecimal("23.45").ceil(2).should == BigDecimal('23.45')
|
84
|
+
|
85
|
+
BigDecimal("-23.45").ceil(0).should == BigDecimal('-23')
|
86
|
+
BigDecimal("-23.45").ceil(1).should == BigDecimal('-23.4')
|
87
|
+
BigDecimal("-23.45").ceil(2).should == BigDecimal('-23.45')
|
88
|
+
|
89
|
+
BigDecimal("2E-10").ceil(0).should == @one
|
90
|
+
BigDecimal("2E-10").ceil(9).should == BigDecimal('1E-9')
|
91
|
+
BigDecimal("2E-10").ceil(10).should == BigDecimal('2E-10')
|
92
|
+
BigDecimal("2E-10").ceil(11).should == BigDecimal('2E-10')
|
93
|
+
|
94
|
+
(1..10).each do |n|
|
95
|
+
# 0.4, 0.34, 0.334, etc.
|
96
|
+
(@one.div(@three,20)).ceil(n).should == BigDecimal("0.#{'3'*(n-1)}4")
|
97
|
+
# 1.4, 1.34, 1.334, etc.
|
98
|
+
(@four.div(@three,20)).ceil(n).should == BigDecimal("1.#{'3'*(n-1)}4")
|
99
|
+
(BigDecimal('31').div(@three,20)).ceil(n).should == BigDecimal("10.#{'3'*(n-1)}4")
|
100
|
+
end
|
101
|
+
(1..10).each do |n|
|
102
|
+
# -0.4, -0.34, -0.334, etc.
|
103
|
+
(-@one.div(@three,20)).ceil(n).should == BigDecimal("-0.#{'3'* n}")
|
104
|
+
end
|
105
|
+
(1..10).each do |n|
|
106
|
+
(@three.div(@one,20)).ceil(n).should == @three
|
107
|
+
end
|
108
|
+
(1..10).each do |n|
|
109
|
+
(-@three.div(@one,20)).ceil(n).should == -@three
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it "sets n digits left of the decimal point to 0, if given n < 0" do
|
114
|
+
BigDecimal("13345.234").ceil(-2).should == BigDecimal("13400.0")
|
115
|
+
@mixed_big.ceil(-99).should == BigDecimal("0.13E101")
|
116
|
+
@mixed_big.ceil(-100).should == BigDecimal("0.2E101")
|
117
|
+
@mixed_big.ceil(-95).should == BigDecimal("0.123457E101")
|
118
|
+
BigDecimal("1E10").ceil(-30).should == BigDecimal('1E30')
|
119
|
+
BigDecimal("-1E10").ceil(-30).should == @zero
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
data/spec/coerce_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
describe "BigDecimal#coerce" do
|
4
|
+
|
5
|
+
it "returns [other, self] both as BigDecimal" do
|
6
|
+
one = BigDecimal("1.0")
|
7
|
+
five_point_28 = BigDecimal("5.28")
|
8
|
+
zero_minus = BigDecimal("-0.0")
|
9
|
+
some_value = 32434234234234234234
|
10
|
+
|
11
|
+
BigDecimal("1.2").coerce(1).should == [one, BigDecimal("1.2")]
|
12
|
+
five_point_28.coerce(1.0).should == [one, BigDecimal("5.28")]
|
13
|
+
one.coerce(one).should == [one, one]
|
14
|
+
one.coerce(2.5).should == [2.5, one]
|
15
|
+
BigDecimal("1").coerce(3.14).should == [3.14, one]
|
16
|
+
a, b = zero_minus.coerce(some_value)
|
17
|
+
a.should == BigDecimal(some_value.to_s)
|
18
|
+
b.should == zero_minus
|
19
|
+
a, b = one.coerce(some_value)
|
20
|
+
a.should == BigDecimal(some_value.to_s)
|
21
|
+
b.to_f.should be_close(1.0, TOLERANCE) # can we take out the to_f once BigDecimal#- is implemented?
|
22
|
+
b.should == one
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
describe "BigDecimal#<=>" do
|
4
|
+
before(:each) do
|
5
|
+
@zero = BigDecimal("0")
|
6
|
+
@zero_pos = BigDecimal("+0")
|
7
|
+
@zero_neg = BigDecimal("-0")
|
8
|
+
@mixed = BigDecimal("1.23456789")
|
9
|
+
@mixed_big = BigDecimal("1.23456789E100")
|
10
|
+
@pos_int = BigDecimal("2E5555")
|
11
|
+
@neg_int = BigDecimal("-2E5555")
|
12
|
+
@pos_frac = BigDecimal("2E-9999")
|
13
|
+
@neg_frac = BigDecimal("-2E-9999")
|
14
|
+
|
15
|
+
@int_mock = mock('123')
|
16
|
+
class << @int_mock
|
17
|
+
def coerce(other)
|
18
|
+
return [other, BigDecimal('123')]
|
19
|
+
end
|
20
|
+
def >= (other)
|
21
|
+
BigDecimal('123') >= other
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
@values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac,
|
26
|
+
-2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1,
|
27
|
+
@zero , 1, 2, 10, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg]
|
28
|
+
|
29
|
+
@infinity = BigDecimal("Infinity")
|
30
|
+
@infinity_neg = BigDecimal("-Infinity")
|
31
|
+
@nan = BigDecimal("NaN")
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
it "returns 0 if a == b" do
|
36
|
+
(@pos_int <=> @pos_int).should == 0
|
37
|
+
(@neg_int <=> @neg_int).should == 0
|
38
|
+
(@pos_frac <=> @pos_frac).should == 0
|
39
|
+
(@neg_frac <=> @neg_frac).should == 0
|
40
|
+
(@zero <=> @zero).should == 0
|
41
|
+
(@infinity <=> @infinity).should == 0
|
42
|
+
(@infinity_neg <=> @infinity_neg).should == 0
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns 1 if a > b" do
|
46
|
+
(@pos_int <=> @neg_int).should == 1
|
47
|
+
(@pos_frac <=> @neg_frac).should == 1
|
48
|
+
(@pos_frac <=> @zero).should == 1
|
49
|
+
@values.each { |val|
|
50
|
+
(@infinity <=> val).should == 1
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns -1 if a < b" do
|
55
|
+
(@zero <=> @pos_frac).should == -1
|
56
|
+
(@neg_int <=> @pos_frac).should == -1
|
57
|
+
(@pos_frac <=> @pos_int).should == -1
|
58
|
+
@values.each { |val|
|
59
|
+
(@infinity_neg <=> val).should == -1
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns nil if NaN is involved" do
|
64
|
+
@values += [@infinity, @infinity_neg, @nan]
|
65
|
+
@values << nil
|
66
|
+
@values << Object.new
|
67
|
+
@values.each { |val|
|
68
|
+
(@nan <=> val).should == nil
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns nil if the argument is nil" do
|
73
|
+
(@zero <=> nil).should == nil
|
74
|
+
(@infinity <=> nil).should == nil
|
75
|
+
(@infinity_neg <=> nil).should == nil
|
76
|
+
(@mixed <=> nil).should == nil
|
77
|
+
(@pos_int <=> nil).should == nil
|
78
|
+
(@neg_frac <=> nil).should == nil
|
79
|
+
end
|
80
|
+
end
|
data/spec/div_spec.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.expand_path('../shared/quo', __FILE__)
|
2
|
+
require 'bigdecimal'
|
3
|
+
|
4
|
+
describe "BigDecimal#div with precision set to 0" do
|
5
|
+
# TODO: figure out if there is a better way to do these
|
6
|
+
# shared specs rather than sending [0]. See other specs
|
7
|
+
# that share :bigdecimal_quo.
|
8
|
+
it_behaves_like :bigdecimal_quo, :div, [0]
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "BigDecimal#div" do
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@one = BigDecimal("1")
|
15
|
+
@zero = BigDecimal("0")
|
16
|
+
@zero_plus = BigDecimal("+0")
|
17
|
+
@zero_minus = BigDecimal("-0")
|
18
|
+
@two = BigDecimal("2")
|
19
|
+
@three = BigDecimal("3")
|
20
|
+
@nan = BigDecimal("NaN")
|
21
|
+
@infinity = BigDecimal("Infinity")
|
22
|
+
@infinity_minus = BigDecimal("-Infinity")
|
23
|
+
@one_minus = BigDecimal("-1")
|
24
|
+
@frac_1 = BigDecimal("1E-99999")
|
25
|
+
@frac_2 = BigDecimal("0.9E-99999")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns a / b with optional precision" do
|
29
|
+
@two.div(@one).should == @two
|
30
|
+
@one.div(@two).should == @zero
|
31
|
+
# ^^ is this really intended for a class with arbitrary precision?
|
32
|
+
@one.div(@two, 1).should == BigDecimal("0.5")
|
33
|
+
@one.div(@one_minus).should == @one_minus
|
34
|
+
@one_minus.div(@one_minus).should == @one
|
35
|
+
@frac_2.div(@frac_1, 1).should == BigDecimal("0.9")
|
36
|
+
@frac_1.div(@frac_1).should == @one
|
37
|
+
|
38
|
+
res = "0." + "3" * 1000
|
39
|
+
(1..100).each { |idx|
|
40
|
+
@one.div(@three, idx).to_s("F").should == "0." + res[2, idx]
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
ruby_version_is "" ... "1.9" do
|
45
|
+
it "returns NaN if NaN is involved" do
|
46
|
+
@one.div(@nan).nan?.should == true
|
47
|
+
@nan.div(@one).nan?.should == true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns NaN if divided by Infinity and no precision given" do
|
51
|
+
@zero.div(@infinity).nan?.should == true
|
52
|
+
@frac_2.div(@infinity).nan?.should == true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ruby_version_is "1.9" do
|
57
|
+
it "raises FloatDomainError if NaN is involved" do
|
58
|
+
lambda { @one.div(@nan) }.should raise_error(FloatDomainError)
|
59
|
+
lambda { @nan.div(@one) }.should raise_error(FloatDomainError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns 0 if divided by Infinity and no precision given" do
|
63
|
+
@zero.div(@infinity).should == 0
|
64
|
+
@frac_2.div(@infinity).should == 0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns 0 if divided by Infinity with given precision" do
|
69
|
+
@zero.div(@infinity, 0).should == 0
|
70
|
+
@frac_2.div(@infinity, 1).should == 0
|
71
|
+
@zero.div(@infinity, 100000).should == 0
|
72
|
+
@frac_2.div(@infinity, 100000).should == 0
|
73
|
+
end
|
74
|
+
|
75
|
+
ruby_version_is "" ... "1.9" do
|
76
|
+
it "returns NaN if divided by zero and no precision given" do
|
77
|
+
@one.div(@zero).nan?.should == true
|
78
|
+
@one.div(@zero_plus).nan?.should == true
|
79
|
+
@one.div(@zero_minus).nan?.should == true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "returns NaN if zero is divided by zero" do
|
83
|
+
@zero.div(@zero).nan?.should == true
|
84
|
+
@zero_minus.div(@zero_plus).nan?.should == true
|
85
|
+
@zero_plus.div(@zero_minus).nan?.should == true
|
86
|
+
|
87
|
+
@zero.div(@zero, 0).nan?.should == true
|
88
|
+
@zero_minus.div(@zero_plus, 0).nan?.should == true
|
89
|
+
@zero_plus.div(@zero_minus, 0).nan?.should == true
|
90
|
+
|
91
|
+
@zero.div(@zero, 10).nan?.should == true
|
92
|
+
@zero_minus.div(@zero_plus, 10).nan?.should == true
|
93
|
+
@zero_plus.div(@zero_minus, 10).nan?.should == true
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns NaN if (+|-) Infinity divided by 1 and no precision given" do
|
97
|
+
@infinity_minus.div(@one).nan?.should == true
|
98
|
+
@infinity.div(@one).nan?.should == true
|
99
|
+
@infinity_minus.div(@one_minus).nan?.should == true
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
ruby_version_is "1.9" do
|
104
|
+
it "raises ZeroDivisionError if divided by zero and no precision given" do
|
105
|
+
lambda { @one.div(@zero) }.should raise_error(ZeroDivisionError)
|
106
|
+
lambda { @one.div(@zero_plus) }.should raise_error(ZeroDivisionError)
|
107
|
+
lambda { @one.div(@zero_minus) }.should raise_error(ZeroDivisionError)
|
108
|
+
|
109
|
+
lambda { @zero.div(@zero) }.should raise_error(ZeroDivisionError)
|
110
|
+
lambda { @zero_minus.div(@zero_plus) }.should raise_error(ZeroDivisionError)
|
111
|
+
lambda { @zero_plus.div(@zero_minus) }.should raise_error(ZeroDivisionError)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "returns NaN if zero is divided by zero" do
|
115
|
+
@zero.div(@zero, 0).nan?.should == true
|
116
|
+
@zero_minus.div(@zero_plus, 0).nan?.should == true
|
117
|
+
@zero_plus.div(@zero_minus, 0).nan?.should == true
|
118
|
+
|
119
|
+
@zero.div(@zero, 10).nan?.should == true
|
120
|
+
@zero_minus.div(@zero_plus, 10).nan?.should == true
|
121
|
+
@zero_plus.div(@zero_minus, 10).nan?.should == true
|
122
|
+
end
|
123
|
+
|
124
|
+
it "raises FloatDomainError if (+|-) Infinity divided by 1 and no precision given" do
|
125
|
+
lambda { @infinity_minus.div(@one) }.should raise_error(FloatDomainError)
|
126
|
+
lambda { @infinity.div(@one) }.should raise_error(FloatDomainError)
|
127
|
+
lambda { @infinity_minus.div(@one_minus) }.should raise_error(FloatDomainError)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "returns (+|-)Infinity if (+|-)Infinity by 1 and precision given" do
|
132
|
+
@infinity_minus.div(@one, 0).should == @infinity_minus
|
133
|
+
@infinity.div(@one, 0).should == @infinity
|
134
|
+
@infinity_minus.div(@one_minus, 0).should == @infinity
|
135
|
+
end
|
136
|
+
|
137
|
+
it "returns NaN if Infinity / ((+|-) Infinity)" do
|
138
|
+
@infinity.div(@infinity_minus, 100000).nan?.should == true
|
139
|
+
@infinity_minus.div(@infinity, 1).nan?.should == true
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
end
|
data/spec/divide_spec.rb
ADDED
data/spec/divmod_spec.rb
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
require File.expand_path('../shared/modulo', __FILE__)
|
2
|
+
require 'bigdecimal'
|
3
|
+
|
4
|
+
module DivmodSpecs
|
5
|
+
def self.check_both_nan(array)
|
6
|
+
array.length.should == 2
|
7
|
+
array[0].nan?.should == true
|
8
|
+
array[1].nan?.should == true
|
9
|
+
end
|
10
|
+
def self.check_both_bigdecimal(array)
|
11
|
+
array.length.should == 2
|
12
|
+
array[0].kind_of?(BigDecimal).should == true
|
13
|
+
array[1].kind_of?(BigDecimal).should == true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# TODO: figure out a way to do the shared specs with helpers instead
|
18
|
+
# of spec'ing a method that does not really exist
|
19
|
+
describe "BigDecimal#mod_part_of_divmod" do
|
20
|
+
# BigDecimal#divmod[1] behaves exactly like #modulo
|
21
|
+
before :all do
|
22
|
+
class BigDecimal
|
23
|
+
def mod_part_of_divmod(arg)
|
24
|
+
divmod(arg)[1]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
after :all do
|
30
|
+
class BigDecimal
|
31
|
+
undef mod_part_of_divmod
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it_behaves_like :bigdecimal_modulo, :mod_part_of_divmod
|
36
|
+
|
37
|
+
ruby_version_is "" ... "1.9" do
|
38
|
+
it "does NOT raise ZeroDivisionError if other is zero" do
|
39
|
+
bd6543 = BigDecimal.new("6543.21")
|
40
|
+
bd5667 = BigDecimal.new("5667.19")
|
41
|
+
a = BigDecimal("1.0000000000000000000000000000000000000000005")
|
42
|
+
b = BigDecimal("1.00000000000000000000000000000000000000000005")
|
43
|
+
|
44
|
+
bd5667.send(@method, 0).nan?.should == true
|
45
|
+
bd5667.send(@method, BigDecimal("0")).nan?.should == true
|
46
|
+
@zero.send(@method, @zero).nan?.should == true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
ruby_version_is "1.9" do
|
51
|
+
it "raises ZeroDivisionError if other is zero" do
|
52
|
+
bd6543 = BigDecimal.new("6543.21")
|
53
|
+
bd5667 = BigDecimal.new("5667.19")
|
54
|
+
a = BigDecimal("1.0000000000000000000000000000000000000000005")
|
55
|
+
b = BigDecimal("1.00000000000000000000000000000000000000000005")
|
56
|
+
|
57
|
+
lambda { bd5667.send(@method, 0) }.should raise_error(ZeroDivisionError)
|
58
|
+
lambda { bd5667.send(@method, BigDecimal("0")) }.should raise_error(ZeroDivisionError)
|
59
|
+
lambda { @zero.send(@method, @zero) }.should raise_error(ZeroDivisionError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "BigDecimal#divmod" do
|
65
|
+
|
66
|
+
before(:each) do
|
67
|
+
@a = BigDecimal("42.00000000000000000001")
|
68
|
+
|
69
|
+
@zero = BigDecimal("0")
|
70
|
+
@zero_pos = BigDecimal("+0")
|
71
|
+
@zero_neg = BigDecimal("-0")
|
72
|
+
|
73
|
+
@one = BigDecimal("1")
|
74
|
+
@mixed = BigDecimal("1.23456789")
|
75
|
+
@pos_int = BigDecimal("2E5555")
|
76
|
+
@neg_int = BigDecimal("-2E5555")
|
77
|
+
@pos_frac = BigDecimal("2E-9999")
|
78
|
+
@neg_frac = BigDecimal("-2E-9999")
|
79
|
+
@nan = BigDecimal("NaN")
|
80
|
+
@infinity = BigDecimal("Infinity")
|
81
|
+
@infinity_minus = BigDecimal("-Infinity")
|
82
|
+
@one_minus = BigDecimal("-1")
|
83
|
+
@frac_1 = BigDecimal("1E-99999")
|
84
|
+
@frac_2 = BigDecimal("0.9E-99999")
|
85
|
+
|
86
|
+
@special_vals = [@infinity, @infinity_minus, @nan]
|
87
|
+
@regular_vals = [
|
88
|
+
@one, @mixed, @pos_int, @neg_int, @pos_frac,
|
89
|
+
@neg_frac, @one_minus, @frac_1, @frac_2]
|
90
|
+
@zeroes = [@zero, @zero_pos, @zero_neg]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "divides value, returns an array" do
|
94
|
+
res = @a.divmod(5)
|
95
|
+
res.kind_of?(Array).should == true
|
96
|
+
end
|
97
|
+
|
98
|
+
it "array contains quotient and modulus as BigDecimal" do
|
99
|
+
res = @a.divmod(5)
|
100
|
+
DivmodSpecs::check_both_bigdecimal(res)
|
101
|
+
res[0].should == BigDecimal('0.8E1')
|
102
|
+
res[1].should == BigDecimal('2.00000000000000000001')
|
103
|
+
|
104
|
+
BigDecimal('1').divmod(BigDecimal('2')).should == [0, 1]
|
105
|
+
BigDecimal('2').divmod(BigDecimal('1')).should == [2, 0]
|
106
|
+
|
107
|
+
BigDecimal('1').divmod(BigDecimal('-2')).should == [-1, -1]
|
108
|
+
BigDecimal('2').divmod(BigDecimal('-1')).should == [-2, 0]
|
109
|
+
|
110
|
+
BigDecimal('-1').divmod(BigDecimal('2')).should == [-1, 1]
|
111
|
+
BigDecimal('-2').divmod(BigDecimal('1')).should == [-2, 0]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "Can be reversed with * and +" do
|
115
|
+
# Example taken from BigDecimal documentation
|
116
|
+
a = BigDecimal.new("42")
|
117
|
+
b = BigDecimal.new("9")
|
118
|
+
q, m = a.divmod(b)
|
119
|
+
c = q * b + m
|
120
|
+
a.should == c
|
121
|
+
|
122
|
+
values = [@one, @one_minus, BigDecimal('2'), BigDecimal('-2'),
|
123
|
+
BigDecimal('5'), BigDecimal('-5'), BigDecimal('10'), BigDecimal('-10'),
|
124
|
+
BigDecimal('20'), BigDecimal('-20'), BigDecimal('100'), BigDecimal('-100'),
|
125
|
+
BigDecimal('1.23456789E10'), BigDecimal('-1.23456789E10')
|
126
|
+
]
|
127
|
+
|
128
|
+
# TODO: file MRI bug:
|
129
|
+
# BigDecimal('1').divmod(BigDecimal('3E-9'))[0] #=> 0.3E9,
|
130
|
+
# but really should be 0.333333333E9
|
131
|
+
ruby_bug "#206", "1.8" do #MRI's precision is very low in some cases
|
132
|
+
values << BigDecimal('1E-10')
|
133
|
+
values << BigDecimal('-1E-10')
|
134
|
+
values << BigDecimal('2E55')
|
135
|
+
values << BigDecimal('-2E55')
|
136
|
+
values << BigDecimal('2E-5555')
|
137
|
+
values << BigDecimal('-2E-5555')
|
138
|
+
|
139
|
+
|
140
|
+
values_and_zeroes = values + @zeroes
|
141
|
+
values_and_zeroes.each do |val1|
|
142
|
+
values.each do |val2|
|
143
|
+
res = val1.divmod(val2)
|
144
|
+
DivmodSpecs::check_both_bigdecimal(res)
|
145
|
+
res[0].should == ((val1/val2).floor)
|
146
|
+
res[1].should == (val1 - res[0] * val2)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
ruby_version_is "" ... "1.9" do
|
153
|
+
it "properly handles special values" do
|
154
|
+
values = @special_vals + @zeroes
|
155
|
+
values.each do |val1|
|
156
|
+
values.each do |val2|
|
157
|
+
DivmodSpecs::check_both_nan(val1.divmod(val2))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
@special_vals.each do |val1|
|
162
|
+
@regular_vals.each do |val2|
|
163
|
+
DivmodSpecs::check_both_nan(val1.divmod(val2))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
@regular_vals.each do |val1|
|
168
|
+
@special_vals.each do |val2|
|
169
|
+
DivmodSpecs::check_both_nan(val1.divmod(val2))
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it "returns an array of two NaNs if the argument is zero" do
|
175
|
+
values = @regular_vals + @special_vals
|
176
|
+
values.each do |val1|
|
177
|
+
@zeroes.each do |val2|
|
178
|
+
DivmodSpecs::check_both_nan(val1.divmod(val2))
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
ruby_version_is "1.9" do
|
185
|
+
it "returns an array of two NaNs if NaN is involved" do
|
186
|
+
(@special_vals + @regular_vals + @zeroes).each do |val|
|
187
|
+
DivmodSpecs::check_both_nan(val.divmod(@nan))
|
188
|
+
DivmodSpecs::check_both_nan(@nan.divmod(val))
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it "raises ZeroDivisionError if the divisor is zero" do
|
193
|
+
(@special_vals + @regular_vals + @zeroes - [@nan]).each do |val|
|
194
|
+
@zeroes.each do |zero|
|
195
|
+
lambda { val.divmod(zero) }.should raise_error(ZeroDivisionError)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
it "returns an array of Infinity and NaN if the dividend is Infinity" do
|
201
|
+
@regular_vals.each do |val|
|
202
|
+
array = @infinity.divmod(val)
|
203
|
+
array.length.should == 2
|
204
|
+
array[0].infinite?.should == (val > 0 ? 1 : -1)
|
205
|
+
array[1].nan?.should == true
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
it "returns an array of zero and the dividend if the divisor is Infinity" do
|
210
|
+
@regular_vals.each do |val|
|
211
|
+
array = val.divmod(@infinity)
|
212
|
+
array.length.should == 2
|
213
|
+
array[0].should == @zero
|
214
|
+
array[1].should == val
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
it "returns an array of two zero if the diviend is zero" do
|
219
|
+
@zeroes.each do |zero|
|
220
|
+
@regular_vals.each do |val|
|
221
|
+
zero.divmod(val).should == [@zero, @zero]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it "raises TypeError if the argument cannot be coerced to BigDecimal" do
|
228
|
+
lambda {
|
229
|
+
@one.divmod('1')
|
230
|
+
}.should raise_error(TypeError)
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|