[822] | 1 | package bigfft
|
---|
| 2 |
|
---|
| 3 | import (
|
---|
| 4 | "math/big"
|
---|
| 5 | )
|
---|
| 6 |
|
---|
| 7 | // FromDecimalString converts the base 10 string
|
---|
| 8 | // representation of a natural (non-negative) number
|
---|
| 9 | // into a *big.Int.
|
---|
| 10 | // Its asymptotic complexity is less than quadratic.
|
---|
| 11 | func FromDecimalString(s string) *big.Int {
|
---|
| 12 | var sc scanner
|
---|
| 13 | z := new(big.Int)
|
---|
| 14 | sc.scan(z, s)
|
---|
| 15 | return z
|
---|
| 16 | }
|
---|
| 17 |
|
---|
| 18 | type scanner struct {
|
---|
| 19 | // powers[i] is 10^(2^i * quadraticScanThreshold).
|
---|
| 20 | powers []*big.Int
|
---|
| 21 | }
|
---|
| 22 |
|
---|
| 23 | func (s *scanner) chunkSize(size int) (int, *big.Int) {
|
---|
| 24 | if size <= quadraticScanThreshold {
|
---|
| 25 | panic("size < quadraticScanThreshold")
|
---|
| 26 | }
|
---|
| 27 | pow := uint(0)
|
---|
| 28 | for n := size; n > quadraticScanThreshold; n /= 2 {
|
---|
| 29 | pow++
|
---|
| 30 | }
|
---|
| 31 | // threshold * 2^(pow-1) <= size < threshold * 2^pow
|
---|
| 32 | return quadraticScanThreshold << (pow - 1), s.power(pow - 1)
|
---|
| 33 | }
|
---|
| 34 |
|
---|
| 35 | func (s *scanner) power(k uint) *big.Int {
|
---|
| 36 | for i := len(s.powers); i <= int(k); i++ {
|
---|
| 37 | z := new(big.Int)
|
---|
| 38 | if i == 0 {
|
---|
| 39 | if quadraticScanThreshold%14 != 0 {
|
---|
| 40 | panic("quadraticScanThreshold % 14 != 0")
|
---|
| 41 | }
|
---|
| 42 | z.Exp(big.NewInt(1e14), big.NewInt(quadraticScanThreshold/14), nil)
|
---|
| 43 | } else {
|
---|
| 44 | z.Mul(s.powers[i-1], s.powers[i-1])
|
---|
| 45 | }
|
---|
| 46 | s.powers = append(s.powers, z)
|
---|
| 47 | }
|
---|
| 48 | return s.powers[k]
|
---|
| 49 | }
|
---|
| 50 |
|
---|
| 51 | func (s *scanner) scan(z *big.Int, str string) {
|
---|
| 52 | if len(str) <= quadraticScanThreshold {
|
---|
| 53 | z.SetString(str, 10)
|
---|
| 54 | return
|
---|
| 55 | }
|
---|
| 56 | sz, pow := s.chunkSize(len(str))
|
---|
| 57 | // Scan the left half.
|
---|
| 58 | s.scan(z, str[:len(str)-sz])
|
---|
| 59 | // FIXME: reuse temporaries.
|
---|
| 60 | left := Mul(z, pow)
|
---|
| 61 | // Scan the right half
|
---|
| 62 | s.scan(z, str[len(str)-sz:])
|
---|
| 63 | z.Add(z, left)
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | // quadraticScanThreshold is the number of digits
|
---|
| 67 | // below which big.Int.SetString is more efficient
|
---|
| 68 | // than subquadratic algorithms.
|
---|
| 69 | // 1232 digits fit in 4096 bits.
|
---|
| 70 | const quadraticScanThreshold = 1232
|
---|