long-decimal 0.00.21 → 0.00.22
Sign up to get free protection for your applications and to get access to all the features.
- data/README +23 -16
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/doc/classes/LongDecimal.html +343 -343
- data/doc/classes/LongDecimal.src/M000036.html +4 -4
- data/doc/classes/LongDecimal.src/M000037.html +4 -4
- data/doc/classes/LongDecimal.src/M000038.html +4 -4
- data/doc/classes/LongDecimal.src/M000039.html +4 -4
- data/doc/classes/LongDecimal.src/M000040.html +4 -6
- data/doc/classes/LongDecimal.src/M000041.html +4 -106
- data/doc/classes/LongDecimal.src/M000042.html +6 -21
- data/doc/classes/LongDecimal.src/M000043.html +105 -10
- data/doc/classes/LongDecimal.src/M000044.html +17 -23
- data/doc/classes/LongDecimal.src/M000045.html +10 -18
- data/doc/classes/LongDecimal.src/M000046.html +27 -4
- data/doc/classes/LongDecimal.src/M000047.html +17 -13
- data/doc/classes/LongDecimal.src/M000048.html +4 -28
- data/doc/classes/LongDecimal.src/M000049.html +15 -4
- data/doc/classes/LongDecimal.src/M000050.html +26 -6
- data/doc/classes/LongDecimal.src/M000051.html +4 -6
- data/doc/classes/LongDecimal.src/M000052.html +8 -4
- data/doc/classes/LongDecimal.src/M000053.html +6 -15
- data/doc/classes/LongDecimal.src/M000054.html +4 -7
- data/doc/classes/LongDecimal.src/M000055.html +15 -4
- data/doc/classes/LongDecimal.src/M000056.html +6 -14
- data/doc/classes/LongDecimal.src/M000057.html +4 -13
- data/doc/classes/LongDecimal.src/M000058.html +15 -4
- data/doc/classes/LongDecimal.src/M000059.html +13 -4
- data/doc/classes/LongDecimal.src/M000060.html +4 -4
- data/doc/classes/LongDecimal.src/M000062.html +4 -5
- data/doc/classes/LongDecimal.src/M000063.html +5 -4
- data/doc/classes/LongDecimal.src/M000064.html +5 -8
- data/doc/classes/LongDecimal.src/M000065.html +4 -9
- data/doc/classes/LongDecimal.src/M000066.html +6 -7
- data/doc/classes/LongDecimal.src/M000067.html +6 -6
- data/doc/classes/LongDecimal.src/M000068.html +9 -4
- data/doc/classes/LongDecimal.src/M000069.html +7 -13
- data/doc/classes/LongDecimal.src/M000070.html +4 -9
- data/doc/classes/LongDecimal.src/M000071.html +13 -7
- data/doc/classes/LongDecimal.src/M000072.html +7 -18
- data/doc/classes/LongDecimal.src/M000073.html +8 -7
- data/doc/classes/LongDecimal.src/M000074.html +20 -5
- data/doc/classes/LongDecimal.src/M000075.html +7 -8
- data/doc/classes/LongDecimal.src/M000076.html +5 -9
- data/doc/classes/LongDecimal.src/M000077.html +5 -5
- data/doc/classes/LongDecimal.src/M000078.html +9 -4
- data/doc/classes/LongDecimal.src/M000079.html +8 -6
- data/doc/classes/LongDecimal.src/M000080.html +4 -7
- data/doc/classes/LongDecimal.src/M000081.html +7 -4
- data/doc/classes/LongDecimal.src/M000082.html +7 -4
- data/doc/classes/LongDecimal.src/M000083.html +4 -9
- data/doc/classes/LongDecimal.src/M000084.html +4 -9
- data/doc/classes/LongDecimal.src/M000085.html +9 -5
- data/doc/classes/LongDecimal.src/M000086.html +7 -7
- data/doc/classes/LongDecimal.src/M000087.html +5 -4
- data/doc/classes/LongDecimal.src/M000088.html +9 -4
- data/doc/classes/LongDecimal.src/M000089.html +4 -4
- data/doc/classes/LongDecimal.src/M000090.html +4 -4
- data/doc/classes/LongDecimal.src/M000091.html +4 -59
- data/doc/classes/LongDecimal.src/M000092.html +4 -4
- data/doc/classes/LongDecimal.src/M000093.html +59 -4
- data/doc/classes/LongDecimal.src/M000094.html +4 -5
- data/doc/classes/LongDecimal.src/M000095.html +4 -4
- data/doc/classes/LongDecimal.src/M000098.html +5 -4
- data/doc/classes/LongDecimal.src/M000099.html +5 -4
- data/doc/classes/LongDecimal.src/M000100.html +4 -4
- data/doc/classes/LongDecimal.src/M000101.html +4 -4
- data/doc/classes/LongDecimalBase.html +53 -53
- data/doc/classes/LongDecimalBase.src/M000107.html +4 -4
- data/doc/classes/LongDecimalBase.src/M000108.html +4 -4
- data/doc/classes/LongDecimalBase.src/M000109.html +4 -4
- data/doc/classes/LongDecimalBase.src/M000110.html +4 -4
- data/doc/classes/LongDecimalBase.src/M000111.html +4 -5
- data/doc/classes/LongDecimalBase.src/M000112.html +9 -9
- data/doc/classes/LongDecimalBase.src/M000115.html +23 -0
- data/doc/classes/LongDecimalQuot.html +174 -133
- data/doc/classes/LongDecimalQuot.src/M000003.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000004.html +2 -1
- data/doc/classes/LongDecimalQuot.src/M000005.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000006.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000007.html +6 -5
- data/doc/classes/LongDecimalQuot.src/M000008.html +5 -4
- data/doc/classes/LongDecimalQuot.src/M000009.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000010.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000011.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000012.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000013.html +7 -4
- data/doc/classes/LongDecimalQuot.src/M000014.html +5 -8
- data/doc/classes/LongDecimalQuot.src/M000015.html +5 -9
- data/doc/classes/LongDecimalQuot.src/M000016.html +6 -7
- data/doc/classes/LongDecimalQuot.src/M000017.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000018.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000019.html +6 -18
- data/doc/classes/LongDecimalQuot.src/M000020.html +8 -7
- data/doc/classes/LongDecimalQuot.src/M000021.html +21 -5
- data/doc/classes/LongDecimalQuot.src/M000022.html +8 -4
- data/doc/classes/LongDecimalQuot.src/M000023.html +5 -96
- data/doc/classes/LongDecimalQuot.src/M000024.html +4 -38
- data/doc/classes/LongDecimalQuot.src/M000025.html +96 -4
- data/doc/classes/LongDecimalQuot.src/M000026.html +38 -4
- data/doc/classes/LongDecimalQuot.src/M000027.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000028.html +4 -4
- data/doc/classes/LongDecimalQuot.src/M000029.html +4 -4
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.html +10 -10
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000148.html +22 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000149.html +18 -0
- data/doc/classes/LongMath.html +159 -161
- data/doc/classes/LongMath.src/M000118.html +5 -4
- data/doc/classes/LongMath.src/M000119.html +4 -5
- data/doc/classes/LongMath.src/M000120.html +4 -4
- data/doc/classes/LongMath.src/M000121.html +5 -18
- data/doc/classes/LongMath.src/M000122.html +4 -18
- data/doc/classes/LongMath.src/M000123.html +18 -5
- data/doc/classes/LongMath.src/M000124.html +16 -27
- data/doc/classes/LongMath.src/M000125.html +4 -4
- data/doc/classes/LongMath.src/M000126.html +17 -45
- data/doc/classes/LongMath.src/M000127.html +5 -21
- data/doc/classes/LongMath.src/M000128.html +50 -29
- data/doc/classes/LongMath.src/M000129.html +21 -6
- data/doc/classes/LongMath.src/M000130.html +31 -28
- data/doc/classes/LongMath.src/M000131.html +6 -48
- data/doc/classes/LongMath.src/M000132.html +33 -8
- data/doc/classes/LongMath.src/M000133.html +51 -4
- data/doc/classes/LongMath.src/M000134.html +7 -4
- data/doc/classes/LongMath.src/M000135.html +4 -64
- data/doc/classes/LongMath.src/M000136.html +4 -43
- data/doc/classes/LongMath.src/M000137.html +64 -4
- data/doc/classes/LongMath.src/M000138.html +43 -4
- data/doc/classes/LongMath.src/M000139.html +4 -7
- data/doc/classes/LongMath.src/M000140.html +4 -20
- data/doc/classes/LongMath.src/M000141.html +4 -18
- data/doc/classes/LongMath.src/M000142.html +11 -34
- data/doc/classes/LongMath.src/M000143.html +13 -253
- data/doc/classes/LongMath.src/M000144.html +40 -16
- data/doc/classes/LongMath.src/M000145.html +227 -0
- data/doc/classes/LongMath.src/M000146.html +33 -0
- data/doc/classes/LongMath/CacheKey.html +6 -6
- data/doc/classes/LongMath/CacheKey.src/M000147.html +36 -0
- data/doc/classes/Numeric.html +10 -10
- data/doc/classes/Numeric.src/M000103.html +18 -0
- data/doc/classes/Rational.html +5 -5
- data/doc/classes/Rational.src/M000104.html +23 -0
- data/doc/created.rid +1 -1
- data/doc/files/lib/long-decimal_rb.src/M000001.html +1 -1
- data/doc/files/lib/long-decimal_rb.src/M000002.html +1 -1
- data/doc/fr_method_index.html +145 -143
- data/lib/long-decimal.rb +52 -71
- data/test/testlongdecimal.rb +218 -449
- data/test/testlongdeclib.rb +485 -0
- data/test/testrandom.rb +75 -0
- data/version.rb +1 -1
- metadata +12 -3
- data/doc/files/lib/long-decimal_rb.html +0 -189
@@ -0,0 +1,485 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# library for testlongdecimal.rb
|
4
|
+
#
|
5
|
+
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdeclib.rb,v 1.2 2006/04/07 22:26:08 bk1 Exp $
|
6
|
+
# CVS-Label: $Name: PRE_ALPHA_0_22 $
|
7
|
+
# Author: $Author: bk1 $ (Karl Brodowsky)
|
8
|
+
#
|
9
|
+
|
10
|
+
load "lib/long-decimal.rb"
|
11
|
+
|
12
|
+
#
|
13
|
+
# test class for LongDecimal and LongDecimalQuot
|
14
|
+
#
|
15
|
+
module TestLongDecHelper
|
16
|
+
|
17
|
+
@RCS_ID='-$Id: testlongdeclib.rb,v 1.2 2006/04/07 22:26:08 bk1 Exp $-'
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# convenience method for comparing two numbers. true if and only if
|
22
|
+
# they express the same value
|
23
|
+
#
|
24
|
+
def assert_val_equal(expected, actual, message="")
|
25
|
+
_wrap_assertion {
|
26
|
+
full_message = build_message(message, "Expected <?> to match <?>", actual, expected)
|
27
|
+
assert_block(full_message) {
|
28
|
+
(expected <=> actual).zero?
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# convenience method for comparing Float with LongDecimal
|
35
|
+
# using a delta coming from these
|
36
|
+
#
|
37
|
+
def assert_mixed_equal(expected_f, actual_ld, message="")
|
38
|
+
delta = [ actual_ld.unit, expected_f.abs / 1e10 ].max
|
39
|
+
assert_equal_float(expected_f, actual_ld, delta, message)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# helper method for test_split_merge_words
|
44
|
+
#
|
45
|
+
def check_split_merge_words(x, l, wl)
|
46
|
+
w = LongMath.split_to_words(x, l)
|
47
|
+
y = LongMath.merge_from_words(w, l)
|
48
|
+
assert_equal(x, y, "#{x} splitted and merged should be equal but is #{y} l=#{l}")
|
49
|
+
assert_equal(wl, w.length, "#{x} splitted to l=#{l} should have length #{wl} but has #{w.length}")
|
50
|
+
w
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# helper method for test_exp
|
55
|
+
# tests if exp(x) with precision prec is calculated correctly
|
56
|
+
#
|
57
|
+
def check_exp_floated(x, prec)
|
58
|
+
|
59
|
+
print "."
|
60
|
+
$stdout.flush
|
61
|
+
|
62
|
+
# make sure x is LongDecimal
|
63
|
+
x0 = x
|
64
|
+
x = x.to_ld
|
65
|
+
# calculate y = exp(x)
|
66
|
+
# eprec = prec+1
|
67
|
+
y = LongMath.exp(x, prec)
|
68
|
+
|
69
|
+
# compare y against z = exp(x) calculated using regular floating point arithmetic
|
70
|
+
z = Math.exp(x.to_f)
|
71
|
+
yf = y.to_f
|
72
|
+
assert((yf - z).abs <= [ y.unit, z.abs / 1e9 ].max, "y=#{yf.to_s} and z=#{z.to_s} should be almost equal x=#{x}")
|
73
|
+
|
74
|
+
# check by taking log(exp(x))
|
75
|
+
# we have to take into account that we might not have enough
|
76
|
+
# significant digits, so we have to go down with the precision
|
77
|
+
if (y > 0) then
|
78
|
+
lprec = prec - 1
|
79
|
+
if (y < 1) then
|
80
|
+
l10 = (Math.log(y.to_f) / Math.log(10)).round
|
81
|
+
lprec += l10
|
82
|
+
end
|
83
|
+
df = 1
|
84
|
+
if (lprec < 0)
|
85
|
+
df += lprec.abs
|
86
|
+
lprec = 0
|
87
|
+
end
|
88
|
+
z = LongMath.log(y, lprec)
|
89
|
+
delta = z.unit * df
|
90
|
+
assert((x - z).abs <= delta, "x=#{x.to_s} and z=#{z.to_s} should be almost equal (#{(x-z).abs.inspect} < d=#{delta.inspect} y=#{y.to_s} lprec=#{lprec} prec=#{prec})")
|
91
|
+
end
|
92
|
+
|
93
|
+
# check by doing calculation with different internal rounding modes. They should not differ.
|
94
|
+
yd = LongMath.exp_internal(x, prec, nil, nil, nil, nil, LongDecimal::ROUND_DOWN)
|
95
|
+
yu = LongMath.exp_internal(x, prec, nil, nil, nil, nil, LongDecimal::ROUND_UP)
|
96
|
+
assert_equal(yd, yu, "the result yd/yu should not depend on the internal rounding mode x0=#{x0} x=#{x} p=#{prec} d=#{(yd-yu).to_f.to_s}")
|
97
|
+
assert_equal(y, yu, "the result y/yu should not depend on the internal rounding mode x0=#{x0} x=#{x} p=#{prec} d=#{(y -yu).to_f.to_s}")
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# helper method for test_exp_int
|
102
|
+
# tests if exp(x) with precision prec is calculated correctly
|
103
|
+
#
|
104
|
+
def check_exp_int(x)
|
105
|
+
|
106
|
+
# make sure x is LongDecimal
|
107
|
+
x0 = x
|
108
|
+
x = x.to_ld
|
109
|
+
y = LongMath.exp(x, 0)
|
110
|
+
assert_equal(y.scale, 0, "scale must be 0")
|
111
|
+
|
112
|
+
# compare y against z = exp(x) calculated using regular floating point arithmetic
|
113
|
+
z = Math.exp(x0.to_f)
|
114
|
+
yf = y.to_f
|
115
|
+
yi = yf.round
|
116
|
+
zi = z.round
|
117
|
+
assert((yi-zi).abs / [yf.abs, z.abs, Float::MIN].max < 1e-9, "yi=#{yi} and zi=#{zi} should be equal x=#{x} y=#{y} z=#{z}")
|
118
|
+
|
119
|
+
if (y > 1)
|
120
|
+
w = LongMath.log(y, 0)
|
121
|
+
assert((w-x).abs < 1, "log(y)=#{w} must be almost x=#{x0}")
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# helper method for test_lm_power_xint
|
128
|
+
# tests if exp(x) with precision prec is calculated correctly
|
129
|
+
#
|
130
|
+
def check_power_xint(x, y, prec)
|
131
|
+
|
132
|
+
xi = x.to_i
|
133
|
+
x = x.to_ld()
|
134
|
+
y = y.to_ld()
|
135
|
+
z = LongMath.power(x, y, prec)
|
136
|
+
zz = LongMath.power_internal(x, y, prec)
|
137
|
+
assert((zz - z).abs <= z.unit, "power with and without optimizations z=#{z} zz=#{zz} x=#{x} y=#{y}")
|
138
|
+
# compare y against z = exp(x) calculated using regular floating point arithmetic
|
139
|
+
zz = (xi) ** (y.to_f)
|
140
|
+
zf = z.to_f
|
141
|
+
assert((zf - zz).abs < [z.unit.to_f, zz.abs / 1e9 ].max, "z=#{z} and zz=#{zz} should be almost equal x=#{x} y=#{y} (zf=#{zf})")
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# helper method for test_lm_power_yint
|
146
|
+
# tests if exp(x) with precision prec is calculated correctly
|
147
|
+
#
|
148
|
+
def check_power_yint(x, y, prec)
|
149
|
+
|
150
|
+
yi = y.to_i
|
151
|
+
x = x.to_ld
|
152
|
+
y = y.to_ld
|
153
|
+
|
154
|
+
z = LongMath.power(x, y, prec, LongMath::ROUND_HALF_UP)
|
155
|
+
zz = (x ** yi).round_to_scale(prec, LongMath::ROUND_HALF_UP)
|
156
|
+
assert_equal(z, zz, "power with ** or power-method x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
157
|
+
zz = LongMath.power_internal(x, y, prec)
|
158
|
+
assert((zz - z).abs <= z.unit, "power with and without optimizations x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
159
|
+
|
160
|
+
zz = (x.to_f) ** (y.to_f)
|
161
|
+
zf = z.to_f
|
162
|
+
# assert((zf - zz).abs / [zf.abs, zz.abs, Float::MIN].max < 1e-9, "z=#{zf.to_s} and zz=#{zz.to_s} should be almost equal x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
163
|
+
assert((zf - zz).abs < [ z.unit.to_f, zf.abs / 1e9 ].max, "zf=#{zf.to_s} and zz=#{zz.to_s} should be almost equal x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# helper method for test_log
|
168
|
+
# tests if log(x) with precision prec is calculated correctly
|
169
|
+
#
|
170
|
+
def check_log_floated(x, prec, divisor=1e9, summand=0)
|
171
|
+
|
172
|
+
print ","
|
173
|
+
$stdout.flush
|
174
|
+
|
175
|
+
# make sure x is LongDecimal
|
176
|
+
x0 = x
|
177
|
+
x = x.to_ld
|
178
|
+
# calculate y = log(x)
|
179
|
+
y = LongMath.log(x, prec)
|
180
|
+
|
181
|
+
# compare y against z = exp(x) calculated using regular floating
|
182
|
+
# point arithmetic
|
183
|
+
if (x <= LongMath::MAX_FLOATABLE) then
|
184
|
+
xf = x.to_f
|
185
|
+
if (xf > 0) then
|
186
|
+
z = Math.log(x.to_f)
|
187
|
+
zl = z.to_ld(y.scale)
|
188
|
+
delta = [ y.unit, z.abs / divisor + summand ].max
|
189
|
+
assert((y - zl).abs <= delta, "y=#{y.to_s} (#{y.to_f}) and z=#{z.to_s} (#{zl.to_f}) should be almost equal (d=#{delta.inspect} x=#{x} y=#{y})")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# check by taking exp(log(y))
|
194
|
+
# we have to take into account that we might not have enough
|
195
|
+
# significant digits, so we have to go down with the precision
|
196
|
+
if (y <= LongMath::MAX_EXP_ABLE) then
|
197
|
+
eprec = prec - 1
|
198
|
+
if (y > 1) then
|
199
|
+
ly = 0
|
200
|
+
if (y > LongMath::MAX_FLOATABLE) then
|
201
|
+
puts("unusual y=#{y} y=#{y}\n")
|
202
|
+
ly = LongMath::MAX_EXP_ABLE
|
203
|
+
else
|
204
|
+
ly = Math.log(y.to_f)
|
205
|
+
end
|
206
|
+
# l10 = (ly * (1.2+2/(prec+1.0)) / Math.log(10)).ceil
|
207
|
+
l10 = (y.to_f * (1.2+2/(prec+1.0)) / Math.log(10)).ceil
|
208
|
+
# l10 = (y.to_f / Math.log(10)).ceil
|
209
|
+
eprec -= l10
|
210
|
+
end
|
211
|
+
df = 1
|
212
|
+
if (eprec < 0)
|
213
|
+
df += eprec.abs
|
214
|
+
eprec = 0
|
215
|
+
end
|
216
|
+
z = LongMath.exp(y, eprec)
|
217
|
+
u = z.unit
|
218
|
+
delta = (u + u.move_point_left(1)) * df
|
219
|
+
assert((x - z).abs <= delta, "x=#{x.to_s} and z=#{z.to_s} should be almost equal (#{(x-z).abs.inspect} < d=#{delta.inspect} y=#{y.to_s} eprec=#{eprec} prec=#{prec})")
|
220
|
+
end
|
221
|
+
|
222
|
+
# check by doing calculation with different internal rounding modes. They should not differ.
|
223
|
+
yd = LongMath.log_internal(x, prec, nil, nil, LongDecimal::ROUND_DOWN)
|
224
|
+
yu = LongMath.log_internal(x, prec, nil, nil, LongDecimal::ROUND_UP)
|
225
|
+
assert_equal(yd, yu, "the result yd/yu should not depend on the internal rounding mode yd=#{yd} yu=#{yu} y=#{y} p=#{prec} d=#{(yd-yu).to_f.to_s}")
|
226
|
+
assert_equal(y, yu, "the result y/yu should not depend on the internal rounding mode yd=#{yd} yu=#{yu} y=#{y} p=#{prec} d=#{(y -yu).to_f.to_s}")
|
227
|
+
end
|
228
|
+
|
229
|
+
#
|
230
|
+
# helper method for test_lm_power
|
231
|
+
# tests if LongMath::power(x, y, prec) with precision prec is calculated correctly
|
232
|
+
#
|
233
|
+
def check_power_floated(x, y, prec)
|
234
|
+
|
235
|
+
# puts("start: check_power_floated: x=#{x} y=#{y} prec=#{prec}\n")
|
236
|
+
# make sure x and y are LongDecimal
|
237
|
+
x0 = x
|
238
|
+
x = x.to_ld
|
239
|
+
y0 = y
|
240
|
+
y = y.to_ld
|
241
|
+
# calculate z = x**y
|
242
|
+
z = LongMath.power(x, y, prec)
|
243
|
+
|
244
|
+
# compare y against w = x**y calculated using regular floating point arithmetic
|
245
|
+
w = (x.to_f) ** (y.to_f)
|
246
|
+
zf = z.to_f
|
247
|
+
# assert((zf - w).abs / [zf.abs, w.abs, Float::MIN].max < 1e-9, "z=#{zf.to_s} and w=#{w.to_s} should be almost equal x=#{x} y=#{y}")
|
248
|
+
assert((zf - w).abs <= [ z.unit, zf.abs / 1e9 ].max, "z=#{zf.to_s} and w=#{w.to_s} should be almost equal x=#{x} y=#{y}")
|
249
|
+
|
250
|
+
# check by taking log(z) = y * log(x)
|
251
|
+
# we have to take into account that we might not have enough
|
252
|
+
# significant digits, so we have to go down with the precision
|
253
|
+
if (z > 0) then
|
254
|
+
lprec = prec
|
255
|
+
if (z < 1) then
|
256
|
+
l10 = (Math.log(z.to_f) / Math.log(10)).floor
|
257
|
+
lprec += l10
|
258
|
+
end
|
259
|
+
if (x < 1) then
|
260
|
+
l10 = (Math.log(x.to_f) / Math.log(10)).floor
|
261
|
+
lprec += l10
|
262
|
+
end
|
263
|
+
unit = (10**(-lprec)).to_ld
|
264
|
+
if (lprec < 0)
|
265
|
+
lprec = 0
|
266
|
+
end
|
267
|
+
l10y = 0
|
268
|
+
if (y > 1) then
|
269
|
+
l10y = (Math.log(y.to_f) / Math.log(10)).ceil
|
270
|
+
end
|
271
|
+
u = LongMath.log(z, lprec)
|
272
|
+
v = LongMath.log(x, lprec+l10y)
|
273
|
+
yv = (y*v).round_to_scale(lprec, LongDecimal::ROUND_HALF_DOWN)
|
274
|
+
assert((u - yv).abs <= unit, "u=#{u} and yv=y*v=#{yv} should be almost equal (unit=#{unit} x=#{x.to_s} y=#{y.to_s} z=#{z.to_s} u=#{u.to_s} v=#{v.to_s} lprec=#{lprec} prec=#{prec})")
|
275
|
+
end
|
276
|
+
# puts("ok check_power_floated: x=#{x} y=#{y} prec=#{prec}\n")
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
#
|
281
|
+
# helper method for test_log10
|
282
|
+
# tests if log10(x) with precision prec is calculated correctly
|
283
|
+
#
|
284
|
+
def check_log10_floated(x, prec)
|
285
|
+
|
286
|
+
# make sure x is LongDecimal
|
287
|
+
x0 = x
|
288
|
+
x = x.to_ld
|
289
|
+
# calculate y = log10(x)
|
290
|
+
y = LongMath.log10(x, prec)
|
291
|
+
|
292
|
+
# compare y against z = log10(x) calculated using regular floating
|
293
|
+
# point arithmetic
|
294
|
+
if (x <= LongMath::MAX_FLOATABLE) then
|
295
|
+
xf = x.to_f
|
296
|
+
if (xf > 0) then
|
297
|
+
z = Math.log(x.to_f) / Math.log(10)
|
298
|
+
yf = y.to_f
|
299
|
+
assert((yf - z).abs / [yf.abs, z.abs, Float::MIN].max < 1e-9, "y=#{yf.to_s} and z=#{z.to_s} should be almost equal x=#{x}")
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# check by taking 10**(log10(x))
|
304
|
+
# we have to take into account that we might not have enough
|
305
|
+
# significant digits, so we have to go down with the precision
|
306
|
+
if (y <= LongMath::MAX_EXP_ABLE) then
|
307
|
+
eprec = prec
|
308
|
+
if (y > 1) then
|
309
|
+
lx = 0
|
310
|
+
if (x > LongMath::MAX_FLOATABLE) then
|
311
|
+
puts("unusual x=#{x} y=#{y}\n")
|
312
|
+
lx = LongMath::MAX_EXP_ABLE
|
313
|
+
else
|
314
|
+
lx = Math.log(x.to_f)
|
315
|
+
end
|
316
|
+
l10 = (lx / Math.log(10)).ceil
|
317
|
+
eprec = [ eprec - l10, 0 ].max
|
318
|
+
end
|
319
|
+
|
320
|
+
z = LongMath.power(10.to_ld, y, eprec)
|
321
|
+
# zz = LongMath.exp10(y, eprec)
|
322
|
+
# assert((zz - z).abs <= z.unit, "zz=#{zz.to_s} and z=#{z.to_s} should be almost equal (y=#{y.to_s} eprec=#{eprec} prec=#{prec})")
|
323
|
+
assert((x - z).abs <= z.unit, "x=#{x.to_s} and z=#{z.to_s} should be almost equal (y=#{y.to_s} eprec=#{eprec} prec=#{prec})")
|
324
|
+
end
|
325
|
+
|
326
|
+
end
|
327
|
+
|
328
|
+
#
|
329
|
+
# helper method for test_log10
|
330
|
+
# tests if log10(x) with precision prec is calculated correctly
|
331
|
+
#
|
332
|
+
def check_log10_exact(x, log10x, prec)
|
333
|
+
|
334
|
+
# make sure x is LongDecimal
|
335
|
+
x0 = x
|
336
|
+
x = x.to_ld
|
337
|
+
log10x = log10x.to_ld(prec)
|
338
|
+
# calculate y = log10(x)
|
339
|
+
y = LongMath.log10(x, prec)
|
340
|
+
assert_equal(y, log10x, "log x should match exactly x=#{x} y=#{y} log10x=#{log10x}")
|
341
|
+
end
|
342
|
+
|
343
|
+
#
|
344
|
+
# helper method for test_log2
|
345
|
+
# tests if log2(x) with precision prec is calculated correctly
|
346
|
+
#
|
347
|
+
def check_log2_floated(x, prec)
|
348
|
+
|
349
|
+
# make sure x is LongDecimal
|
350
|
+
x0 = x
|
351
|
+
x = x.to_ld
|
352
|
+
# calculate y = log2(x)
|
353
|
+
y = LongMath.log2(x, prec)
|
354
|
+
|
355
|
+
# compare y against z = log2(x) calculated using regular floating
|
356
|
+
# point arithmetic
|
357
|
+
if (x <= LongMath::MAX_FLOATABLE) then
|
358
|
+
xf = x.to_f
|
359
|
+
if (xf > 0) then
|
360
|
+
z = Math.log(x.to_f) / Math.log(2)
|
361
|
+
yf = y.to_f
|
362
|
+
assert((yf - z).abs / [yf.abs, z.abs, Float::MIN].max < 1e-9, "y=#{yf.to_s} and z=#{z.to_s} should be almost equal x=#{x}")
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# check by taking 2**(log2(x))
|
367
|
+
# we have to take into account that we might not have enough
|
368
|
+
# significant digits, so we have to go down with the precision
|
369
|
+
if (y <= LongMath::MAX_EXP_ABLE) then
|
370
|
+
eprec = prec
|
371
|
+
if (y > 1) then
|
372
|
+
lx = 0
|
373
|
+
if (x > LongMath::MAX_FLOATABLE) then
|
374
|
+
puts("unusual x=#{x} y=#{y}\n")
|
375
|
+
lx = LongMath::MAX_EXP_ABLE
|
376
|
+
else
|
377
|
+
lx = Math.log(x.to_f)
|
378
|
+
end
|
379
|
+
l10 = (lx / Math.log(10)).ceil
|
380
|
+
eprec = [ eprec - l10, 0 ].max
|
381
|
+
end
|
382
|
+
|
383
|
+
z = LongMath.power(2.to_ld, y, eprec)
|
384
|
+
# zz = LongMath.exp2(y, eprec)
|
385
|
+
# assert((zz - z).abs <= z.unit, "zz=#{zz.to_s} and z=#{z.to_s} should be almost equal (y=#{y.to_s} eprec=#{eprec} prec=#{prec})")
|
386
|
+
assert((x - z).abs <= z.unit, "x=#{x.to_s} and z=#{z.to_s} should be almost equal (y=#{y.to_s} eprec=#{eprec} prec=#{prec})")
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
#
|
392
|
+
# helper method for test_log2
|
393
|
+
# tests if log2(x) with precision prec is calculated correctly
|
394
|
+
#
|
395
|
+
def check_log2_exact(x, log2x, prec)
|
396
|
+
|
397
|
+
# make sure x is LongDecimal
|
398
|
+
x0 = x
|
399
|
+
x = x.to_ld
|
400
|
+
log2x = log2x.to_ld(prec)
|
401
|
+
# calculate y = log2(x)
|
402
|
+
y = LongMath.log2(x, prec)
|
403
|
+
assert_equal(y, log2x, "log x should match exactly x=#{x} y=#{y} log2x=#{log2x} prec=#{prec}")
|
404
|
+
end
|
405
|
+
|
406
|
+
#
|
407
|
+
# helper method for test_int_sqrtb
|
408
|
+
#
|
409
|
+
def check_sqrtb(x, s)
|
410
|
+
y = LongMath.sqrtb(x)
|
411
|
+
z = y * y
|
412
|
+
zz = (y+1)*(y+1)
|
413
|
+
assert(0 <= y, "sqrt must be >= 0" + s)
|
414
|
+
assert(z <= x && x < zz, "y=#{y}=sqrt(#{x}) and x in [#{z}, #{zz})" + s)
|
415
|
+
y
|
416
|
+
end
|
417
|
+
|
418
|
+
#
|
419
|
+
# helper method of test_int_sqrtw
|
420
|
+
#
|
421
|
+
def check_sqrtw(x, s)
|
422
|
+
y = LongMath.sqrtw(x)
|
423
|
+
z = y * y
|
424
|
+
zz = (y+1)*(y+1)
|
425
|
+
assert(0 <= y, "sqrt must be >= 0" + s)
|
426
|
+
assert(z <= x && x < zz, "y=#{y}=sqrt(#{x}) and x in [#{z}, #{zz})" + s)
|
427
|
+
y
|
428
|
+
end
|
429
|
+
|
430
|
+
#
|
431
|
+
# helper method for test_int_sqrtb_with_remainder
|
432
|
+
#
|
433
|
+
def check_sqrtb_with_remainder(x, s)
|
434
|
+
y, r = LongMath.sqrtb_with_remainder(x)
|
435
|
+
z0 = y * y
|
436
|
+
z1 = z0 + r
|
437
|
+
z2 = (y+1)*(y+1)
|
438
|
+
assert(0 <= y, "sqrt _with_remaindermust be >= 0" + s)
|
439
|
+
assert_equal(z1, x, "x=#{x} y=#{y} r=#{r} z0=#{z0} z1=#{z1} z2=#{z2}" + s)
|
440
|
+
assert(z0 <= x && x < z2, "y=#{y}=sqrt(_with_remainder#{x}) and x in [#{z0}, #{z2}) r=#{r} z0=#{z0} z1=#{z1} z2=#{z2}" + s)
|
441
|
+
y
|
442
|
+
end
|
443
|
+
|
444
|
+
#
|
445
|
+
# helper method for test_int_sqrtw_with_remainder
|
446
|
+
#
|
447
|
+
def check_sqrtw_with_remainder(x, s)
|
448
|
+
y, r = LongMath.sqrtw_with_remainder(x)
|
449
|
+
z0 = y * y
|
450
|
+
z1 = z0 + r
|
451
|
+
z2 = (y+1)*(y+1)
|
452
|
+
assert(0 <= y, "sqrt _with_remaindermust be >= 0" + s)
|
453
|
+
assert_equal(z1, x, "x=#{x} y=#{y} r=#{r} z0=#{z0} z1=#{z1} z2=#{z2}" + s)
|
454
|
+
assert(z0 <= x && x < z2, "y=#{y}=sqrt(_with_remainder#{x}) and x in [#{z0}, #{z2}) r=#{r} z0=#{z0} z1=#{z1} z2=#{z2}" + s)
|
455
|
+
y
|
456
|
+
end
|
457
|
+
|
458
|
+
#
|
459
|
+
# helper method of test_sqrt
|
460
|
+
#
|
461
|
+
def check_sqrt(x, scale, mode, su0, su1, str)
|
462
|
+
y = x.sqrt(scale, mode)
|
463
|
+
z0 = (y+su0*y.unit).square
|
464
|
+
z1 = (y+su1*y.unit).square
|
465
|
+
assert(0 <= y.sign, "sqrt must be >= 0" + str)
|
466
|
+
assert(z0 <= x && x <= z1, "y=#{y}=sqrt(#{x}) and x in [#{z0}, #{z1}) " + str)
|
467
|
+
y
|
468
|
+
end
|
469
|
+
|
470
|
+
#
|
471
|
+
# helper method of test_sqrt_with_remainder
|
472
|
+
#
|
473
|
+
def check_sqrt_with_remainder(x, scale, str)
|
474
|
+
y, r = x.sqrt_with_remainder(scale)
|
475
|
+
z0 = y.square
|
476
|
+
z1 = y.succ.square
|
477
|
+
assert(0 <= y.sign, "sqrt must be >= 0" + str)
|
478
|
+
assert(z0 <= x && x < z1, "y=#{y}=sqrt(#{x}) and x in [#{z0}, #{z1}) " + str)
|
479
|
+
assert((x - z0 - r).zero?, "x=y*y+r x=#{x} z0=#{z0} z1=#{z1} r=#{r} total=#{x - z0 - r} " + str)
|
480
|
+
r
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
# end of file testlongdecimal.rb
|