/// <summary> /// Compute e^x to a given scale. <br />Break x into its whole and /// fraction parts and compute (e^(1 + fraction/whole))^whole using /// Taylor's formula. /// </summary> /// <param name="scale"> /// the desired <c>scale</c> of the result. (where the <c>scale</c> is /// the number of digits to the right of the decimal point. /// </param> /// <returns> /// the result value /// </returns> /// <exception cref="ArgumentException"> /// if <c>scale</c> <= 0. /// </exception> public static DecimalX Exp(this DecimalX x, int scale) { if (scale <= 0) { throw new ArgumentException(InvalidScale2); } if (x.Signum() == 0) { return(DecimalX.Create(1)); } if (x.Signum() == -1) { var a = DecimalX.Create(1); return(a.CDivide(x.Negate().Exp(scale), scale, RoundingMode.HalfEven)); } // Compute the whole part of x. var xWhole = DecimalX.Rescale(x, 0, RoundingMode.Down); // If there isn't a whole part, compute and return e^x. if (xWhole.Signum() == 0) { return(expTaylor(x, scale)); } // Compute the fraction part of x. var xFraction = x.Subtract(xWhole); // z = 1 + fraction/whole var b = DecimalX.Create(1); var z = b.Add(xFraction.CDivide(xWhole, scale, RoundingMode.HalfEven)); // t = e^z var t = expTaylor(z, scale); var maxLong = DecimalX.Create(long.MaxValue); var tempRes = DecimalX.Create(1); // Compute and return t^whole using IntPower(). // If whole > Int64.MaxValue, then first compute products // of e^Int64.MaxValue. while (xWhole.CompareTo(maxLong) >= 0) { tempRes = tempRes.Multiply(t.IntPower(long.MaxValue, scale)); tempRes = DecimalX.Rescale(tempRes, -scale, RoundingMode.HalfEven); xWhole = xWhole.Subtract(maxLong); } var result = tempRes.Multiply(t.IntPower(xWhole.ToLong(), scale)); return(DecimalX.Rescale(result, -scale, RoundingMode.HalfEven)); }