mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2024-12-23 03:03:13 +00:00
71 lines
1.6 KiB
Go
71 lines
1.6 KiB
Go
|
package bigfft
|
||
|
|
||
|
import (
|
||
|
"math/big"
|
||
|
)
|
||
|
|
||
|
// FromDecimalString converts the base 10 string
|
||
|
// representation of a natural (non-negative) number
|
||
|
// into a *big.Int.
|
||
|
// Its asymptotic complexity is less than quadratic.
|
||
|
func FromDecimalString(s string) *big.Int {
|
||
|
var sc scanner
|
||
|
z := new(big.Int)
|
||
|
sc.scan(z, s)
|
||
|
return z
|
||
|
}
|
||
|
|
||
|
type scanner struct {
|
||
|
// powers[i] is 10^(2^i * quadraticScanThreshold).
|
||
|
powers []*big.Int
|
||
|
}
|
||
|
|
||
|
func (s *scanner) chunkSize(size int) (int, *big.Int) {
|
||
|
if size <= quadraticScanThreshold {
|
||
|
panic("size < quadraticScanThreshold")
|
||
|
}
|
||
|
pow := uint(0)
|
||
|
for n := size; n > quadraticScanThreshold; n /= 2 {
|
||
|
pow++
|
||
|
}
|
||
|
// threshold * 2^(pow-1) <= size < threshold * 2^pow
|
||
|
return quadraticScanThreshold << (pow - 1), s.power(pow - 1)
|
||
|
}
|
||
|
|
||
|
func (s *scanner) power(k uint) *big.Int {
|
||
|
for i := len(s.powers); i <= int(k); i++ {
|
||
|
z := new(big.Int)
|
||
|
if i == 0 {
|
||
|
if quadraticScanThreshold%14 != 0 {
|
||
|
panic("quadraticScanThreshold % 14 != 0")
|
||
|
}
|
||
|
z.Exp(big.NewInt(1e14), big.NewInt(quadraticScanThreshold/14), nil)
|
||
|
} else {
|
||
|
z.Mul(s.powers[i-1], s.powers[i-1])
|
||
|
}
|
||
|
s.powers = append(s.powers, z)
|
||
|
}
|
||
|
return s.powers[k]
|
||
|
}
|
||
|
|
||
|
func (s *scanner) scan(z *big.Int, str string) {
|
||
|
if len(str) <= quadraticScanThreshold {
|
||
|
z.SetString(str, 10)
|
||
|
return
|
||
|
}
|
||
|
sz, pow := s.chunkSize(len(str))
|
||
|
// Scan the left half.
|
||
|
s.scan(z, str[:len(str)-sz])
|
||
|
// FIXME: reuse temporaries.
|
||
|
left := Mul(z, pow)
|
||
|
// Scan the right half
|
||
|
s.scan(z, str[len(str)-sz:])
|
||
|
z.Add(z, left)
|
||
|
}
|
||
|
|
||
|
// quadraticScanThreshold is the number of digits
|
||
|
// below which big.Int.SetString is more efficient
|
||
|
// than subquadratic algorithms.
|
||
|
// 1232 digits fit in 4096 bits.
|
||
|
const quadraticScanThreshold = 1232
|