MCPcopy
hub / github.com/shopspring/decimal / ExpTaylor

Method ExpTaylor

decimal.go:1054–1108  ·  view source on GitHub ↗

ExpTaylor calculates the natural exponent of decimal (e to the power of d) using Taylor series expansion. Precision argument specifies how precise the result must be (number of digits after decimal point). Negative precision is allowed. ExpTaylor is much faster for large precision values than ExpHu

(precision int32)

Source from the content-addressed store, hash-verified

1052// NewFromFloat(26.1).ExpTaylor(-10).String()
1053// d.String() // output: "220000000000"
1054func (d Decimal) ExpTaylor(precision int32) (Decimal, error) {
1055 // Note(mwoss): Implementation can be optimized by exclusively using big.Int API only
1056 if d.IsZero() {
1057 return Decimal{oneInt, 0}.Round(precision), nil
1058 }
1059
1060 var epsilon Decimal
1061 var divPrecision int32
1062 if precision < 0 {
1063 epsilon = New(1, -1)
1064 divPrecision = 8
1065 } else {
1066 epsilon = New(1, -precision-1)
1067 divPrecision = precision + 1
1068 }
1069
1070 decAbs := d.Abs()
1071 pow := d.Abs()
1072 factorial := New(1, 0)
1073
1074 result := New(1, 0)
1075
1076 for i := int64(1); ; {
1077 step := pow.DivRound(factorial, divPrecision)
1078 result = result.Add(step)
1079
1080 // Stop Taylor series when current step is smaller than epsilon
1081 if step.Cmp(epsilon) < 0 {
1082 break
1083 }
1084
1085 pow = pow.Mul(decAbs)
1086
1087 i++
1088
1089 // Calculate next factorial number or retrieve cached value
1090 if len(factorials) >= int(i) && !factorials[i-1].IsZero() {
1091 factorial = factorials[i-1]
1092 } else {
1093 // To avoid any race conditions, firstly the zero value is appended to a slice to create
1094 // a spot for newly calculated factorial. After that, the zero value is replaced by calculated
1095 // factorial using the index notation.
1096 factorial = factorials[i-2].Mul(New(i, 0))
1097 factorials = append(factorials, Zero)
1098 factorials[i-1] = factorial
1099 }
1100 }
1101
1102 if d.Sign() < 0 {
1103 result = New(1, 0).DivRound(result, precision+1)
1104 }
1105
1106 result = result.Round(precision)
1107 return result, nil
1108}
1109
1110// Ln calculates natural logarithm of d.
1111// Precision argument specifies how precise the result must be (number of digits after decimal point).

Callers 5

LnMethod · 0.95
TestDecimal_ExpTaylorFunction · 0.80
PowMethod · 0.80
PowWithPrecisionMethod · 0.80

Calls 9

IsZeroMethod · 0.95
AbsMethod · 0.95
SignMethod · 0.95
NewFunction · 0.85
DivRoundMethod · 0.80
AddMethod · 0.80
CmpMethod · 0.80
MulMethod · 0.80
RoundMethod · 0.45

Tested by 2

TestDecimal_ExpTaylorFunction · 0.64