Beispiel #1
0
    /// <summary>
    /// Returns 2 raised to the specified power.
    /// Provides at least 6 decimals of accuracy.
    /// </summary>
    internal static FP Pow2(FP x)
    {
        if (x.RawValue == 0)
        {
            return(FP.One);
        }

        // Avoid negative arguments by exploiting that exp(-x) = 1/exp(x).
        bool neg = x.RawValue < 0;

        if (neg)
        {
            x = -x;
        }

        if (x == FP.One)
        {
            return(neg ? FP.One / (FP)2 : (FP)2);
        }
        if (x >= FP.Log2Max)
        {
            return(neg ? FP.One / FP.MaxValue : FP.MaxValue);
        }
        if (x <= FP.Log2Min)
        {
            return(neg ? FP.MaxValue : FP.Zero);
        }

        /* The algorithm is based on the power series for exp(x):
         * http://en.wikipedia.org/wiki/Exponential_function#Formal_definition
         *
         * From term n, we get term n+1 by multiplying with x/n.
         * When the sum term drops to zero, we can stop summing.
         */

        int integerPart = (int)Floor(x);

        // Take fractional part of exponent
        x = FP.FromRaw(x.RawValue & 0x00000000FFFFFFFF);

        var result = FP.One;
        var term   = FP.One;
        int i      = 1;

        while (term.RawValue != 0)
        {
            term    = FP.FastMul(FP.FastMul(x, term), FP.Ln2) / (FP)i;
            result += term;
            i++;
        }

        result = FP.FromRaw(result.RawValue << integerPart);
        if (neg)
        {
            result = FP.One / result;
        }

        return(result);
    }
Beispiel #2
0
    /// <summary>
    /// Returns the base-2 logarithm of a specified number.
    /// Provides at least 9 decimals of accuracy.
    /// </summary>
    /// <exception cref="ArgumentOutOfRangeException">
    /// The argument was non-positive
    /// </exception>
    internal static FP Log2(FP x)
    {
        if (x.RawValue <= 0)
        {
            throw new ArgumentOutOfRangeException("Non-positive value passed to Ln", "x");
        }

        // This implementation is based on Clay. S. Turner's fast binary logarithm
        // algorithm (C. S. Turner,  "A Fast Binary Logarithm Algorithm", IEEE Signal
        //     Processing Mag., pp. 124,140, Sep. 2010.)

        long b = 1U << (FP.FRACTIONAL_PLACES - 1);
        long y = 0;

        long rawX = x.RawValue;

        while (rawX < FP.ONE)
        {
            rawX <<= 1;
            y     -= FP.ONE;
        }

        while (rawX >= (FP.ONE << 1))
        {
            rawX >>= 1;
            y     += FP.ONE;
        }

        var z = FP.FromRaw(rawX);

        for (int i = 0; i < FP.FRACTIONAL_PLACES; i++)
        {
            z = FP.FastMul(z, z);
            if (z.RawValue >= (FP.ONE << 1))
            {
                z  = FP.FromRaw(z.RawValue >> 1);
                y += b;
            }
            b >>= 1;
        }

        return(FP.FromRaw(y));
    }
Beispiel #3
0
 /// <summary>
 /// Returns the natural logarithm of a specified number.
 /// Provides at least 7 decimals of accuracy.
 /// </summary>
 /// <exception cref="ArgumentOutOfRangeException">
 /// The argument was non-positive
 /// </exception>
 public static FP Ln(FP x)
 {
     return(FP.FastMul(Log2(x), FP.Ln2));
 }