Exp sets d = e**x.
(d, x *Decimal)
| 872 | |
| 873 | // Exp sets d = e**x. |
| 874 | func (c *Context) Exp(d, x *Decimal) (Condition, error) { |
| 875 | // See: Variable Precision Exponential Function, T. E. Hull and A. Abrham, ACM |
| 876 | // Transactions on Mathematical Software, Vol 12 #2, pp79-91, ACM, June 1986. |
| 877 | |
| 878 | if c.shouldSetAsNaN(x, nil) { |
| 879 | return c.setAsNaN(d, x, nil) |
| 880 | } |
| 881 | if x.Form == Infinite { |
| 882 | if x.Negative { |
| 883 | d.Set(decimalZero) |
| 884 | } else { |
| 885 | d.Set(decimalInfinity) |
| 886 | } |
| 887 | return 0, nil |
| 888 | } |
| 889 | |
| 890 | if x.IsZero() { |
| 891 | d.Set(decimalOne) |
| 892 | return 0, nil |
| 893 | } |
| 894 | |
| 895 | if c.Precision == 0 { |
| 896 | return 0, errors.New(errZeroPrecisionStr) |
| 897 | } |
| 898 | |
| 899 | res := Inexact | Rounded |
| 900 | |
| 901 | // Stage 1 |
| 902 | cp := c.Precision |
| 903 | var tmp1 Decimal |
| 904 | tmp1.Abs(x) |
| 905 | if f, err := tmp1.Float64(); err == nil { |
| 906 | // This algorithm doesn't work if currentprecision*23 < |x|. Attempt to |
| 907 | // increase the working precision if needed as long as it isn't too large. If |
| 908 | // it is too large, don't bump the precision, causing an early overflow return. |
| 909 | if ncp := f / 23; ncp > float64(cp) && ncp < 1000 { |
| 910 | cp = uint32(math.Ceil(ncp)) |
| 911 | } |
| 912 | } |
| 913 | var tmp2 Decimal |
| 914 | tmp2.SetInt64(int64(cp) * 23) |
| 915 | // if abs(x) > 23*currentprecision; assert false |
| 916 | if tmp1.Cmp(&tmp2) > 0 { |
| 917 | res |= Overflow |
| 918 | if x.Sign() < 0 { |
| 919 | res = res.negateOverflowFlags() |
| 920 | res |= Clamped |
| 921 | d.SetFinite(0, c.etiny()) |
| 922 | } else { |
| 923 | d.Set(decimalInfinity) |
| 924 | } |
| 925 | return c.goError(res) |
| 926 | } |
| 927 | // if abs(x) <= setexp(.9, -currentprecision); then result 1 |
| 928 | tmp2.SetFinite(9, int32(-cp)-1) |
| 929 | if tmp1.Cmp(&tmp2) <= 0 { |
| 930 | d.Set(decimalOne) |
| 931 | return c.goError(res) |
no test coverage detected