long-decimal 0.01.01 → 0.01.02
Sign up to get free protection for your applications and to get access to all the features.
- data/README +17 -94
- data/VERSION +1 -1
- data/doc/classes/Integer.html +239 -0
- data/doc/classes/Integer.src/M000036.html +18 -0
- data/doc/classes/Integer.src/M000039.html +145 -0
- data/doc/classes/LongDecimal.html +453 -399
- data/doc/classes/LongDecimal.src/M000040.html +4 -4
- data/doc/classes/LongDecimal.src/M000041.html +4 -4
- data/doc/classes/LongDecimal.src/M000042.html +4 -6
- data/doc/classes/LongDecimal.src/M000043.html +4 -106
- data/doc/classes/LongDecimal.src/M000044.html +4 -21
- data/doc/classes/LongDecimal.src/M000045.html +4 -11
- data/doc/classes/LongDecimal.src/M000046.html +6 -27
- data/doc/classes/LongDecimal.src/M000047.html +103 -16
- data/doc/classes/LongDecimal.src/M000048.html +21 -4
- data/doc/classes/LongDecimal.src/M000049.html +10 -14
- data/doc/classes/LongDecimal.src/M000050.html +22 -36
- data/doc/classes/LongDecimal.src/M000051.html +34 -4
- data/doc/classes/LongDecimal.src/M000052.html +17 -6
- data/doc/classes/LongDecimal.src/M000053.html +4 -6
- data/doc/classes/LongDecimal.src/M000054.html +15 -4
- data/doc/classes/LongDecimal.src/M000055.html +44 -12
- data/doc/classes/LongDecimal.src/M000056.html +4 -7
- data/doc/classes/LongDecimal.src/M000057.html +8 -4
- data/doc/classes/LongDecimal.src/M000058.html +6 -15
- data/doc/classes/LongDecimal.src/M000059.html +4 -13
- data/doc/classes/LongDecimal.src/M000060.html +15 -4
- data/doc/classes/LongDecimal.src/M000061.html +7 -5
- data/doc/classes/LongDecimal.src/M000062.html +4 -4
- data/doc/classes/LongDecimal.src/M000063.html +15 -5
- data/doc/classes/LongDecimal.src/M000064.html +13 -5
- data/doc/classes/LongDecimal.src/M000065.html +4 -4
- data/doc/classes/LongDecimal.src/M000067.html +4 -8
- data/doc/classes/LongDecimal.src/M000068.html +5 -9
- data/doc/classes/LongDecimal.src/M000069.html +5 -9
- data/doc/classes/LongDecimal.src/M000070.html +4 -9
- data/doc/classes/LongDecimal.src/M000071.html +4 -4
- data/doc/classes/LongDecimal.src/M000072.html +6 -17
- data/doc/classes/LongDecimal.src/M000073.html +7 -7
- data/doc/classes/LongDecimal.src/M000074.html +7 -7
- data/doc/classes/LongDecimal.src/M000075.html +7 -19
- data/doc/classes/LongDecimal.src/M000076.html +4 -8
- data/doc/classes/LongDecimal.src/M000077.html +19 -5
- data/doc/classes/LongDecimal.src/M000078.html +7 -7
- data/doc/classes/LongDecimal.src/M000079.html +7 -7
- data/doc/classes/LongDecimal.src/M000080.html +19 -7
- data/doc/classes/LongDecimal.src/M000081.html +8 -4
- data/doc/classes/LongDecimal.src/M000082.html +5 -7
- data/doc/classes/LongDecimal.src/M000083.html +8 -6
- data/doc/classes/LongDecimal.src/M000084.html +9 -4
- data/doc/classes/LongDecimal.src/M000085.html +9 -4
- data/doc/classes/LongDecimal.src/M000086.html +4 -9
- data/doc/classes/LongDecimal.src/M000087.html +6 -8
- data/doc/classes/LongDecimal.src/M000088.html +7 -5
- data/doc/classes/LongDecimal.src/M000089.html +4 -9
- data/doc/classes/LongDecimal.src/M000090.html +4 -4
- data/doc/classes/LongDecimal.src/M000091.html +9 -4
- data/doc/classes/LongDecimal.src/M000092.html +9 -4
- data/doc/classes/LongDecimal.src/M000093.html +5 -4
- data/doc/classes/LongDecimal.src/M000094.html +7 -57
- data/doc/classes/LongDecimal.src/M000095.html +4 -4
- data/doc/classes/LongDecimal.src/M000096.html +4 -4
- data/doc/classes/LongDecimal.src/M000097.html +4 -5
- data/doc/classes/LongDecimal.src/M000098.html +4 -5
- data/doc/classes/LongDecimal.src/M000099.html +59 -5
- data/doc/classes/LongDecimal.src/M000100.html +4 -5
- data/doc/classes/LongDecimal.src/M000101.html +4 -4
- data/doc/classes/LongDecimal.src/M000104.html +19 -0
- data/doc/classes/LongDecimal.src/M000105.html +19 -0
- data/doc/classes/LongDecimal.src/M000106.html +18 -0
- data/doc/classes/LongDecimal.src/M000107.html +18 -0
- data/doc/classes/LongDecimal.src/M000108.html +18 -0
- data/doc/classes/LongDecimal.src/M000109.html +18 -0
- data/doc/classes/LongDecimalBase.html +69 -66
- data/doc/classes/LongDecimalBase.src/M000113.html +4 -9
- data/doc/classes/LongDecimalBase.src/M000114.html +4 -5
- data/doc/classes/LongDecimalBase.src/M000115.html +4 -9
- data/doc/classes/LongDecimalBase.src/M000116.html +4 -9
- data/doc/classes/LongDecimalBase.src/M000117.html +4 -5
- data/doc/classes/LongDecimalBase.src/M000118.html +23 -0
- data/doc/classes/LongDecimalBase.src/M000121.html +23 -0
- data/doc/classes/LongDecimalBase.src/M000122.html +19 -0
- data/doc/classes/LongDecimalBase.src/M000123.html +18 -0
- data/doc/classes/LongDecimalQuot.html +33 -27
- data/doc/classes/LongDecimalQuot.src/M000003.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000004.html +1 -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 +1 -1
- data/doc/classes/LongDecimalQuot.src/M000008.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000009.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000010.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000011.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000012.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000013.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000014.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000015.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000016.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000017.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000018.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000019.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000020.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000021.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000022.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000023.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000024.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000025.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000026.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000027.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000028.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000029.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000030.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000031.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000034.html +1 -1
- data/doc/classes/LongDecimalQuot.src/M000035.html +1 -1
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.html +25 -24
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000156.html +22 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000157.html +18 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000158.html +18 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000159.html +18 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000161.html +25 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000162.html +18 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000163.html +18 -0
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000164.html +18 -0
- data/doc/classes/LongDecimalRoundingMode/ZeroRoundingModeClass.html +178 -0
- data/doc/classes/LongDecimalRoundingMode/ZeroRoundingModeClass.src/M000165.html +25 -0
- data/doc/classes/LongDecimalRoundingMode/ZeroRoundingModeClass.src/M000166.html +18 -0
- data/doc/classes/LongDecimalRoundingMode.html +41 -4
- data/doc/classes/LongMath/CacheKey.html +10 -10
- data/doc/classes/LongMath/CacheKey.src/M000155.html +36 -0
- data/doc/classes/LongMath/CacheKey.src/M000160.html +36 -0
- data/doc/classes/LongMath.html +246 -235
- data/doc/classes/LongMath.src/M000124.html +5 -18
- data/doc/classes/LongMath.src/M000125.html +4 -18
- data/doc/classes/LongMath.src/M000126.html +4 -5
- data/doc/classes/LongMath.src/M000127.html +5 -29
- data/doc/classes/LongMath.src/M000128.html +4 -5
- data/doc/classes/LongMath.src/M000129.html +14 -53
- data/doc/classes/LongMath.src/M000130.html +17 -20
- data/doc/classes/LongMath.src/M000131.html +5 -36
- data/doc/classes/LongMath.src/M000132.html +29 -6
- data/doc/classes/LongMath.src/M000133.html +5 -33
- data/doc/classes/LongMath.src/M000134.html +47 -41
- data/doc/classes/LongMath.src/M000135.html +21 -7
- data/doc/classes/LongMath.src/M000136.html +36 -4
- data/doc/classes/LongMath.src/M000137.html +6 -4
- data/doc/classes/LongMath.src/M000138.html +31 -70
- data/doc/classes/LongMath.src/M000139.html +45 -38
- data/doc/classes/LongMath.src/M000140.html +7 -4
- data/doc/classes/LongMath.src/M000141.html +4 -4
- data/doc/classes/LongMath.src/M000142.html +4 -6
- data/doc/classes/LongMath.src/M000143.html +67 -14
- data/doc/classes/LongMath.src/M000144.html +39 -14
- data/doc/classes/LongMath.src/M000145.html +4 -44
- data/doc/classes/LongMath.src/M000146.html +5 -339
- data/doc/classes/LongMath.src/M000147.html +6 -25
- data/doc/classes/LongMath.src/M000148.html +14 -75
- data/doc/classes/LongMath.src/M000149.html +33 -0
- data/doc/classes/LongMath.src/M000150.html +58 -0
- data/doc/classes/LongMath.src/M000151.html +406 -0
- data/doc/classes/LongMath.src/M000152.html +63 -0
- data/doc/classes/LongMath.src/M000153.html +117 -0
- data/doc/classes/LongMath.src/M000154.html +150 -0
- data/doc/classes/LongMath.src/M000155.html +63 -0
- data/doc/classes/LongMath.src/M000156.html +18 -0
- data/doc/classes/LongMath.src/M000157.html +19 -0
- data/doc/classes/LongMath.src/M000158.html +18 -0
- data/doc/classes/LongMath.src/M000159.html +19 -0
- data/doc/classes/Numeric.html +23 -21
- data/doc/classes/Numeric.src/M000106.html +18 -0
- data/doc/classes/Numeric.src/M000110.html +23 -0
- data/doc/classes/Numeric.src/M000111.html +18 -0
- data/doc/classes/Rational.html +18 -16
- data/doc/classes/Rational.src/M000107.html +23 -0
- data/doc/classes/Rational.src/M000112.html +23 -0
- data/doc/created.rid +1 -1
- data/doc/dot/f_0.dot +23 -1
- data/doc/dot/f_0.png +0 -0
- data/doc/dot/m_0_0.png +0 -0
- data/doc/dot/m_0_1.dot +13 -0
- data/doc/dot/m_0_1.png +0 -0
- data/doc/files/lib/long-decimal_rb.html +15 -13
- 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_class_index.html +2 -0
- data/doc/fr_method_index.html +131 -124
- data/lib/long-decimal.rb +373 -49
- data/test/testlongdecimal.rb +689 -7
- data/test/testlongdeclib.rb +51 -11
- data/test/testrandlib.rb +23 -7
- data/test/testrandom.rb +4 -4
- data/test/testrandpower.rb +11 -9
- metadata +48 -3
data/lib/long-decimal.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#
|
2
2
|
# long-decimal.rb -- Arbitrary precision decimals with fixed decimal point
|
3
3
|
#
|
4
|
-
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/long-decimal.rb,v 1.
|
5
|
-
# CVS-Label: $Name:
|
4
|
+
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/long-decimal.rb,v 1.50 2007/07/12 20:46:59 bk1 Exp $
|
5
|
+
# CVS-Label: $Name: ALPHA_01_02 $
|
6
6
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
7
7
|
#
|
8
8
|
require "complex"
|
@@ -32,8 +32,11 @@ module LongDecimalRoundingMode
|
|
32
32
|
def <=>(o)
|
33
33
|
if o.respond_to?:num
|
34
34
|
self.num <=> o.num
|
35
|
-
|
35
|
+
elsif o.kind_of? Numeric
|
36
36
|
self.num <=> o
|
37
|
+
else
|
38
|
+
puts("stack=#{caller.join("\n")}")
|
39
|
+
raise TypeError, "o=#{o.inspect} must be numeric or RoundingMode";
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
@@ -97,13 +100,219 @@ module LongDecimalRoundingMode
|
|
97
100
|
ROUND_UNNECESSARY => ROUND_UNNECESSARY
|
98
101
|
}
|
99
102
|
|
103
|
+
ZeroRoundingModeClass = Struct.new(:name, :num)
|
104
|
+
|
105
|
+
#
|
106
|
+
# enumeration class to express the possible rounding modes that are
|
107
|
+
# supported by LongDecimal
|
108
|
+
#
|
109
|
+
class ZeroRoundingModeClass
|
110
|
+
include Comparable
|
111
|
+
|
112
|
+
#
|
113
|
+
# introduce some ordering for rounding modes
|
114
|
+
#
|
115
|
+
def <=>(o)
|
116
|
+
if o.respond_to?:num
|
117
|
+
self.num <=> o.num
|
118
|
+
elsif o.kind_of? Numeric
|
119
|
+
self.num <=> o
|
120
|
+
else
|
121
|
+
puts("stack=#{caller.join("\n")}")
|
122
|
+
raise TypeError, "o=#{o.inspect} must be numeric or ZeroRoundingMode";
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def hash
|
127
|
+
num
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# rounding modes as constants
|
134
|
+
#
|
135
|
+
ZERO_ROUND_TO_PLUS = ZeroRoundingModeClass.new(:ZERO_ROUND_TO_PLUS, 0)
|
136
|
+
ZERO_ROUND_TO_MINUS = ZeroRoundingModeClass.new(:ZERO_ROUND_TO_MINUS, 1)
|
137
|
+
ZERO_ROUND_TO_CLOSEST_PREFER_PLUS = ZeroRoundingModeClass.new(:ZERO_ROUND_TO_CLOSEST_PREFER_PLUS, 2)
|
138
|
+
ZERO_ROUND_TO_CLOSEST_PREFER_MINUS = ZeroRoundingModeClass.new(:ZERO_ROUND_TO_CLOSEST_PREFER_MINUS, 3)
|
139
|
+
ZERO_ROUND_UNNECESSARY = ZeroRoundingModeClass.new(:ZERO_ROUND_UNNECESSARY, 4)
|
140
|
+
|
100
141
|
end # LongDecimalRoundingMode
|
101
142
|
|
143
|
+
#
|
144
|
+
# add one method to Integer
|
145
|
+
#
|
146
|
+
class Integer
|
147
|
+
|
148
|
+
#
|
149
|
+
# get the sign of self
|
150
|
+
# -1 if self < 0
|
151
|
+
# 0 if self is 0 (with any number of 0s after the decimal point)
|
152
|
+
# +1 if self > 0
|
153
|
+
#
|
154
|
+
def sgn
|
155
|
+
self <=> 0
|
156
|
+
end
|
157
|
+
|
158
|
+
alias signum sgn
|
159
|
+
alias sign sgn
|
160
|
+
|
161
|
+
#
|
162
|
+
# create copy of self round in such a way that the result is
|
163
|
+
# congruent modulo modulus to one of the members of remainders
|
164
|
+
#
|
165
|
+
# param1: remainders array of allowed remainders
|
166
|
+
# param2: modulus modulus of the remainders
|
167
|
+
# param3: rounding_mode rounding mode to be applied when information is
|
168
|
+
# lost. defaults to ROUND_UNNECESSARY, which
|
169
|
+
# means that an exception is thrown if rounding
|
170
|
+
# would actually loose any information.
|
171
|
+
# param4: zero_rounding_mode if self is zero, but zero is not among
|
172
|
+
# the available remainders, it has to be
|
173
|
+
# rounded to positive or negative value.
|
174
|
+
# If the rounding_mode does not allow to
|
175
|
+
# determine which of the two values to
|
176
|
+
# use, zero_rounding_mode has to be used
|
177
|
+
# to decide.
|
178
|
+
#
|
179
|
+
def round_to_allowed_remainders(remainders,
|
180
|
+
modulus,
|
181
|
+
rounding_mode = LongDecimalRoundingMode::ROUND_UNNECESSARY,
|
182
|
+
zero_rounding_mode = LongDecimalRoundingMode::ZERO_ROUND_UNNECESSARY)
|
183
|
+
|
184
|
+
raise TypeError, "remainders must be Array" unless remainders.kind_of? Array
|
185
|
+
raise TypeError, "remainders must be non-empty Array" unless remainders.length > 0
|
186
|
+
raise TypeError, "modulus #{modulus.inspect} must be integer" unless modulus.kind_of? Integer
|
187
|
+
raise TypeError, "modulus #{modulus.inspect} must be >= 2" unless modulus >= 2
|
188
|
+
raise TypeError, "rounding_mode #{rounding_mode.inspect} must be legal rounding rounding_mode" unless rounding_mode.kind_of? LongDecimalRoundingMode::RoundingModeClass
|
189
|
+
raise TypeError, "ROUND_HALF_EVEN is not applicable here" if rounding_mode == LongDecimalRoundingMode::ROUND_HALF_EVEN
|
190
|
+
raise TypeError, "zero_rounding_mode #{zero_rounding_mode.inspect} must be legal zero_rounding zero_rounding_mode" unless zero_rounding_mode.kind_of? LongDecimalRoundingMode::ZeroRoundingModeClass
|
191
|
+
|
192
|
+
r_self = self % modulus
|
193
|
+
r_self_00 = r_self
|
194
|
+
remainders = remainders.collect do |r|
|
195
|
+
raise TypeError, "remainders must be numbers" unless r.kind_of? Integer
|
196
|
+
r % modulus
|
197
|
+
end
|
198
|
+
remainders.sort!.uniq!
|
199
|
+
r_first = remainders[0]
|
200
|
+
r_last = remainders[-1]
|
201
|
+
r_first_again = r_first + modulus
|
202
|
+
remainders.push r_first_again
|
203
|
+
if (r_self < r_first) then
|
204
|
+
r_self += modulus
|
205
|
+
end
|
206
|
+
# puts "r_self=#{r_self_00}->#{r_self} r_first=#{r_first} r_last=#{r_last} r_first_again=#{r_first_again}"
|
207
|
+
r_lower = -1
|
208
|
+
r_upper = -1
|
209
|
+
remainders.each_index do |i|
|
210
|
+
r = remainders[i]
|
211
|
+
if (r == r_self) then
|
212
|
+
return self
|
213
|
+
elsif (r < r_self) then
|
214
|
+
r_lower = r
|
215
|
+
elsif (r > r_self) then
|
216
|
+
r_upper = r
|
217
|
+
break
|
218
|
+
end
|
219
|
+
end
|
220
|
+
lower = self - (r_self - r_lower)
|
221
|
+
upper = self + (r_upper - r_self)
|
222
|
+
# puts "r_lower=#{r_lower} r_upper=#{r_upper} lower=#{lower} upper=#{upper} s=#{self}"
|
223
|
+
|
224
|
+
unless (lower < self && self < upper)
|
225
|
+
raise Error, "self=#{self} not in (#{lower}, #{upper})"
|
226
|
+
end
|
227
|
+
if (rounding_mode == LongDecimalRoundingMode::ROUND_UNNECESSARY) then
|
228
|
+
raise ArgumentError, "mode ROUND_UNNECESSARY not applicable, self=#{self.to_s} is in open interval (#{lower}, #{upper})"
|
229
|
+
end
|
230
|
+
|
231
|
+
# if (rounding_mode == LongDecimalRoundingMode::ROUND_FLOOR) then
|
232
|
+
# return lower
|
233
|
+
# elsif (rounding_mode == LongDecimalRoundingMode::ROUND_CEILING) then
|
234
|
+
# return upper
|
235
|
+
# end
|
236
|
+
|
237
|
+
sign_self = self.sign
|
238
|
+
if (sign_self == 0) then
|
239
|
+
if (rounding_mode == LongDecimalRoundingMode::ROUND_UP || rounding_mode == LongDecimalRoundingMode::ROUND_DOWN \
|
240
|
+
|| lower == -upper && (rounding_mode == LongDecimalRoundingMode::ROUND_HALF_UP || rounding_mode == LongDecimalRoundingMode::ROUND_HALF_DOWN))
|
241
|
+
if (zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_UNNECESSARY) then
|
242
|
+
raise ArgumentError, "self=#{self.to_s} is 0 in open interval (#{lower}, #{upper}) and cannot be resolved with ZERO_ROUND_UNNECESSARY"
|
243
|
+
elsif (zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_TO_CLOSEST_PREFER_PLUS \
|
244
|
+
|| zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_TO_CLOSEST_PREFER_MINUS) then
|
245
|
+
diff = lower.abs <=> upper.abs
|
246
|
+
if (diff < 0) then
|
247
|
+
return lower
|
248
|
+
elsif (diff > 0) then
|
249
|
+
return upper
|
250
|
+
elsif (zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_TO_CLOSEST_PREFER_PLUS) then
|
251
|
+
return upper
|
252
|
+
elsif (zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_TO_CLOSEST_PREFER_MINUS) then
|
253
|
+
return lower
|
254
|
+
else
|
255
|
+
raise Error, "this case can never happen: zero_rounding_mode=#{zero_rounding_mode}"
|
256
|
+
end
|
257
|
+
elsif (zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_TO_PLUS) then
|
258
|
+
return upper
|
259
|
+
elsif (zero_rounding_mode == LongDecimalRoundingMode::ZERO_ROUND_TO_MINUS) then
|
260
|
+
return lower
|
261
|
+
else
|
262
|
+
raise Error, "this case can never happen: zero_rounding_mode=#{zero_rounding_mode}"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# now we can assume that sign_self (and self) is != 0, which allows to decide on the rounding_mode
|
268
|
+
|
269
|
+
if (rounding_mode == LongDecimalRoundingMode::ROUND_UP)
|
270
|
+
# ROUND_UP goes to the closest possible value away from zero
|
271
|
+
rounding_mode = (sign_self < 0) ? LongDecimalRoundingMode::ROUND_FLOOR : LongDecimalRoundingMode::ROUND_CEILING
|
272
|
+
elsif (rounding_mode == LongDecimalRoundingMode::ROUND_DOWN)
|
273
|
+
# ROUND_DOWN goes to the closest possible value towards zero or beyond zero
|
274
|
+
rounding_mode = (sign_self < 0) ? LongDecimalRoundingMode::ROUND_CEILING : LongDecimalRoundingMode::ROUND_FLOOR
|
275
|
+
elsif (rounding_mode == LongDecimalRoundingMode::ROUND_HALF_UP)
|
276
|
+
# ROUND_HALF_UP goes to the closest possible value preferring away from zero
|
277
|
+
rounding_mode = (sign_self < 0) ? LongDecimalRoundingMode::ROUND_HALF_FLOOR : LongDecimalRoundingMode::ROUND_HALF_CEILING
|
278
|
+
elsif (rounding_mode == LongDecimalRoundingMode::ROUND_HALF_DOWN)
|
279
|
+
# ROUND_HALF_DOWN goes to the closest possible value preferring towards zero or beyond zero
|
280
|
+
rounding_mode = (sign_self < 0) ? LongDecimalRoundingMode::ROUND_HALF_CEILING : LongDecimalRoundingMode::ROUND_HALF_FLOOR
|
281
|
+
end
|
282
|
+
if (rounding_mode == LongDecimalRoundingMode::ROUND_HALF_FLOOR \
|
283
|
+
|| rounding_mode == LongDecimalRoundingMode::ROUND_HALF_CEILING) then
|
284
|
+
d_lower = self - lower
|
285
|
+
d_upper = upper - self
|
286
|
+
if (d_lower < d_upper) then
|
287
|
+
return lower
|
288
|
+
elsif (d_upper < d_lower) then
|
289
|
+
return upper
|
290
|
+
elsif (rounding_mode == LongDecimalRoundingMode::ROUND_HALF_FLOOR) then
|
291
|
+
rounding_mode = LongDecimalRoundingMode::ROUND_FLOOR
|
292
|
+
elsif (rounding_mode == LongDecimalRoundingMode::ROUND_HALF_CEILING) then
|
293
|
+
rounding_mode = LongDecimalRoundingMode::ROUND_CEILING
|
294
|
+
else
|
295
|
+
raise Error, "this case can never happen: rounding_mode=#{rounding_mode}"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
if (rounding_mode == LongDecimalRoundingMode::ROUND_FLOOR) then
|
300
|
+
# puts "floor/lower r_lower=#{r_lower} r_upper=#{r_upper} lower=#{lower} upper=#{upper} s=#{self}"
|
301
|
+
return lower
|
302
|
+
elsif (rounding_mode == LongDecimalRoundingMode::ROUND_CEILING) then
|
303
|
+
# puts "ceiling/upper r_lower=#{r_lower} r_upper=#{r_upper} lower=#{lower} upper=#{upper} s=#{self}"
|
304
|
+
return upper
|
305
|
+
else
|
306
|
+
raise Error, "this case can never happen: rounding_mode=#{rounding_mode}"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
102
311
|
#
|
103
312
|
# common base class for LongDecimal and LongDecimalQuot
|
104
313
|
#
|
105
314
|
class LongDecimalBase < Numeric
|
106
|
-
@RCS_ID='-$Id: long-decimal.rb,v 1.
|
315
|
+
@RCS_ID='-$Id: long-decimal.rb,v 1.50 2007/07/12 20:46:59 bk1 Exp $-'
|
107
316
|
|
108
317
|
include LongDecimalRoundingMode
|
109
318
|
|
@@ -211,7 +420,7 @@ end # class LongDecimalBase
|
|
211
420
|
# digits and the other one the position of the decimal point.
|
212
421
|
#
|
213
422
|
class LongDecimal < LongDecimalBase
|
214
|
-
@RCS_ID='-$Id: long-decimal.rb,v 1.
|
423
|
+
@RCS_ID='-$Id: long-decimal.rb,v 1.50 2007/07/12 20:46:59 bk1 Exp $-'
|
215
424
|
|
216
425
|
# MINUS_ONE = LongDecimal(-1)
|
217
426
|
# ZERO = LongDecimal(0)
|
@@ -343,18 +552,18 @@ class LongDecimal < LongDecimalBase
|
|
343
552
|
raise TypeError, "1st arg must not be empty string. \"#{num_str.inspect}\"" if len == 0
|
344
553
|
|
345
554
|
# remove spaces and underscores
|
346
|
-
num_str.gsub!
|
347
|
-
num_str.gsub!
|
555
|
+
num_str.gsub!(/\s/, "")
|
556
|
+
num_str.gsub!(/_/, "")
|
348
557
|
|
349
558
|
# handle sign
|
350
|
-
num_str.gsub!
|
559
|
+
num_str.gsub!(/^\+/, "")
|
351
560
|
negative = false
|
352
|
-
if num_str.gsub!
|
561
|
+
if num_str.gsub!(/^-/, "") then
|
353
562
|
negative = true
|
354
563
|
end
|
355
564
|
|
356
565
|
# split in parts before and after decimal point
|
357
|
-
num_arr = num_str.split
|
566
|
+
num_arr = num_str.split(/\./)
|
358
567
|
if num_arr.length > 2 then
|
359
568
|
raise TypeError, "1st arg contains more than one . \"#{num_str.inspect}\""
|
360
569
|
end
|
@@ -363,7 +572,7 @@ class LongDecimal < LongDecimalBase
|
|
363
572
|
num_frac = nil
|
364
573
|
num_exp = nil
|
365
574
|
unless num_rem.nil? then
|
366
|
-
num_arr = num_rem.split
|
575
|
+
num_arr = num_rem.split(/[Ee]/)
|
367
576
|
num_frac = num_arr[0]
|
368
577
|
num_exp = num_arr[1]
|
369
578
|
end
|
@@ -480,6 +689,60 @@ class LongDecimal < LongDecimalBase
|
|
480
689
|
end
|
481
690
|
end
|
482
691
|
|
692
|
+
#
|
693
|
+
# create copy of self round in such a way that the result times
|
694
|
+
# 10**scale is congruent modulo modulus to one of the members of
|
695
|
+
# remainders
|
696
|
+
#
|
697
|
+
# param1: new_scale new scale for result
|
698
|
+
# param2: remainders array of allowed remainders
|
699
|
+
# param3: modulus modulus of the remainders
|
700
|
+
# param4: rounding_mode rounding mode to be applied when information is
|
701
|
+
# lost. defaults to ROUND_UNNECESSARY, which
|
702
|
+
# means that an exception is thrown if rounding
|
703
|
+
# would actually loose any information.
|
704
|
+
# param5: zero_rounding_mode if self is zero, but zero is not among
|
705
|
+
# the available remainders, it has to be
|
706
|
+
# rounded to positive or negative value.
|
707
|
+
# If the rounding_mode does not allow to
|
708
|
+
# determine which of the two values to
|
709
|
+
# use, zero_rounding_mode has to be used
|
710
|
+
# to decide.
|
711
|
+
#
|
712
|
+
def round_to_allowed_remainders(new_scale,
|
713
|
+
remainders,
|
714
|
+
modulus,
|
715
|
+
rounding_mode = LongDecimalRoundingMode::ROUND_UNNECESSARY,
|
716
|
+
zero_rounding_mode = LongDecimalRoundingMode::ZERO_ROUND_UNNECESSARY)
|
717
|
+
|
718
|
+
raise TypeError, "new_scale #{new_scale.inspect} must be integer" unless new_scale.kind_of? Integer
|
719
|
+
raise TypeError, "new_scale #{new_scale.inspect} must be >= 0" unless new_scale >= 0
|
720
|
+
raise TypeError, "remainders must be Array" unless remainders.kind_of? Array
|
721
|
+
raise TypeError, "remainders must be non-empty Array" unless remainders.length > 0
|
722
|
+
raise TypeError, "modulus #{modulus.inspect} must be integer" unless modulus.kind_of? Integer
|
723
|
+
raise TypeError, "modulus #{modulus.inspect} must be >= 2" unless modulus >= 2
|
724
|
+
raise TypeError, "rounding_mode #{rounding_mode.inspect} must be legal rounding rounding_mode" unless rounding_mode.kind_of? RoundingModeClass
|
725
|
+
raise TypeError, "ROUND_HALF_EVEN is not applicable here" if rounding_mode == LongDecimalRoundingMode::ROUND_HALF_EVEN
|
726
|
+
raise TypeError, "zero_rounding_mode #{zero_rounding_mode.inspect} must be legal zero_rounding zero_rounding_mode" unless zero_rounding_mode.kind_of? ZeroRoundingModeClass
|
727
|
+
|
728
|
+
if @scale < new_scale then
|
729
|
+
expanded = self.round_to_scale(new_scale, rounding_mode)
|
730
|
+
return expanded.round_to_allowed_remainders(new_scale, remainders, modulus, rounding_mode, zero_rounding_mode)
|
731
|
+
elsif @scale > new_scale
|
732
|
+
factor = 10**(@scale - new_scale)
|
733
|
+
remainders = remainders.collect do |r|
|
734
|
+
r * factor
|
735
|
+
end
|
736
|
+
modulus *= factor
|
737
|
+
end
|
738
|
+
|
739
|
+
int_val_2 = @int_val.round_to_allowed_remainders(remainders, modulus, rounding_mode, zero_rounding_mode)
|
740
|
+
self_2 = LongDecimal.new(int_val_2, @scale)
|
741
|
+
|
742
|
+
result = self_2.round_to_scale(new_scale, rounding_mode)
|
743
|
+
return result
|
744
|
+
end
|
745
|
+
|
483
746
|
#
|
484
747
|
# convert self into String, which is the decimal representation.
|
485
748
|
# Use trailing zeros, if int_val has them.
|
@@ -558,28 +821,34 @@ class LongDecimal < LongDecimalBase
|
|
558
821
|
return 0.0
|
559
822
|
end
|
560
823
|
|
561
|
-
|
824
|
+
if (self < 0) then
|
825
|
+
return -(-self).to_f
|
826
|
+
end
|
827
|
+
|
828
|
+
dividend = numerator
|
829
|
+
divisor = denominator
|
830
|
+
|
562
831
|
if (divisor == 1) then
|
563
|
-
return
|
564
|
-
elsif
|
832
|
+
return dividend.to_f
|
833
|
+
elsif dividend.abs <= LongMath::MAX_FLOATABLE then
|
565
834
|
if (divisor.abs > LongMath::MAX_FLOATABLE) then
|
566
|
-
|
567
|
-
|
568
|
-
|
835
|
+
q = 10**(scale - Float::MAX_10_EXP)
|
836
|
+
f = (dividend / q).to_f
|
837
|
+
d = divisor / q
|
569
838
|
return f / d
|
570
839
|
else
|
571
|
-
f =
|
840
|
+
f = dividend.to_f
|
572
841
|
return f / divisor
|
573
842
|
end
|
574
|
-
elsif
|
843
|
+
elsif dividend.abs < divisor
|
575
844
|
# self is between -1 and 1
|
576
845
|
|
577
|
-
# factor =
|
846
|
+
# factor = dividend.abs.div(LongMath::MAX_FLOATABLE)
|
578
847
|
# digits = factor.to_ld.int_digits10
|
579
|
-
# return LongDecimal(
|
848
|
+
# return LongDecimal(dividend.div(10**digits), scale -digits).to_f
|
580
849
|
return self.to_s.to_f
|
581
850
|
else
|
582
|
-
q =
|
851
|
+
q = dividend.abs / divisor
|
583
852
|
if (q.abs > 1000000000000000000000)
|
584
853
|
return q.to_f
|
585
854
|
else
|
@@ -1269,7 +1538,7 @@ end # LongDecimal
|
|
1269
1538
|
#
|
1270
1539
|
class LongDecimalQuot < LongDecimalBase
|
1271
1540
|
|
1272
|
-
@RCS_ID='-$Id: long-decimal.rb,v 1.
|
1541
|
+
@RCS_ID='-$Id: long-decimal.rb,v 1.50 2007/07/12 20:46:59 bk1 Exp $-'
|
1273
1542
|
|
1274
1543
|
#
|
1275
1544
|
# constructor
|
@@ -2452,7 +2721,7 @@ module LongMath
|
|
2452
2721
|
#
|
2453
2722
|
def LongMath.exp_internal(x, prec = nil, final_mode = LongMath.standard_mode, j = nil, k = nil, iprec = nil, mode = LongMath.standard_imode, cache_result = true) # down?
|
2454
2723
|
|
2455
|
-
if (prec
|
2724
|
+
if (prec.nil?) then
|
2456
2725
|
if (x.kind_of? LongDecimalBase)
|
2457
2726
|
prec = x.scale
|
2458
2727
|
else
|
@@ -2461,7 +2730,7 @@ module LongMath
|
|
2461
2730
|
end
|
2462
2731
|
check_is_prec(prec, "prec")
|
2463
2732
|
|
2464
|
-
if (final_mode
|
2733
|
+
if (final_mode.nil?)
|
2465
2734
|
final_mode = LongMath.standard_mode
|
2466
2735
|
end
|
2467
2736
|
check_is_mode(final_mode, "final_mode")
|
@@ -2469,7 +2738,8 @@ module LongMath
|
|
2469
2738
|
|
2470
2739
|
# if the result would come out to zero anyway, cut the work
|
2471
2740
|
xi = x.to_i
|
2472
|
-
if (xi < -LongMath::MAX_FLOATABLE) || -((xi.to_f - 1) / LOG10) > prec+10 then
|
2741
|
+
# if (xi < -LongMath::MAX_FLOATABLE) || -((xi.to_f - 1) / LOG10) > prec+10 then
|
2742
|
+
if (xi < -LongMath::MAX_FLOATABLE) || xi + 1 < -prec * LOG10 - LOG2 then
|
2473
2743
|
return LongDecimal(25, prec+2).round_to_scale(prec, final_mode)
|
2474
2744
|
end
|
2475
2745
|
x_was_neg = false
|
@@ -2478,12 +2748,12 @@ module LongMath
|
|
2478
2748
|
x_was_neg = true
|
2479
2749
|
end
|
2480
2750
|
|
2481
|
-
if j
|
2751
|
+
if j.nil? || k.nil? then
|
2482
2752
|
s1 = (prec * LOG10 / LOG2) ** (1.0/3.0)
|
2483
|
-
if (j
|
2753
|
+
if (j.nil?) then
|
2484
2754
|
j = s1.round
|
2485
2755
|
end
|
2486
|
-
if (k
|
2756
|
+
if (k.nil?) then
|
2487
2757
|
k = (s1 + Math.log([1, prec].max) / LOG2).round
|
2488
2758
|
end
|
2489
2759
|
if (x > 1) then
|
@@ -2499,7 +2769,7 @@ module LongMath
|
|
2499
2769
|
check_is_int(j, "j")
|
2500
2770
|
check_is_int(k, "k")
|
2501
2771
|
|
2502
|
-
if (iprec
|
2772
|
+
if (iprec.nil?) then
|
2503
2773
|
iprec = calc_iprec_for_exp(x, prec, x_was_neg)
|
2504
2774
|
end
|
2505
2775
|
check_is_prec(iprec, "iprec")
|
@@ -2704,7 +2974,7 @@ module LongMath
|
|
2704
2974
|
def LongMath.log_internal(x, prec = nil, final_mode = LongMath.standard_mode, iprec = nil, mode = LongMath.standard_imode, cache_result = true)
|
2705
2975
|
|
2706
2976
|
raise TypeError, "x=#{x.inspect} must not be positive" unless x > 0
|
2707
|
-
if (prec
|
2977
|
+
if (prec.nil?) then
|
2708
2978
|
if (x.kind_of? LongDecimalBase)
|
2709
2979
|
prec = x.scale
|
2710
2980
|
else
|
@@ -2713,13 +2983,13 @@ module LongMath
|
|
2713
2983
|
end
|
2714
2984
|
check_is_prec(prec, "prec")
|
2715
2985
|
|
2716
|
-
if (final_mode
|
2986
|
+
if (final_mode.nil?)
|
2717
2987
|
final_mode = LongMath.standard_mode
|
2718
2988
|
end
|
2719
2989
|
check_is_mode(final_mode, "final_mode")
|
2720
2990
|
check_is_mode(mode, "mode")
|
2721
2991
|
|
2722
|
-
if (iprec
|
2992
|
+
if (iprec.nil?) then
|
2723
2993
|
# iprec = ((prec+10)*1.20).round
|
2724
2994
|
iprec = ((prec+12)*1.20).round
|
2725
2995
|
end
|
@@ -2839,27 +3109,51 @@ module LongMath
|
|
2839
3109
|
# internal helper method for calculating the internal precision for power
|
2840
3110
|
#
|
2841
3111
|
def LongMath.calc_iprec_for_power(x, y, prec)
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
3112
|
+
|
3113
|
+
logx_f = nil
|
3114
|
+
if (x.abs <= LongMath::MAX_FLOATABLE)
|
3115
|
+
x_f = x.to_f
|
3116
|
+
logx_f = Math.log(x_f.abs)
|
3117
|
+
else
|
3118
|
+
logx_f = LongMath.log(x, 15, LongMath::ROUND_UP)
|
3119
|
+
end
|
3120
|
+
|
3121
|
+
y_f = nil
|
3122
|
+
if (y.abs <= LongMath::MAX_FLOATABLE) then
|
3123
|
+
y_f = y.to_f
|
3124
|
+
else
|
3125
|
+
y_f = y.round_to_scale(15, LongMath::ROUND_UP)
|
3126
|
+
end
|
3127
|
+
|
2850
3128
|
logx_y_f = logx_f * y_f
|
3129
|
+
if (logx_y_f.abs > LongMath::MAX_FLOATABLE) then
|
3130
|
+
raise ArgumentError, "power would be way too big: y*log(x)=#{logx_y_f}";
|
3131
|
+
end
|
3132
|
+
logx_y_f = logx_y_f.to_f unless logx_y_f.kind_of? Float
|
3133
|
+
|
2851
3134
|
iprec_x = calc_iprec_for_exp(logx_y_f.abs.ceil, prec, logx_y_f < 0)
|
2852
|
-
# iprec_x = calc_iprec_for_exp(logx_y_f, prec, logx_y_f < 0) + 10
|
2853
3135
|
iprec_y = iprec_x
|
2854
3136
|
iprec = iprec_x + 2
|
2855
3137
|
if (logx_f < 0)
|
2856
3138
|
iprec_x -= (logx_f/LOG10).round
|
2857
3139
|
end
|
2858
|
-
if (
|
3140
|
+
if (y_f.abs < 1)
|
3141
|
+
logy_f = nil
|
3142
|
+
if (y_f.kind_of? Float) then
|
3143
|
+
logy_f = Math.log(y_f.abs)
|
3144
|
+
else
|
3145
|
+
logy_f = LongMath.log(y_f.abs, 15, LongMath::ROUND_UP)
|
3146
|
+
if (logy_f.abs > LongMath::MAX_FLOATABLE) then
|
3147
|
+
raise ArgumentError, "exponent would be way too big: y=#{y} logy_f=#{logy_f}";
|
3148
|
+
end
|
3149
|
+
logy_f = logy_f.to_f
|
3150
|
+
end
|
3151
|
+
# puts("x=#{x} y=#{y} x_f=#{x_f} y_f=#{y_f} logx_f=#{logx_f} logy_f=#{logy_f} logx_y_f=#{logx_y_f}\n")
|
2859
3152
|
iprec_y -= (logy_f/LOG10).round
|
2860
3153
|
end
|
3154
|
+
# puts("x=#{x} y=#{y} x_f=#{x_f} y_f=#{y_f} logx_f=#{logx_f} logy_f=#{logy_f} logx_y_f=#{logx_y_f}\n")
|
2861
3155
|
# puts("\niprec: x=#{x} y=#{y} iprec=#{iprec} iprec_x=#{iprec_x} iprec_y=#{iprec_y}\n")
|
2862
|
-
[ iprec, iprec_x, iprec_y ]
|
3156
|
+
[ iprec, iprec_x, iprec_y, logx_y_f ]
|
2863
3157
|
|
2864
3158
|
end
|
2865
3159
|
|
@@ -2893,7 +3187,16 @@ module LongMath
|
|
2893
3187
|
return LongDecimal.one!(prec)
|
2894
3188
|
end
|
2895
3189
|
|
2896
|
-
|
3190
|
+
# els
|
3191
|
+
# could be result with our precision
|
3192
|
+
# x ** y <= 10**-s/2 <=> y * log(x) <= -s log(10) - log(2)
|
3193
|
+
|
3194
|
+
iprec, iprec_x, iprec_y, logx_y_f = calc_iprec_for_power(x, y, prec)
|
3195
|
+
if (x < 1 && y > 0 || x > 1 && y < 0) then
|
3196
|
+
if (logx_y_f <= - prec * LOG10 - LOG2) then
|
3197
|
+
return LongDecimal.zero!(prec)
|
3198
|
+
end
|
3199
|
+
end
|
2897
3200
|
# puts("x=#{x} y=#{y} iprec=#{iprec} iprec_x=#{iprec_x} iprec_y=#{iprec_y} prec=#{prec}")
|
2898
3201
|
|
2899
3202
|
unless (x.kind_of? LongDecimalBase) || (x.kind_of? Integer)
|
@@ -2904,9 +3207,20 @@ module LongMath
|
|
2904
3207
|
end
|
2905
3208
|
|
2906
3209
|
# try shortcut if exponent is an integer
|
2907
|
-
if (y.kind_of? LongDecimalBase) && y.is_int?
|
3210
|
+
if (y.kind_of? LongDecimalBase) && y.is_int? then
|
2908
3211
|
y = y.to_i
|
2909
3212
|
end
|
3213
|
+
unless (y.kind_of? Integer)
|
3214
|
+
y2 = y*2
|
3215
|
+
if (y2.kind_of? LongDecimalBase) && y2.is_int? then
|
3216
|
+
y2 = y2.to_i
|
3217
|
+
puts("y2=#{y2}")
|
3218
|
+
end
|
3219
|
+
if (y2.kind_of? Integer)
|
3220
|
+
x = LongMath.sqrt(x, 2*iprec_x, mode)
|
3221
|
+
y = y2
|
3222
|
+
end
|
3223
|
+
end
|
2910
3224
|
if (y.kind_of? Integer)
|
2911
3225
|
unless x.kind_of? LongDecimal
|
2912
3226
|
# x = x.to_ld(prec)
|
@@ -2925,6 +3239,8 @@ module LongMath
|
|
2925
3239
|
y = y.to_ld(iprec_y, mode)
|
2926
3240
|
end
|
2927
3241
|
|
3242
|
+
# if x < 1 && y < 0 then
|
3243
|
+
# working with x < 1 should be improved, less precision needed
|
2928
3244
|
if x < 1 then
|
2929
3245
|
# since we do not allow x < 0 and we have handled x = 0 already,
|
2930
3246
|
# we can be sure that x is no integer, so it has been converted
|
@@ -2966,6 +3282,8 @@ module LongMath
|
|
2966
3282
|
check_is_prec(prec, "prec")
|
2967
3283
|
check_is_mode(mode, "mode")
|
2968
3284
|
|
3285
|
+
cnt = 0
|
3286
|
+
|
2969
3287
|
if (y.zero?)
|
2970
3288
|
return 1
|
2971
3289
|
elsif ! (x.kind_of? LongDecimalBase) || x.scale * y.abs <= prec
|
@@ -2982,17 +3300,23 @@ module LongMath
|
|
2982
3300
|
z = x
|
2983
3301
|
while true do
|
2984
3302
|
|
3303
|
+
cnt++
|
2985
3304
|
y -= 1
|
2986
3305
|
if (y.zero?)
|
2987
3306
|
break
|
2988
3307
|
end
|
2989
3308
|
while (y & 0x01) == 0 do
|
2990
3309
|
|
3310
|
+
cnt++
|
2991
3311
|
y = y >> 1
|
2992
3312
|
x = (x*x)
|
2993
3313
|
if (x.kind_of? LongDecimalBase)
|
2994
3314
|
x = x.round_to_scale(prec, mode)
|
2995
3315
|
end
|
3316
|
+
if (cnt > 1000)
|
3317
|
+
puts("ipower x=#{x} y=#{y} cnt=#{cnt} z=#{z}")
|
3318
|
+
cnt = 0
|
3319
|
+
end
|
2996
3320
|
|
2997
3321
|
end
|
2998
3322
|
z = (z*x)
|
@@ -3014,7 +3338,7 @@ module LongMath
|
|
3014
3338
|
#
|
3015
3339
|
def LongMath.power_internal(x, y, prec = nil, final_mode = LongMath.standard_mode, iprec = nil, mode = LongMath.standard_imode)
|
3016
3340
|
|
3017
|
-
if (prec
|
3341
|
+
if (prec.nil?) then
|
3018
3342
|
if (x.kind_of? LongDecimalBase) && (y.kind_of? LongDecimalBase)
|
3019
3343
|
prec = [x.scale, y.scale].max
|
3020
3344
|
elsif (x.kind_of? LongDecimalBase)
|
@@ -3027,7 +3351,7 @@ module LongMath
|
|
3027
3351
|
end
|
3028
3352
|
check_is_prec(prec, "prec")
|
3029
3353
|
|
3030
|
-
if (final_mode
|
3354
|
+
if (final_mode.nil?)
|
3031
3355
|
final_mode = LongMath.standard_mode
|
3032
3356
|
end
|
3033
3357
|
check_is_mode(final_mode, "final_mode")
|
@@ -3039,7 +3363,7 @@ module LongMath
|
|
3039
3363
|
return LongDecimal.zero!(prec)
|
3040
3364
|
end
|
3041
3365
|
|
3042
|
-
if (iprec
|
3366
|
+
if (iprec.nil?) then
|
3043
3367
|
iprec, iprec_x, iprec_y = calc_iprec_for_power(x, y, prec)
|
3044
3368
|
end
|
3045
3369
|
unless (x.kind_of? LongDecimal)
|