Exemple #1
0
        /// <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> &lt;= 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));
        }