File: test_big_decimal.rb

package info (click to toggle)
jruby 1.5.6-9
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 45,088 kB
  • ctags: 77,093
  • sloc: ruby: 398,491; java: 170,202; yacc: 3,782; xml: 2,529; sh: 299; tcl: 40; makefile: 35; ansic: 23
file content (242 lines) | stat: -rw-r--r-- 9,563 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
require 'test/unit'
require 'bigdecimal'

class TestBigDecimal < Test::Unit::TestCase

  def test_bad_to_s_format_strings
    bd = BigDecimal.new("1")
    assert_equal("0.1E1", bd.to_s)
    assert_equal("+0.1E1", bd.to_s("+-2"))
    assert_equal("0.23", BigDecimal.new("0.23").to_s("F"))
  end

  def test_no_singleton_methods_on_bigdecimal
    num = BigDecimal.new("0.001")
    assert_raise(TypeError) { class << num ; def amethod ; end ; end }
    assert_raise(TypeError) { def num.amethod ; end }
  end
  
  def test_can_instantiate_big_decimal
    assert_nothing_raised {BigDecimal.new("4")}
    assert_nothing_raised {BigDecimal.new("3.14159")}
  end
  
  def test_can_implicitly_instantiate_big_decimal
    # JRUBY-153 issues
    assert_nothing_raised {BigDecimal("4")}
    assert_nothing_raised {BigDecimal("3.14159")}
  end

  def test_reject_arguments_not_responding_to_to_str
    assert_raise(TypeError) { BigDecimal.new(4) }
    assert_raise(TypeError) { BigDecimal.new(3.14159) }
    assert_raise(TypeError) { BigDecimal(4) }
    assert_raise(TypeError) { BigDecimal(3.14159) }
  end

  def test_alphabetic_args_return_zero
    assert_equal( BigDecimal("0.0"), BigDecimal("XXX"),
                  'Big Decimal objects instanitiated with a value that starts
                  with a letter should have a value of 0.0' )
  end
  
  class X
    def to_str; "3.14159" end
  end
  
  def test_can_accept_arbitrary_objects_as_arguments
    # as log as the object has a #to_str method...
    x = X.new
    assert_nothing_raised { BigDecimal.new(x) }
    assert_nothing_raised { BigDecimal(x) }
  end
  
  require "bigdecimal/newton"
  include Newton
  
  class Function
    def initialize()
      @zero = BigDecimal::new("0.0")
      @one  = BigDecimal::new("1.0")
      @two  = BigDecimal::new("2.0")
      @ten  = BigDecimal::new("10.0")
      @eps  = BigDecimal::new("1.0e-16")
    end
    def zero;@zero;end
    def one ;@one ;end
    def two ;@two ;end
    def ten ;@ten ;end
    def eps ;@eps ;end
    def values(x) # <= defines functions solved
      f = []
      f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0
      f2 = x[0] - x[1]                  # f2 = x    - y        => 0
      f <<= f1
      f <<= f2
      f
    end
  end
  
  def test_newton_extension
    f = BigDecimal::limit(100)
    f = Function.new
    x = [f.zero,f.zero]      # Initial values
    n = nlsolve(f,x)
    expected = [BigDecimal('0.1000000000262923315461642086010446338567975310185638386446002778855192224707966221794469725479649528E1'),
                BigDecimal('0.1000000000262923315461642086010446338567975310185638386446002778855192224707966221794469725479649528E1')]
    assert_equal expected, x
  end
  
  require "bigdecimal/math.rb"
  include BigMath
  
  def test_math_extension
    expected = BigDecimal('0.31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066453462141417033006060218E1')
    # this test fails under C Ruby
    # ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.9.1]
    assert_equal expected, PI(100)

    zero= BigDecimal("0")
    one = BigDecimal("1")
    two = BigDecimal("2")
    three = BigDecimal("3")
    
    assert_equal one * 1, one
    assert_equal one / 1, one
    assert_equal one + 1, two
    assert_equal one - 1, zero

    assert_equal zero, one % 1
    assert_equal one, three % two
    assert_equal BigDecimal("0.2"), BigDecimal("2.2") % two
    assert_equal BigDecimal("0.003"), BigDecimal("15.993") % BigDecimal("15.99")
    
    assert_equal 1*one, one
    assert_equal 1/one, one
    assert_equal 1+one, BigDecimal("2")
    assert_equal 1-one, BigDecimal("0")
    
    assert_equal one * 1.0, 1.0
    assert_equal one / 1.0, 1.0
    assert_equal one + 1.0, 2.0
    assert_equal one - 1.0, 0.0
    
    assert_equal 1.0*one, 1.0
    assert_equal 1.0/one, 1.0
    assert_equal 1.0+one, 2.0
    assert_equal 1.0-one, 0.0
    
    assert_equal("1.0", BigDecimal.new('1.0').to_s('F'))
    assert_equal("0.0", BigDecimal.new('0.0').to_s)
    
    assert_equal(BigDecimal("2"), BigDecimal("1.5").round)
    assert_equal(BigDecimal("15"), BigDecimal("15").round)
    assert_equal(BigDecimal("20"), BigDecimal("15").round(-1))
    assert_equal(BigDecimal("0"), BigDecimal("15").round(-2))
    assert_equal(BigDecimal("-10"), BigDecimal("-15").round(-1, BigDecimal::ROUND_CEILING))
    assert_equal(BigDecimal("10"), BigDecimal("15").round(-1, BigDecimal::ROUND_HALF_DOWN))
    assert_equal(BigDecimal("20"), BigDecimal("25").round(-1, BigDecimal::ROUND_HALF_EVEN))
    assert_equal(BigDecimal("15.99"), BigDecimal("15.993").round(2))
    
    assert_equal(BigDecimal("1"), BigDecimal("1.8").round(0, BigDecimal::ROUND_DOWN))
    assert_equal(BigDecimal("2"), BigDecimal("1.2").round(0, BigDecimal::ROUND_UP))
    assert_equal(BigDecimal("-1"), BigDecimal("-1.5").round(0, BigDecimal::ROUND_CEILING))
    assert_equal(BigDecimal("-2"), BigDecimal("-1.5").round(0, BigDecimal::ROUND_FLOOR))
    assert_equal(BigDecimal("-2"), BigDecimal("-1.5").round(0, BigDecimal::ROUND_FLOOR))
    assert_equal(BigDecimal("1"), BigDecimal("1.5").round(0, BigDecimal::ROUND_HALF_DOWN))
    assert_equal(BigDecimal("2"), BigDecimal("1.5").round(0, BigDecimal::ROUND_HALF_EVEN))
    assert_equal(BigDecimal("2"), BigDecimal("2.5").round(0, BigDecimal::ROUND_HALF_EVEN))
  end
    
  def test_big_decimal_power
    n = BigDecimal("10")
    assert_equal(n.power(0), BigDecimal("1"))
    assert_equal(n.power(1), n)
    assert_equal(n.power(2), BigDecimal("100"))
    assert_equal(n.power(-1), BigDecimal("0.1"))
    assert_raises(TypeError) { n.power(1.1) }
  end

  def test_big_decimal_mode
    # Accept valid arguments to #mode
    assert BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW)
    assert BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW,true)
    assert BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW,false)
    
    # Reject invalid arguments to #mode
    assert_raises(TypeError) { BigDecimal.mode(true) } # first argument must be a Fixnum
    assert_raises(TypeError) { BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, 1) } # second argument must be [true|false]
    assert_raises(TypeError) { BigDecimal.mode(512) } # first argument must be == 256, or return non-zero when AND-ed with 255
    
    # exception mode defaults to 0
    assert_equal 0, BigDecimal.mode(1) # value of first argument doesn't matter when retrieving the current exception mode, as long as it's a Fixnum <= 255
    
    # set and clear a single exception mode
    assert_equal BigDecimal::EXCEPTION_INFINITY, BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
    assert_equal 0, BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
    assert_equal BigDecimal::EXCEPTION_NaN, BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true)
    assert_equal 0, BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
    
    # set a composition of exception modes separately, make sure the final result is the composited value
    BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
    BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true)
    assert_equal BigDecimal::EXCEPTION_INFINITY | BigDecimal::EXCEPTION_NaN, BigDecimal.mode(1)
    
    # reset the exception mode to 0 for the following tests
    BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
    BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
    
    # set a composition of exception modes with one call and retrieve it using the retrieval idiom
    # note: this is to check compatibility with MRI, which currently sets only the last mode
    # it checks for
    BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY | BigDecimal::EXCEPTION_NaN, true)
    assert_equal BigDecimal::EXCEPTION_NaN, BigDecimal.mode(1)
    
    # rounding mode defaults to BigDecimal::ROUND_HALF_UP
    assert_equal BigDecimal::ROUND_HALF_UP, BigDecimal.mode(BigDecimal::ROUND_MODE)
    
    # make sure each setting complete replaces any previous setting
    [BigDecimal::ROUND_UP, BigDecimal::ROUND_DOWN, BigDecimal::ROUND_CEILING, BigDecimal::ROUND_FLOOR,
     BigDecimal::ROUND_HALF_UP, BigDecimal::ROUND_HALF_DOWN, BigDecimal::ROUND_HALF_EVEN].each do |mode|
    	assert_equal mode, BigDecimal.mode(BigDecimal::ROUND_MODE, mode)
    end
    
    # reset rounding mode to 0 for following tests
    BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
    
    assert_raises(TypeError) { BigDecimal.mode(BigDecimal::ROUND_MODE, true) } # second argument must be a Fixnum
    assert_raises(TypeError) { BigDecimal.mode(BigDecimal::ROUND_MODE, 8) } # any Fixnum >= 8 should trigger this error, as the valid rounding modes are currently [0..6]
  end

  def test_marshaling
    f = 123.456
    bd = BigDecimal.new(f.to_s)
    bd_serialized = Marshal.dump(bd)
    assert_equal f, Marshal.restore(bd_serialized).to_f
  end
  
  #JRUBY-2272
  def test_marshal_regression
    assert_equal BigDecimal('0.0'), Marshal.load(Marshal.dump(BigDecimal.new('0.0')))
  end

  def test_large_bigdecimal_to_f
    pos_inf = BigDecimal.new("5E69999999").to_f
    assert pos_inf.infinite?
    assert pos_inf > 0
    assert BigDecimal.new("0E69999999").to_f < Float::EPSILON
    neg_inf = BigDecimal.new("-5E69999999").to_f
    assert neg_inf.infinite?
    assert neg_inf < 0
    assert BigDecimal.new("5E-69999999").to_f < Float::EPSILON
  end
  
  #JRUBY-3818
  def test_decimal_format
    require 'java'
    format = java.text.DecimalFormat.new("#,##0.00")
    value = java.math.BigDecimal.new("10")
    assert format.format(value) == "10.00"
  end

end