Пример #1
0
    /// <summary>
    /// Returns 2 raised to the specified power.
    /// </summary>
    public static Fix32 Pow2(this Fix32 xx)
    {
#if USE_DOUBLES
        return(Math.Pow(2, x.ToDouble()).ToFix32());
#endif
        Fix32 x = xx;
        if ((int)x == 0)
        {
            return(Fix32.One);
        }

        // Avoid negative arguments by exploiting that exp(-x) = 1/exp(x).
        bool neg = (int)x < 0;
        if (neg)
        {
            x = x.Neg();
        }

        if ((int)x == (int)Fix32.One)
        {
            return(neg ? Fix32.One.Div(Fix32.Two) : Fix32.Two);            // Can be cached
        }
        if ((int)x >= (int)Fix32.Log2Max)
        {
            return(neg ? Fix32.One.Div(Fix32.MaxValue) : Fix32.MaxValue);                                        // Can be cached
        }
        if ((int)x <= (int)Fix32.Log2Min)
        {
            return(neg ? Fix32.MaxValue : Fix32.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 = x.Floor().ToInt();
        // Take fractional part of exponent
        x = (Fix32)((uint)x & FRACTIONAL_MASK);

        Fix32 result = Fix32.One;
        Fix32 term   = Fix32.One;
        Fix32 i      = Fix32.One;
        while ((int)term != 0)
        {
            term   = x.Mul(term).Mul(Fix32.Ln2.Div(i));
            result = result.Add(term);
            i      = i.AddFast(Fix32.One);
        }

        result = (Fix32)((int)result << integerPart);
        if (neg)
        {
            result = Fix32.One.Div(result);
        }

        return(result);
    }