Improve taylor series calculation of exp and sin by binary splitting method #433
+147
−116
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
With #407,
exp(x, N)andsin(x, N)calculation improves fromO(N^3/logN)toO(N^2).This pull request further improves
O(N^2)toO(N*(logN)**a)where a is about 3 or 4.Drops Ruby 2.5 support to use
(1..).bsearchBinary Splitting method
If
xcan be represented assmall_numerator/small_denominator,exp(x)andsin(x)can be calculated fast using binary splitting method.This technique is normally used in PI calculation.
Here's an example of calculating
exp(1).The prerequisite is that all numbers are small in the initial step.
In each step, average number of digits doubles and number of terms halves.
Split digits (decimal form of bit-burst algorithm)
Normally,
xhas many digits, so simply applying binary splitting method toexp(x)isn't fast.Now lets split
xinto several parts.Number of digits doubled, number of terms required for convergence is almost halved.
So each
expcalculation performs well with binary splitting method.We need to repeat binary splitting method for about
logNtimes, so the total time complexity will be quasilinear time.BigMath.sin
Almost the same as
BigMath.exp.Restore
sin(x.xxxxxxxxxxxxxxxx)fromsin(x.xx),sin(0.00xx),sin(0.0000xxxx),sin(0.00000000xxxxxxxx)using trigonometric addition theorem.BigMath.log and BigMath.atan
Since
expandsinbecomes orders of magnitude faster, implementinglogandatanby newton's method is better.log(x): Solveexp(y) - x = 0atan(x): Solvetan(y) - x = 0There is an option to implement binary splitting method to
logandatantaylor series, but implementation will be more complicated, needs special care to make|x| ≪ 1, and convergence is slower thanexpandsin.