Skip to content

Conversation

tompng
Copy link
Member

@tompng tompng commented Oct 4, 2025

When y.exponent is several thousand or more, x**y was slow because exponentiation by squaring requires several thousands of multiplications.
Use exp and log in such case.

irb(main):002> n=BigDecimal('1e+4000'); (1+1/n).power(n, 100)
processing time: 14.743024s => 0.003061s
=> 0.2718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427e1
if frac_part.zero? && y.exponent < Math.log(prec) * 5 + 20
  # Use exponentiation by squaring
else
  # Use exp(y*log(x))
end

Appropriate threshold of y.exponent depends on exp, log, and multiplication performance.
This condition is tuned with prec <= 1000000 and #407 #433 applied.
Theoretically, the condition should be y.exponent > coef * log(prec)**a where a is between 1..3, I guess.

When y.exponent is several thousand or more, x**y was slow because exponentiation by squaring requires several thousands of multiplications.
Use exp and log in such case.
Needed to calaculate (1+1/n).power(n, prec)
@tompng tompng merged commit a267ca7 into ruby:master Oct 6, 2025
99 of 128 checks passed
@tompng tompng deleted the power_by_huge branch October 6, 2025 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant