scan.go 1.6 KB

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