flt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/History.txt +41 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +42 -0
  4. data/README.txt +557 -0
  5. data/Rakefile +34 -0
  6. data/lib/flt.rb +9 -0
  7. data/lib/flt/b.rb +6 -0
  8. data/lib/flt/bigdecimal.rb +151 -0
  9. data/lib/flt/bin_num.rb +250 -0
  10. data/lib/flt/d.rb +6 -0
  11. data/lib/flt/dec_num.rb +1239 -0
  12. data/lib/flt/float.rb +458 -0
  13. data/lib/flt/math.rb +66 -0
  14. data/lib/flt/num.rb +4211 -0
  15. data/lib/flt/sugar.rb +102 -0
  16. data/lib/flt/support.rb +1335 -0
  17. data/lib/flt/tolerance.rb +561 -0
  18. data/lib/flt/tolerance/sugar.rb +77 -0
  19. data/lib/flt/version.rb +9 -0
  20. data/setup.rb +1585 -0
  21. data/tasks/ann.rake +80 -0
  22. data/tasks/bones.rake +20 -0
  23. data/tasks/gem.rake +192 -0
  24. data/tasks/git.rake +40 -0
  25. data/tasks/manifest.rake +48 -0
  26. data/tasks/notes.rake +27 -0
  27. data/tasks/post_load.rake +39 -0
  28. data/tasks/rdoc.rake +50 -0
  29. data/tasks/rubyforge.rake +55 -0
  30. data/tasks/setup.rb +279 -0
  31. data/tasks/spec.rake +54 -0
  32. data/tasks/svn.rake +47 -0
  33. data/tasks/test.rake +40 -0
  34. data/test/all_tests.rb +23 -0
  35. data/test/helper.rb +101 -0
  36. data/test/reader.rb +68 -0
  37. data/test/test_basic.rb +396 -0
  38. data/test/test_bin.rb +245 -0
  39. data/test/test_bin_arithmetic.rb +94 -0
  40. data/test/test_binfloat_conversion.rb +24 -0
  41. data/test/test_coercion.rb +22 -0
  42. data/test/test_comparisons.rb +53 -0
  43. data/test/test_dectest.rb +216 -0
  44. data/test/test_define_conversions.rb +144 -0
  45. data/test/test_epsilon.rb +55 -0
  46. data/test/test_exact.rb +147 -0
  47. data/test/test_flags.rb +34 -0
  48. data/test/test_multithreading.rb +32 -0
  49. data/test/test_num_constructor.rb +133 -0
  50. data/test/test_odd_even.rb +78 -0
  51. data/test/test_round.rb +104 -0
  52. data/test/test_to_int.rb +104 -0
  53. data/test/test_to_rf.rb +36 -0
  54. data/test/test_tol.rb +102 -0
  55. data/test/test_ulp.rb +127 -0
  56. metadata +147 -0
data/test/test_bin.rb ADDED
@@ -0,0 +1,245 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ class TestBin < Test::Unit::TestCase
4
+
5
+
6
+ def setup
7
+ initialize_context
8
+ end
9
+
10
+ def test_binfloat
11
+ assert_equal 2, Float::RADIX
12
+
13
+ BinNum.context = BinNum::FloatContext
14
+ assert_equal 23.0, (BinNum(20) + BinNum(3)).to_f
15
+ assert_equal 1.0/3, (BinNum(1) / BinNum(3)).to_f
16
+ assert_equal Math.sqrt(2), BinNum(2).sqrt.to_f
17
+ assert_equal 9, BinNum(345).number_of_digits
18
+ assert_equal 0.1, BinNum('0.1', :fixed).to_f
19
+
20
+ assert_equal 23.0, (BinNum(20) + BinNum(3))
21
+ assert_equal 1.0/3, (BinNum(1) / BinNum(3))
22
+ assert_equal Math.sqrt(2), BinNum(2).sqrt
23
+ assert_equal 0.1, BinNum('0.1', :fixed)
24
+
25
+ assert_equal Float::MAX, BinNum.context.maximum_finite
26
+ assert_equal Float::MIN, BinNum.context.minimum_normal
27
+
28
+ numbers = %w{
29
+ 0.123437
30
+ 0.123437E57
31
+ 0.1
32
+ 0.1111111111111111111111111
33
+ 0.1E56
34
+ 0.5 0.125 7333 0.126
35
+ 1069756.78125
36
+ 106975678125E-5
37
+ 2.1E6
38
+ 3E20
39
+ }
40
+ numbers += %w{0.12343749827397239423432 3423322.345} if Flt.float_correctly_rounded?
41
+
42
+ numbers.each do |n|
43
+ assert_equal Float(n), BinNum(n, :fixed).to_f
44
+ end
45
+
46
+ end
47
+
48
+ def test_text_to_float_rounding
49
+
50
+ BinNum.context.precision = 8
51
+ BinNum.context.rounding = :down
52
+ assert_equal "11001100", BinNum('0.1', :fixed).split[1].to_s(2)
53
+ BinNum.context.rounding = :floor
54
+ assert_equal "11001100", BinNum('0.1', :fixed).split[1].to_s(2)
55
+ BinNum.context.rounding = :ceiling
56
+ assert_equal "11001100", BinNum('-0.1', :fixed).split[1].to_s(2)
57
+ BinNum.context.rounding = :down
58
+ assert_equal "11001100", BinNum('-0.1', :fixed).split[1].to_s(2)
59
+
60
+ BinNum.context.rounding = :up
61
+ assert_equal "11001101", BinNum('0.1', :fixed).split[1].to_s(2)
62
+ BinNum.context.rounding = :ceiling
63
+ assert_equal "11001101", BinNum('0.1', :fixed).split[1].to_s(2)
64
+ BinNum.context.rounding = :floor
65
+ assert_equal "11001101", BinNum('-0.1', :fixed).split[1].to_s(2)
66
+ BinNum.context.rounding = :up
67
+ assert_equal "11001101", BinNum('-0.1', :fixed).split[1].to_s(2)
68
+
69
+ BinNum.context.rounding = :half_up
70
+ assert_equal "11001101", BinNum('0.1', :fixed).split[1].to_s(2)
71
+ BinNum.context.rounding = :half_down
72
+ assert_equal "11001101", BinNum('0.1', :fixed).split[1].to_s(2)
73
+ BinNum.context.rounding = :half_even
74
+ assert_equal "11001101", BinNum('0.1', :fixed).split[1].to_s(2)
75
+ BinNum.context.rounding = :half_up
76
+ assert_equal "11001101", BinNum('-0.1', :fixed).split[1].to_s(2)
77
+ BinNum.context.rounding = :half_down
78
+ assert_equal "11001101", BinNum('-0.1', :fixed).split[1].to_s(2)
79
+ BinNum.context.rounding = :half_even
80
+ assert_equal "11001101", BinNum('-0.1', :fixed).split[1].to_s(2)
81
+
82
+ BinNum.context.rounding = :half_up
83
+ assert_equal "10000001", BinNum('128.5', :fixed).split[1].to_s(2)
84
+ BinNum.context.rounding = :half_down
85
+ assert_equal "10000000", BinNum('128.5', :fixed).split[1].to_s(2)
86
+ BinNum.context.rounding = :half_even
87
+ assert_equal "10000000", BinNum('128.5', :fixed).split[1].to_s(2)
88
+ BinNum.context.rounding = :half_up
89
+ assert_equal "10000010", BinNum('129.5', :fixed).split[1].to_s(2)
90
+ BinNum.context.rounding = :half_down
91
+ assert_equal "10000001", BinNum('129.5', :fixed).split[1].to_s(2)
92
+ BinNum.context.rounding = :half_even
93
+ assert_equal "10000010", BinNum('129.5', :fixed).split[1].to_s(2)
94
+
95
+ BinNum.context.rounding = :half_up
96
+ assert_equal "10000001", BinNum('-128.5', :fixed).split[1].to_s(2)
97
+ BinNum.context.rounding = :half_down
98
+ assert_equal "10000000", BinNum('-128.5', :fixed).split[1].to_s(2)
99
+ BinNum.context.rounding = :half_even
100
+ assert_equal "10000000", BinNum('-128.5', :fixed).split[1].to_s(2)
101
+ BinNum.context.rounding = :half_up
102
+ assert_equal "10000010", BinNum('-129.5', :fixed).split[1].to_s(2)
103
+ BinNum.context.rounding = :half_down
104
+ assert_equal "10000001", BinNum('-129.5', :fixed).split[1].to_s(2)
105
+ BinNum.context.rounding = :half_even
106
+ assert_equal "10000010", BinNum('-129.5', :fixed).split[1].to_s(2)
107
+
108
+ BinNum.context.rounding = :up
109
+ assert_equal "10000001", BinNum('128.5', :fixed).split[1].to_s(2)
110
+ BinNum.context.rounding = :down
111
+ assert_equal "10000000", BinNum('128.5', :fixed).split[1].to_s(2)
112
+ BinNum.context.rounding = :ceiling
113
+ assert_equal "10000001", BinNum('128.5', :fixed).split[1].to_s(2)
114
+ BinNum.context.rounding = :floor
115
+ assert_equal "10000000", BinNum('128.5', :fixed).split[1].to_s(2)
116
+
117
+ BinNum.context.rounding = :up
118
+ assert_equal "10000001", BinNum('-128.5', :fixed).split[1].to_s(2)
119
+ BinNum.context.rounding = :down
120
+ assert_equal "10000000", BinNum('-128.5', :fixed).split[1].to_s(2)
121
+ BinNum.context.rounding = :ceiling
122
+ assert_equal "10000000", BinNum('-128.5', :fixed).split[1].to_s(2)
123
+ BinNum.context.rounding = :floor
124
+ assert_equal "10000001", BinNum('-128.5', :fixed).split[1].to_s(2)
125
+
126
+ BinNum.context.rounding = :up
127
+ assert_equal "10000010", BinNum('129.5', :fixed).split[1].to_s(2)
128
+ BinNum.context.rounding = :down
129
+ assert_equal "10000001", BinNum('129.5', :fixed).split[1].to_s(2)
130
+ BinNum.context.rounding = :ceiling
131
+ assert_equal "10000010", BinNum('129.5', :fixed).split[1].to_s(2)
132
+ BinNum.context.rounding = :floor
133
+ assert_equal "10000001", BinNum('129.5', :fixed).split[1].to_s(2)
134
+
135
+ BinNum.context.rounding = :up
136
+ assert_equal "10000010", BinNum('-129.5', :fixed).split[1].to_s(2)
137
+ BinNum.context.rounding = :down
138
+ assert_equal "10000001", BinNum('-129.5', :fixed).split[1].to_s(2)
139
+ BinNum.context.rounding = :ceiling
140
+ assert_equal "10000001", BinNum('-129.5', :fixed).split[1].to_s(2)
141
+ BinNum.context.rounding = :floor
142
+ assert_equal "10000010", BinNum('-129.5', :fixed).split[1].to_s(2)
143
+
144
+ BinNum.context.precision = 9
145
+ BinNum.context.rounding = :down
146
+ assert_equal "110011001", BinNum('0.1', :fixed).split[1].to_s(2)
147
+ BinNum.context.rounding = :floor
148
+ assert_equal "110011001", BinNum('0.1', :fixed).split[1].to_s(2)
149
+ BinNum.context.rounding = :ceiling
150
+ assert_equal "110011001", BinNum('-0.1', :fixed).split[1].to_s(2)
151
+ BinNum.context.rounding = :down
152
+ assert_equal "110011001", BinNum('-0.1', :fixed).split[1].to_s(2)
153
+
154
+ BinNum.context.rounding = :up
155
+ assert_equal "110011010", BinNum('0.1', :fixed).split[1].to_s(2)
156
+ BinNum.context.rounding = :ceiling
157
+ assert_equal "110011010", BinNum('0.1', :fixed).split[1].to_s(2)
158
+ BinNum.context.rounding = :floor
159
+ assert_equal "110011010", BinNum('-0.1', :fixed).split[1].to_s(2)
160
+ BinNum.context.rounding = :up
161
+ assert_equal "110011010", BinNum('-0.1', :fixed).split[1].to_s(2)
162
+
163
+ BinNum.context.rounding = :half_up
164
+ assert_equal "110011010", BinNum('0.1', :fixed).split[1].to_s(2)
165
+ BinNum.context.rounding = :half_down
166
+ assert_equal "110011010", BinNum('0.1', :fixed).split[1].to_s(2)
167
+ BinNum.context.rounding = :half_even
168
+ assert_equal "110011010", BinNum('0.1', :fixed).split[1].to_s(2)
169
+ BinNum.context.rounding = :half_up
170
+ assert_equal "110011010", BinNum('-0.1', :fixed).split[1].to_s(2)
171
+ BinNum.context.rounding = :half_down
172
+ assert_equal "110011010", BinNum('-0.1', :fixed).split[1].to_s(2)
173
+ BinNum.context.rounding = :half_even
174
+ assert_equal "110011010", BinNum('-0.1', :fixed).split[1].to_s(2)
175
+
176
+ end
177
+
178
+ def test_text_to_float_exact
179
+ BinNum.context.exact = :quiet
180
+ %w{
181
+ 0.1
182
+ 0.12343749827397239423432
183
+ 0.123437
184
+ 0.1111111111111111111111111
185
+ 0.126
186
+ 3423322.345
187
+ }.each do |n|
188
+ BinNum.context.flags[Num::Inexact] = false
189
+ b = BinNum(n, :fixed)
190
+ assert b.nan?, "BinNum('#{n}') is NaN in exact precision mode"
191
+ assert BinNum.context.flags[Num::Inexact], "BinNum('#{n}') sets Inexact flag"
192
+ end
193
+ %w{
194
+ 0.123437E57
195
+ 0.1E56
196
+ 0.5 0.125 7333
197
+ 1069756.78125
198
+ 106975678125E-5
199
+ 2.1E6
200
+ 3E20
201
+ }.each do |n|
202
+ BinNum.context.flags[Num::Inexact] = false
203
+ b = BinNum(n, :fixed)
204
+ assert_equal Float(n), BinNum(n, :fixed).to_f
205
+ assert !b.nan?, "BinNum('#{n}') is not NaN in exact precision mode"
206
+ assert !BinNum.context.flags[Num::Inexact], "BinNum('#{n}') does not set Inexact flag"
207
+ end
208
+ end
209
+
210
+ def test_float_to_bin_float
211
+ %w{
212
+ 0.12343749827397239423432
213
+ 0.123437
214
+ 0.123437E57
215
+ 0.1
216
+ 0.1111111111111111111111111
217
+ 0.1E56
218
+ 0.5 0.125 7333 0.126
219
+ 3423322.345
220
+ 1069756.78125
221
+ 106975678125E-5
222
+ 2.1E6
223
+ 3E20
224
+ 1.1
225
+ 1.1E31
226
+ -1.1E31
227
+ 0.0
228
+ -0.0
229
+ }.each do |n|
230
+ f = Float(n)
231
+ assert_equal f, BinNum(f).to_f
232
+ end
233
+ nan = 0.0/0.0
234
+ inf = 1.0/0.0
235
+ minf = -1.0/0.0
236
+ assert_equal(-1, BinNum(-0.0).sign)
237
+ assert_equal(-1, BinNum(minf).sign)
238
+ assert_equal(+1, BinNum(0.0).sign)
239
+ assert_equal(+1, BinNum(inf).sign)
240
+ assert BinNum(nan).nan?, "Float NaN to BinNum produces NaN"
241
+ assert BinNum(inf).infinite?, "Float +Infinity to BinNum produces Infinite"
242
+ assert BinNum(minf).infinite?, "Float -Infinity to BinNum produces Infinite"
243
+ end
244
+
245
+ end
@@ -0,0 +1,94 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ # These tests assume that Float arithmetic is correctly rounded
4
+ # Random tests using Float as a reference
5
+ class TestBinArithmetic < Test::Unit::TestCase
6
+
7
+ def setup
8
+ initialize_context
9
+ srand 93831
10
+ @test_float_data ||= Array.new(1000){random_num(Float)} + singular_nums(Float) # + special_nums(Float)
11
+ end
12
+
13
+ def test_addition
14
+ float_emulation_context
15
+ each_pair(@test_float_data) do |x, y|
16
+ z = x + y
17
+ assert_equal z, (BinNum(x)+BinNum(y)).to_f
18
+ end
19
+ end
20
+
21
+ def test_subtraction
22
+ float_emulation_context
23
+ each_pair(@test_float_data) do |x, y|
24
+ z = x - y
25
+ assert_equal z, (BinNum(x)-BinNum(y)).to_f
26
+ end
27
+ end
28
+
29
+ def test_multiplication
30
+ float_emulation_context
31
+ each_pair(@test_float_data) do |x, y|
32
+ z = x * y
33
+ assert_equal z, (BinNum(x)*BinNum(y)).to_f
34
+ end
35
+ end
36
+
37
+ def test_division
38
+ float_emulation_context
39
+ each_pair(@test_float_data) do |x, y|
40
+ # next if y.abs < Float::EPSILON*x.abs
41
+ next if y.zero?
42
+ z = x / y
43
+ # if z != (BinNum(x)/BinNum(y)).to_f
44
+ # puts "x=#{float_split(x).inspect}"
45
+ # puts "y=#{float_split(y).inspect}"
46
+ # puts "z=#{float_split(z).inspect}"
47
+ # puts "->#{(BinNum(x)/BinNum(y)).split.inspect}"
48
+ # end
49
+ assert_equal z, (BinNum(x)/BinNum(y)).to_f
50
+ end
51
+ end
52
+
53
+ def test_power
54
+ float_emulation_context
55
+ each_pair(@test_float_data) do |x, y|
56
+ next if x.zero? && y.zero?
57
+ x = x.abs
58
+ xx = BinNum(x)
59
+ yy = BinNum(y)
60
+ z = x**y
61
+ zz = nil
62
+ begin
63
+ zz = xx**yy
64
+ rescue=>err
65
+ if err.is_a?(Num::Overflow)
66
+ zz = BinNum.infinity
67
+ else
68
+ zz = err.to_s
69
+ end
70
+ end
71
+ ok = true
72
+ zzz = nil
73
+ if zz != z
74
+ # Math.power may not be accurate enough
75
+ zzz = +BinNum.context(:precision=>512) { xx**yy }
76
+ if zzz != zz
77
+ ok = false
78
+ end
79
+ end
80
+ assert ok, "#{x}**#{y} (#{Float.context.split(x).inspect}**#{Float.context.split(y).inspect}) Incorrect: #{zz.split.inspect} instead of #{zzz && zzz.split.inspect}"
81
+ end
82
+ end
83
+
84
+ def test_sqrt
85
+ float_emulation_context
86
+ @test_float_data.each do |x|
87
+ context = x.class.context
88
+ x = context.abs(x)
89
+ z = context.sqrt(x)
90
+ assert_equal z, BinNum(x).sqrt.to_f
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+
4
+ class TestBinfloatConversion < Test::Unit::TestCase
5
+
6
+ def setup
7
+ initialize_context
8
+ end
9
+
10
+ def test_conversions
11
+ float_emulation_context
12
+ srand 12322
13
+ [:half_even, :half_up, :half_down, :down, :up, :floor, :ceiling].each do |rounding|
14
+ BinNum.context.rounding = rounding
15
+ 1000.times do
16
+ x = random_float
17
+ txt = BinNum(x).to_s
18
+ y = BinNum(txt, :fixed).to_f
19
+ assert_equal x, y, "FAIL #{Float.context.split(x).inspect} #{rounding} #{Float.context.split(y).inspect} #{x.class}"
20
+ end
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ class TestCoercion < Test::Unit::TestCase
4
+
5
+
6
+ def setup
7
+ initialize_context
8
+ end
9
+
10
+ def test_coerce
11
+ assert_equal DecNum('7.1'), DecNum('0.1') + 7
12
+ assert_equal DecNum('7.1'), 7 + DecNum('0.1')
13
+ assert_equal DecNum('14'), DecNum(7) * 2
14
+ assert_equal DecNum('14'), 2 * DecNum(7)
15
+
16
+ assert_equal DecNum('7.1'), DecNum(7) + Rational(1,10)
17
+ assert_equal DecNum('7.1'), Rational(1,10) + DecNum(7)
18
+ assert_equal DecNum('1.4'), DecNum(7) * Rational(2,10)
19
+ assert_equal DecNum('1.4'), Rational(2,10) * DecNum(7)
20
+ end
21
+
22
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ class TestComparisons < Test::Unit::TestCase
4
+
5
+
6
+ def setup
7
+ initialize_context
8
+ end
9
+
10
+ def test_hash
11
+ assert_equal DecNum('1.1').hash, DecNum('1.1').hash
12
+ assert_equal DecNum('1.1').hash, (DecNum('1.0')+DecNum('0.1')).hash
13
+ assert_equal DecNum('1.1',:precision=>10).hash, DecNum('1.1',:precision=>3).hash
14
+ assert_not_equal DecNum('1.0').hash, DecNum('1.1').hash
15
+ assert_not_equal DecNum('1.0').hash, 1.0.hash
16
+ assert_not_equal DecNum('1.0').hash, 1.hash
17
+
18
+ assert DecNum('1.1').eql?(DecNum('1.1'))
19
+ assert DecNum('1.1').eql?(DecNum('1.0')+DecNum('0.1'))
20
+ assert DecNum('1.1',:precision=>10).eql?(DecNum('1.1',:precision=>3))
21
+ assert !DecNum('1.1').eql?(DecNum('1.0'))
22
+ assert !DecNum('1.0').eql?(1.0)
23
+ assert !DecNum('1.0').eql?(1)
24
+ end
25
+
26
+ def test_equality
27
+ assert DecNum('1.1') == DecNum('1.1')
28
+ assert DecNum('1.1') == (DecNum('1.0')+DecNum('0.1'))
29
+ assert DecNum('1.1',:precision=>10) == DecNum('1.1',:precision=>3)
30
+ assert !(DecNum('1.1') == DecNum('1.0'))
31
+ #assert DecNum('1.1') == 1.1
32
+ #assert DecNum('1.0') == 1.0
33
+ #assert DecNum('1.0') == BigDecimal.new('1.000')
34
+ assert DecNum('1.0') == 1
35
+ assert DecNum('0.1') == Rational(1)/Rational(10)
36
+
37
+ assert !(DecNum.nan == DecNum.nan)
38
+ assert !(DecNum.nan == DecNum('1'))
39
+ assert !(DecNum.nan == DecNum('0'))
40
+ assert !(DecNum.nan == DecNum.infinity)
41
+ #assert !(DecNum.nan == (0.0/0.0))
42
+
43
+ assert !(DecNum.infinity(+1) == DecNum.infinity(-1))
44
+ assert !(DecNum.infinity(+1) == DecNum('0'))
45
+ assert DecNum.infinity(+1) == DecNum.infinity
46
+ assert DecNum.infinity(+1) == DecNum('1')/DecNum('0')
47
+ assert DecNum.infinity(-1) == DecNum('-1')/DecNum('0')
48
+
49
+ # TODO: test <=> <= etc.
50
+ end
51
+
52
+
53
+ end
@@ -0,0 +1,216 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ ROUNDINGS = {
4
+ 'ceiling' => :ceiling,
5
+ 'down' => :down,
6
+ 'floor' => :floor,
7
+ 'half_down' => :half_down,
8
+ 'half_even' => :half_even,
9
+ 'half_up' => :half_up,
10
+ 'up' => :up,
11
+ '05up' => :up05
12
+ }
13
+ FUNCTIONS = {
14
+ 'add'=>'add',
15
+ 'divide'=>'divide',
16
+ 'multiply'=>'multiply',
17
+ 'subtract'=>'subtract',
18
+ 'compare'=>'compare',
19
+ 'copyabs'=>'copy_abs',
20
+ 'copynegate'=>'copy_negate',
21
+ 'copysign'=>'copy_sign',
22
+ 'divideint'=>'divide_int',
23
+ 'logb'=>'logb',
24
+ 'minus'=>'minus',
25
+ 'plus'=>'plus',
26
+ 'reduce'=>'reduce',
27
+ 'remainder'=>'remainder',
28
+ 'remaindernear'=>'remainder_near',
29
+ 'scaleb'=>'scaleb',
30
+ 'rescale'=>'rescale',
31
+ 'quantize'=>'quantize',
32
+ 'samequantum'=>'same_quantum?',
33
+ 'tointegral'=>'to_integral_value',
34
+ 'tointegralx'=>'to_integral_exact',
35
+ 'fma'=>'fma',
36
+ 'squareroot'=>'sqrt',
37
+ 'abs'=>'abs',
38
+ 'nextminus'=>'next_minus',
39
+ 'nextplus'=>'next_plus',
40
+ 'nexttoward'=>'next_toward',
41
+ 'tosci'=>'to_sci_string',
42
+ 'toeng'=>'to_eng_string',
43
+ 'class'=>'number_class',
44
+ 'power'=>'power',
45
+ 'log10'=>'log10',
46
+ 'exp'=>'exp',
47
+ 'ln'=>'ln'
48
+ }
49
+ # Functions not yet implemented
50
+ PENDING = %w{
51
+ rotate
52
+ shift
53
+ trim
54
+
55
+ and
56
+ or
57
+ xor
58
+ invert
59
+
60
+ max
61
+ min
62
+ maxmag
63
+ minmag
64
+ comparetotal
65
+ comparetotmag
66
+ }
67
+ IGNORED = PENDING + %w{
68
+ copy
69
+ apply
70
+ }
71
+
72
+ FLAG_NAMES = {
73
+ 'inexact'=>:Inexact,
74
+ 'rounded'=>:Rounded,
75
+ 'clamped'=>:Clamped,
76
+ 'subnormal'=>:Subnormal,
77
+ 'invalid_operation'=>:InvalidOperation,
78
+ 'underflow'=>:Underflow,
79
+ 'overflow'=>:Overflow,
80
+ 'division_by_zero'=>:DivisionByZero,
81
+ 'division_undefined'=>:InvalidOperation,
82
+ 'division_impossible'=>:DivisionImpossible,
83
+ 'conversion_syntax'=>:ConversionSyntax
84
+ }
85
+
86
+ # Excluded tests that we don't currently pass
87
+ EXCEPTIONS = %w{
88
+ powx1183 powx1184
89
+ powx4001 powx4002 powx4003 powx4005
90
+ powx4008 powx4010 powx4012 powx4014
91
+ logx901 logx902 logx903 logx903 logx905
92
+ expx901 expx902 expx903 expx905
93
+ lnx901 lnx902 lnx903 lnx905
94
+ }
95
+
96
+
97
+ def unquote(txt)
98
+ if txt[0,1]=="'" && txt[-1,1]=="'"
99
+ txt = txt[1...-1].gsub("''","'")
100
+ end
101
+ if txt[0,1]=='"' && txt[-1,1]=='"'
102
+ txt = txt[1...-1].gsub('""','"')
103
+ end
104
+ #txt = 'NaN' if txt=='#' || txt=='?'
105
+ txt = 'sNaN' if txt=='#'
106
+ txt = 'NaN' if txt=='?'
107
+ txt
108
+ end
109
+
110
+ class TestBasic < Test::Unit::TestCase
111
+
112
+ def test_dec
113
+ missing = []
114
+ dir = File.join(File.dirname(__FILE__), 'dectest')
115
+ dir = nil unless File.exists?(dir)
116
+ if dir
117
+ Dir[File.join(dir, '*.decTest')].each do |fn|
118
+
119
+ name = File.basename(fn,'.decTest').downcase
120
+ next if %w{ds dd dq}.include?(name[0,2]) ||
121
+ %w{decsingle decdouble decquad testall}.include?(name)
122
+
123
+ initialize_context
124
+
125
+
126
+ File.open(fn,'r') do |file|
127
+ file.each_line do |line|
128
+ next if line[0,2]=='--' || line.strip.empty?
129
+
130
+ if line.include?(' -> ')
131
+ # test
132
+ # to do :remove inline comments --... on the right of ->
133
+ sides = line.split('->')
134
+ # now split by whitespace but avoid breaking quoted strings (and take care or repeated quotes!)
135
+ lhs = sides.first.strip.scan(/"(?:[^"]|"")*"|'(?:[^']|'')*'|\S+/)
136
+ id = lhs.first
137
+ funct = lhs[1].downcase
138
+ valstemp = lhs[2..-1]
139
+ rhs = sides.last.strip.split
140
+ ans = rhs.first
141
+ flags = rhs[1..-1].map{|f| DecNum.class_eval(FLAG_NAMES[f.downcase].to_s)}.compact
142
+
143
+ next unless valstemp.grep(/#/).empty?
144
+
145
+ $test_id = id
146
+ funct = FUNCTIONS[original_funct=funct]
147
+ next if EXCEPTIONS.include?(id)
148
+ if funct
149
+ # do test
150
+ msg = " Test #{id}: #{funct}(#{valstemp.join(',')}) = #{ans}"
151
+ #File.open('dectests.txt','a'){|f| f.puts msg}
152
+ expected = result = result_flags = nil
153
+ DecNum.local_context do |context|
154
+ context.flags.clear!
155
+ exact_input = !['apply','to_sci_string', 'to_eng_string'].include?(funct)
156
+ if exact_input
157
+ p = context.precision
158
+ context.exact = true
159
+ end
160
+ valstemp.map!{|v| DecNum(unquote(v))}
161
+ context.precision = p if exact_input
162
+ result = context.send(funct, *valstemp)
163
+ result_flags = context.flags.dup
164
+ expected = unquote(ans)
165
+ context.exact = true
166
+ expected = DecNum(expected) unless result.is_a?(String)
167
+ end
168
+ result = 1 if result==true
169
+ result = 0 if result==false
170
+ expected_flags = DecNum::Flags(*flags)
171
+ if ans!='?'
172
+ assert_equal expected.to_s, result.to_s, msg
173
+ end
174
+ assert_equal expected_flags, result_flags, msg
175
+
176
+ else
177
+ missing << original_funct unless IGNORED.include?(original_funct) || missing.include?(original_funct)
178
+ end
179
+
180
+ elsif line.include?(':')
181
+ # directive
182
+ funct,value = line.split(':').map{|x| x.strip.downcase}
183
+ case funct
184
+ when 'rounding'
185
+ value = ROUNDINGS[value]
186
+ else
187
+ value = value.to_i
188
+ end
189
+ if value.nil?
190
+ #raise "error"
191
+ # to do: skip untill next valid value of same funct
192
+ else
193
+ case funct
194
+ when 'rounding','precision'
195
+ DecNum.context.send "#{funct}=", value
196
+ when 'maxexponent'
197
+ DecNum.context.emax = value
198
+ when 'minexponent'
199
+ DecNum.context.emin = value
200
+ when 'clamp'
201
+ DecNum.context.clamp = (value==0 ? false : true)
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ # assert_empty missing
211
+ # In Ruby 1.8 there's no assert_empty
212
+ assert missing.empty?, "#{missing.inspect} is not empty"
213
+
214
+ end
215
+
216
+ end