Skip to content

Commit 8ac5976

Browse files
committed
Use decimal_shift in log and exp calculation
1 parent 12ff693 commit 8ac5976

File tree

1 file changed

+24
-27
lines changed

1 file changed

+24
-27
lines changed

lib/bigdecimal.rb

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def self.log(x, prec)
205205
if x > 10 || x < 0.1
206206
log10 = log(BigDecimal(10), prec)
207207
exponent = x.exponent
208-
x *= BigDecimal("1e#{-x.exponent}")
208+
x = x._decimal_shift(-exponent)
209209
if x < 0.3
210210
x *= 10
211211
exponent -= 1
@@ -269,33 +269,30 @@ def self.exp(x, prec)
269269
return BigDecimal(1) if x.zero?
270270
return BigDecimal(1).div(exp(-x, prec), prec) if x < 0
271271

272-
BigDecimal.save_limit do
273-
BigDecimal.limit(0)
274-
# exp(x * 10**cnt) = exp(x)**(10**cnt)
275-
cnt = x > 1 ? x.exponent : 0
276-
prec2 = prec + BigDecimal.double_fig + cnt
277-
x *= BigDecimal("1e-#{cnt}")
278-
xn = BigDecimal(1)
279-
y = BigDecimal(1)
280-
281-
# Taylor series for exp(x) around 0
282-
1.step do |i|
283-
n = prec2 + xn.exponent
284-
break if n <= 0 || xn.zero?
285-
x = x.mult(1, n)
286-
xn = xn.mult(x, n).div(i, n)
287-
y = y.add(xn, prec2)
288-
end
289-
290-
# calculate exp(x * 10**cnt) from exp(x)
291-
# exp(x * 10**k) = exp(x * 10**(k - 1)) ** 10
292-
cnt.times do
293-
y2 = y.mult(y, prec2)
294-
y5 = y2.mult(y2, prec2).mult(y, prec2)
295-
y = y5.mult(y5, prec2)
296-
end
272+
# exp(x * 10**cnt) = exp(x)**(10**cnt)
273+
cnt = x > 1 ? x.exponent : 0
274+
prec2 = prec + BigDecimal.double_fig + cnt
275+
x = x._decimal_shift(-cnt)
276+
xn = BigDecimal(1)
277+
y = BigDecimal(1)
278+
279+
# Taylor series for exp(x) around 0
280+
1.step do |i|
281+
n = prec2 + xn.exponent
282+
break if n <= 0 || xn.zero?
283+
x = x.mult(1, n)
284+
xn = xn.mult(x, n).div(i, n)
285+
y = y.add(xn, prec2)
286+
end
297287

298-
y.mult(1, prec)
288+
# calculate exp(x * 10**cnt) from exp(x)
289+
# exp(x * 10**k) = exp(x * 10**(k - 1)) ** 10
290+
cnt.times do
291+
y2 = y.mult(y, prec2)
292+
y5 = y2.mult(y2, prec2).mult(y, prec2)
293+
y = y5.mult(y5, prec2)
299294
end
295+
296+
y.mult(1, prec)
300297
end
301298
end

0 commit comments

Comments
 (0)