예제 #1
0
        /// <summary>
        /// Tried the newton method for logs, but the exponential function is too slow to do it.
        /// </summary>
        private void LogNewton()
        {
            if (mantissa.IsZero() || mantissa.Sign)
            {
                return;
            }

            //Compute ln2.
            if (ln2cache == null || mantissa.Precision.NumBits > ln2cache.mantissa.Precision.NumBits)
            {
                CalculateLog2(mantissa.Precision.NumBits);
            }

            int numBits = mantissa.Precision.NumBits;

            //Use inverse exp function with Newton's method.
            BigFloat xn = new BigFloat(this);
            BigFloat oldExponent = new BigFloat(xn.exponent, mantissa.Precision);
            xn.exponent = 0;
            this.exponent = 0;
            //Hack to subtract 1
            xn.mantissa.ClearBit(numBits - 1);
            //x0 = (x - 1) * log2 - this is a straight line fit between log(1) = 0 and log(2) = ln2
            xn.Mul(ln2cache);
            //x0 = (x - 1) * log2 + C - this corrects for minimum error over the range.
            xn.Add(logNewtonConstant);
            BigFloat term = new BigFloat(mantissa.Precision);
            BigFloat one = new BigFloat(1, mantissa.Precision);

            int precision = 32;
            int normalPrecision = mantissa.Precision.NumBits;

            int iterations = 0;

            while (true)
            {
                term.Assign(xn);
                term.mantissa.Sign = true;
                term.Exp(precision);
                term.Mul(this);
                term.Sub(one);

                iterations++;
                if (term.exponent < -((precision >> 1) - 4))
                {
                    if (precision == normalPrecision)
                    {
                        if (term.exponent < -(precision - 4)) break;
                    }
                    else
                    {
                        precision = precision << 1;
                        if (precision > normalPrecision) precision = normalPrecision;
                    }
                }

                xn.Add(term);
            }

            //log(2^n*s) = log(2^n) + log(s) = nlog(2) + log(s)
            term.Assign(ln2cache);
            term.Mul(oldExponent);

            this.Assign(xn);
            this.Add(term);
        }
예제 #2
0
 /// <summary>
 /// The exponential function. Less accurate for high exponents, scales poorly with the number
 /// of bits. This is quite fast for low-precision arguments.
 /// </summary>
 public static BigFloat Exp(BigFloat n1)
 {
     BigFloat res = new BigFloat(n1);
     n1.Exp();
     return n1;
 }