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.
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.