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  }