flt 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +41 -0
- data/License.txt +20 -0
- data/Manifest.txt +42 -0
- data/README.txt +557 -0
- data/Rakefile +34 -0
- data/lib/flt.rb +9 -0
- data/lib/flt/b.rb +6 -0
- data/lib/flt/bigdecimal.rb +151 -0
- data/lib/flt/bin_num.rb +250 -0
- data/lib/flt/d.rb +6 -0
- data/lib/flt/dec_num.rb +1239 -0
- data/lib/flt/float.rb +458 -0
- data/lib/flt/math.rb +66 -0
- data/lib/flt/num.rb +4211 -0
- data/lib/flt/sugar.rb +102 -0
- data/lib/flt/support.rb +1335 -0
- data/lib/flt/tolerance.rb +561 -0
- data/lib/flt/tolerance/sugar.rb +77 -0
- data/lib/flt/version.rb +9 -0
- data/setup.rb +1585 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +192 -0
- data/tasks/git.rake +40 -0
- data/tasks/manifest.rake +48 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +279 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/all_tests.rb +23 -0
- data/test/helper.rb +101 -0
- data/test/reader.rb +68 -0
- data/test/test_basic.rb +396 -0
- data/test/test_bin.rb +245 -0
- data/test/test_bin_arithmetic.rb +94 -0
- data/test/test_binfloat_conversion.rb +24 -0
- data/test/test_coercion.rb +22 -0
- data/test/test_comparisons.rb +53 -0
- data/test/test_dectest.rb +216 -0
- data/test/test_define_conversions.rb +144 -0
- data/test/test_epsilon.rb +55 -0
- data/test/test_exact.rb +147 -0
- data/test/test_flags.rb +34 -0
- data/test/test_multithreading.rb +32 -0
- data/test/test_num_constructor.rb +133 -0
- data/test/test_odd_even.rb +78 -0
- data/test/test_round.rb +104 -0
- data/test/test_to_int.rb +104 -0
- data/test/test_to_rf.rb +36 -0
- data/test/test_tol.rb +102 -0
- data/test/test_ulp.rb +127 -0
- 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
|