NTT multiplication and Newton-Raphson division #407
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.
Multiplication gets maximum 800,000 times faster.
Raises
Multiply size too large (ArgumentError)
if size is larger than the limitation:x * y
requires[x.n_significant_digits, y.n_significant_digits].min <= 603979776
Basic policy of this pull request
NTT(Numeric Theory Translation) multiplication
Calculates multiplication/convolution using NTT with three primes.
Consider calculating convolution of two arrays. Each array is of size
N
witharray[i] in 0..999999999
.Maximum value of
convolution[i]
is999999999**2 * N
. This value is larger than 64bit and smaller than 96bit, so we need three 32-bit primes:29<<27|1
,26<<27|1
,24<<27|1
.These are three largest 32-bit primes that satisfies
P > 999999999
, andP-1
need to be a multiple of large powers of two.Constraints from this primes, maximum
N
is1<<27
.Combination of primes/sizes
Multiplication of various size bigdecimal
Considering
xx_xx_xx * yy
Calculate by
convolution(ntt(xx_xx_xx), ntt(00_00_yy))
is possible, but repeatingconvolution(ntt(xx), ntt(yy))
is faster.If n_significant_digits is both larger than
1<<<26 == 603979776
, multiplication fails with Error(too large).Newton-Raphson division
X / Y
can be calculated byX * Yinv
and
Yinv
can be calculated only by add/sub/mult using Newton's method.Division of various size bigdecimal
Considering
1111_1111_1111_1111.div(7777_7777_7777)
Required precision is 4. Calculating inverse of 7777_7777_7777 in 4 digit is enough.
1111_1111_1111_1111 * 1.285e-12 == 1428
Considering
1111_1111_1111_1111.div(7777)
We can calculate this by repeating
xxxx_xxxx.divmod(7777)
3 times.Calculating inverse of 7777 in 4 digit is enough.
Generic case: Split X into several blocks
xxx_xxxxx_xxxxx_xxxxx / yyyy
Can be calculated by repeating
xxxx_xxxxx.divmod(yyyy)
3 times.xxx_xxxx_xxxx / yyyyy
Can be calculated by repeating
xxxxx_xxxx.divmod(yyyyy)
2 times.xxxxx_xxxxxxx / yyyyy
Can be calculated by repeating
xxxxxx_xxxxxxx.divmod(yyyyy)
1 time.Tests
All bigdecimal test passes with
NTT_MULTIPLICATION_THRESHOLD==1
andNEWTON_RAPHSON_DIVISION_THRESHOLD==1
(All mult/div uses NTT and Newton-Raphson)These large multiplication test passes. (Too slow to add to CI)