github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/util/math/exp.go (about) 1 package math 2 3 import "github.com/filecoin-project/go-state-types/big" 4 5 // ExpBySquaring takes a Q.128 base b and an int64 exponent n and computes n^b 6 // using the exponentiation by squaring method, returning a Q.128 value. 7 func ExpBySquaring(base big.Int, n int64) big.Int { 8 one := big.Lsh(big.NewInt(1), Precision128) 9 // Base cases 10 if n == 0 { 11 return one 12 } 13 if n == 1 { 14 return base 15 } 16 17 // Recurse 18 if n < 0 { 19 inverseBase := big.Div(big.Lsh(one, Precision128), base) // Q.256 / Q.128 => Q.128 20 return ExpBySquaring(inverseBase, -n) 21 } 22 baseSquared := big.Mul(base, base) // Q.128 * Q.128 => Q.256 23 baseSquared = big.Rsh(baseSquared, Precision128) // Q.256 => Q.128 24 if n%2 == 0 { 25 return ExpBySquaring(baseSquared, n/2) 26 } 27 result := big.Mul(base, ExpBySquaring(baseSquared, (n-1)/2)) // Q.128 * Q.128 => Q.256 28 return big.Rsh(result, Precision128) // Q.256 => Q.128 29 }