github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/util/math/expneg.go (about)

     1  package math
     2  
     3  import (
     4  	"math/big"
     5  )
     6  
     7  var (
     8  	// Coefficents in Q.128 format
     9  	expNumCoef  []*big.Int
    10  	expDenoCoef []*big.Int
    11  )
    12  
    13  func init() {
    14  
    15  	// parameters are in integer format,
    16  	// coefficients are *2^-128 of that
    17  	// so we can just load them if we treat them as Q.128
    18  	num := []string{
    19  		"-648770010757830093818553637600",
    20  		"67469480939593786226847644286976",
    21  		"-3197587544499098424029388939001856",
    22  		"89244641121992890118377641805348864",
    23  		"-1579656163641440567800982336819953664",
    24  		"17685496037279256458459817590917169152",
    25  		"-115682590513835356866803355398940131328",
    26  		"340282366920938463463374607431768211456",
    27  	}
    28  	expNumCoef = Parse(num)
    29  
    30  	deno := []string{
    31  		"1225524182432722209606361",
    32  		"114095592300906098243859450",
    33  		"5665570424063336070530214243",
    34  		"194450132448609991765137938448",
    35  		"5068267641632683791026134915072",
    36  		"104716890604972796896895427629056",
    37  		"1748338658439454459487681798864896",
    38  		"23704654329841312470660182937960448",
    39  		"259380097567996910282699886670381056",
    40  		"2250336698853390384720606936038375424",
    41  		"14978272436876548034486263159246028800",
    42  		"72144088983913131323343765784380833792",
    43  		"224599776407103106596571252037123047424",
    44  		"340282366920938463463374607431768211456",
    45  	}
    46  	expDenoCoef = Parse(deno)
    47  }
    48  
    49  // ExpNeg accepts x in Q.128 format and computes e^-x.
    50  // It is most precise within [0, 1.725) range, where error is less than 3.4e-30.
    51  // Over the [0, 5) range its error is less than 4.6e-15.
    52  // Output is in Q.128 format.
    53  func ExpNeg(x *big.Int) *big.Int {
    54  	// exp is approximated by rational function
    55  	// polynomials of the rational function are evaluated using Horner's method
    56  	num := Polyval(expNumCoef, x)   // Q.128
    57  	deno := Polyval(expDenoCoef, x) // Q.128
    58  
    59  	num = num.Lsh(num, Precision128) // Q.256
    60  	return num.Div(num, deno)        // Q.256 / Q.128 => Q.128
    61  }