Ejemplo n.º 1
0
    public static Fix32 Ln(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Log(x.ToDouble()).ToFix32());
#endif
        return(Log2(x).Mul(Fix32.Ln2));
    }
Ejemplo n.º 2
0
    public static Fix32 Exp(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Exp(x.ToDouble()).ToFix32());
#endif
        return((Fix32)Fixed32.Exp((int)x));
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Returns a specified number raised to the specified power. Saturates
    /// </summary>
    /// <exception cref="DivideByZeroException">
    /// The base was zero, with a negative exponent
    /// </exception>
    /// <exception cref="ArgumentOutOfRangeException">
    /// The base was negative, with a non-zero exponent
    /// </exception>
    public static Fix32 Pow(this Fix32 b, Fix32 exp)
    {
#if USE_DOUBLES
        return(Math.Pow(b.ToDouble(), exp.ToDouble()).ToFix32());
#endif
        if ((int)b == (int)Fix32.One)
        {
            return(Fix32.One);
        }
        if ((int)exp == 0)
        {
            return(Fix32.One);
        }
        if ((int)b == 0)
        {
            if ((int)exp < 0)
            {
                throw new DivideByZeroException();
            }
            return(Fix32.Zero);
        }

        if (b < 0 && exp != 0)
        {
            throw new ArgumentOutOfRangeException("Non-positive value passed to Ln", "x");
        }

        return(exp.Mul(b.Log2()).Pow2());
    }
Ejemplo n.º 4
0
    public static Fix32 TanFastest(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Tan(x.ToDouble()).ToFix32());
#endif
        return((Fix32)Fixed32.TanFastest((int)x));
    }
Ejemplo n.º 5
0
    public static Fix32 RcpFast(this Fix32 x)
    {
#if USE_DOUBLES
        return((1 / x.ToDouble()).ToFix32());
#endif
        return((Fix32)Fixed32.RcpFast((int)x));
    }
Ejemplo n.º 6
0
    public static Fix32 RSqrtFastest(this Fix32 x)
    {
#if USE_DOUBLES
        return((1 / Math.Sqrt(x.ToDouble())).ToFix32());
#endif
        return((Fix32)Fixed32.RSqrtFastest((int)x));
    }
Ejemplo n.º 7
0
    public static Fix32 Ceiling(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Floor(x.ToDouble()).ToFix32());
#endif
        var hasFractionalPart = ((int)x & FRACTIONAL_MASK) != 0;
        return(hasFractionalPart ? ((Fix32)((int)x & INTEGER_MASK)).Add(Fix32.One) : x);
    }
Ejemplo n.º 8
0
    public static Fix32 Floor(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Floor(x.ToDouble()).ToFix32());
#endif
        // Just zero out the fractional part
        return((Fix32)((int)x & INTEGER_MASK));
    }
Ejemplo n.º 9
0
    public static Fix32 Neg(this Fix32 x)
    {
#if USE_DOUBLES
        return((-x.ToDouble()).ToFix32());
#endif
        //return new Fix64(-x.RawValue);
        return((Fix32)((int)x == MIN_VALUE ? MAX_VALUE : -(int)x));
    }
Ejemplo n.º 10
0
    public static Fix32 Sub(this Fix32 x, Fix32 y)
    {
#if USE_DOUBLES
        return((x.ToDouble() - y.ToDouble()).ToFix32());
#endif
        long sub = (long)x - (long)y;           // TO TEST: Shift and operate to check overflow
        return((Fix32)(((int)sub) != sub ? (int)((((uint)x >> NUM_BITS_MINUS_ONE) - 1U) ^ (1U << NUM_BITS_MINUS_ONE)) : (int)sub));
    }
Ejemplo n.º 11
0
    public static Fix32 Cos(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Cos(x.ToDouble()).ToFix32());
#endif
        // Don't use Fixed32.Cos, it gives an error
        var rawAngle = (int)x + (x > 0 ? -PI - PI_OVER_2 : PI_OVER_2);
        return(((Fix32)rawAngle).Sin());
    }
Ejemplo n.º 12
0
    public static Fix32 Mod(this Fix32 x, Fix32 y)
    {
#if USE_DOUBLES
        return((x.ToDouble() % y.ToDouble()).ToFix32());
#endif
        return((Fix32)(
                   (int)x == MIN_VALUE & (int)y == -1 ?
                   0 :
                   (int)x % (int)y));
    }
Ejemplo n.º 13
0
    /// <summary>
    /// Returns the base-2 logarithm of a specified number.
    /// </summary>
    /// <exception cref="ArgumentOutOfRangeException">
    /// The argument was non-positive
    /// </exception>
    public static Fix32 Log2(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Log(x.ToDouble(), 2).ToFix32());
#endif
        if ((int)x <= 0)
        {
            throw new ArgumentOutOfRangeException("Non-positive value passed to Ln", "x");
        }

        //return (Fix32) Fixed32.Log2((int) 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.)

        //https://github.com/dmoulding/log2fix/blob/master/log2fix.c

        const int EXTRA_SHIFT = 8;
        long      xx          = (long)x << EXTRA_SHIFT;
        const int PRECISION   = FRACTIONAL_BITS + EXTRA_SHIFT;

        long b = 1 << (PRECISION - 1);
        long y = 0;

        long rawX = (long)xx;
        while (rawX < 1 << PRECISION)
        {
            rawX <<= 1;
            y     -= 1 << PRECISION;
        }

        while (rawX >= 2 << PRECISION)
        {
            rawX >>= 1;
            y     += 1 << PRECISION;
        }

        ulong z = (ulong)rawX;

        for (int i = 0; i < PRECISION; i++)
        {
            z = z * z >> PRECISION;
            if (z >= 2 << PRECISION)
            {
                z >>= 1;
                y  += b;
            }
            b >>= 1;
        }

        return((Fix32)(int)(y >> EXTRA_SHIFT));
    }
Ejemplo n.º 14
0
    public static Fix32 Mul(this Fix32 x, Fix32 y)
    {
#if USE_DOUBLES
        return(Math.Round(x.ToDouble() * y.ToDouble()).ToFix32());
#endif
        long multLong = ((long)x * (long)y) >> FRACTIONAL_BITS;

        int finalSign = (int)x ^ (int)y;

        return((Fix32)(((finalSign ^ multLong) & SIGN_MASK) != 0 && multLong != 0 ?
                       (int)((((uint)finalSign >> NUM_BITS_MINUS_ONE) - 1U) ^ (1U << NUM_BITS_MINUS_ONE)) :
                       (int)multLong));
    }
Ejemplo n.º 15
0
    public static Fix32 Atan2(this Fix32 y, Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Atan2(y.ToDouble(), x.ToDouble()).ToFix32());
#endif
        var yl = (int)y;
        var xl = (int)x;
        if (xl == 0)
        {
            if (yl > 0)
            {
                return(Fix32.PiOver2);
            }
            if (yl == 0)
            {
                return(Fix32.Zero);
            }
            return(Fix32.PiOver2.Neg());
        }
        Fix32 atan;
        var   z = y.Div(x);

        // Deal with overflow
        if ((int)Fix32.One.Add(C0p28.Mul(z).Mul(z)) == (int)Fix32.MaxValue)
        {
            return((int)y < 0 ? Fix32.PiOver2.Neg() : Fix32.PiOver2);
        }

        if ((int)Abs(z) < (int)Fix32.One)
        {
            atan = z.Div(Fix32.One.Add(C0p28.Mul(z).Mul(z)));
            if (xl < 0)
            {
                if (yl < 0)
                {
                    return(atan.Sub(Fix32.Pi));
                }
                return(atan.Add(Fix32.Pi));
            }
        }
        else
        {
            atan = Fix32.PiOver2.Sub(z.Div(z.Mul(z).Add(C0p28)));
            if (yl < 0)
            {
                return(atan.Sub(Fix32.Pi));
            }
        }

        return(atan);
    }
Ejemplo n.º 16
0
    public static Fix32 Abs(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Abs(x.ToDouble()).ToFix32());
#endif
        if ((int)x == MIN_VALUE)
        {
            return(Fix32.MaxValue);
        }

        // branchless implementation, see http://www.strchr.com/optimized_abs_function
        var mask = (int)x >> NUM_BITS_MINUS_ONE;
        return((Fix32)(((int)x + mask) ^ mask));
    }
Ejemplo n.º 17
0
    public static Fix32 Add(this Fix32 x, Fix32 y)
    {
#if USE_DOUBLES
        return((x.ToDouble() + y.ToDouble()).ToFix32());
#endif
        // https://stackoverflow.com/questions/17580118/signed-saturated-add-of-64-bit-ints/17587197#17587197
        // determine the lower or upper bound of the result
        //int ret = (x.RawValue < 0) ? MIN_VALUE : MAX_VALUE;
        int ret = (int)((((uint)x >> NUM_BITS_MINUS_ONE) - 1U) ^ (1U << NUM_BITS_MINUS_ONE));
        // this is always well defined:
        // if x < 0 this adds a positive value to INT64_MIN
        // if x > 0 this subtracts a positive value from INT64_MAX
        //int comp = ret - xRaw;
        // the condition is equivalent to
        // ((x < 0) && (y > comp)) || ((x >=0) && (y <= comp))
        return((Fix32)((x < 0) != ((int)y > (ret - (int)x)) ? ret : (int)x + (int)y));
    }
Ejemplo n.º 18
0
    /// <summary>
    /// Returns the square root of a specified number.
    /// </summary>
    /// <exception cref="ArgumentOutOfRangeException">
    /// The argument was negative.
    /// </exception>
    public static Fix32 SqrtSlow(this Fix32 x)
    {
#if USE_DOUBLES
        return(Math.Sqrt(x.ToDouble()).ToFix32());
#endif
        if (x <= 0)
        {
            return(0);
        }

        // https://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2

        // Manually calculated constants (somehow) for precision Q18.14
        const int ITERATIONS = 25;        // (((NUM_BITS - 16) / 4) * 2) + 16; // 24

        int shift = NUM_BITS - 2;

        // [1] First iteration
        int bottomHalf = 0; // 0x3 & ((int) x >> SHIFT); equals 0

        int a = 0;          // accumulator
        int r = 0;          // remainder
        for (int i = 0; i < ITERATIONS; i++)
        {
            r   = (r << 2) | bottomHalf;
            a <<= 1;
            int e = (a << 1) | 1;             // trial product
            if (r >= e)
            {
                r -= e;
                a |= 1;
            }
            // [1] Subsequent iterations
            bottomHalf = 0x3 & ((int)x >> shift);
            shift     -= 2;
        }

        return((Fix32)a);
    }
Ejemplo n.º 19
0
    /// <summary>
    /// Divide. Saturates on overflow. May change to Fast.
    /// </summary>
    public static Fix32 Div(this Fix32 x, Fix32 y)
    {
#if USE_DOUBLES
        return((x.ToDouble() / y.ToDouble()).ToFix32());
#endif
        if ((int)y == 0)
        {
            return((Fix32)(unchecked ((int)(((((uint)x) >> NUM_BITS_MINUS_ONE) - 1U) ^ (1U << NUM_BITS_MINUS_ONE)))));

            return(x >= 0 ? Fix32.MaxValue : Fix32.MinValue);            // Branched version of the previous code, for clarity. Slower
        }

        long r = ((long)x << FRACTIONAL_BITS) / (int)y;
        if (r > MAX_VALUE)
        {
            return(Fix32.MaxValue);
        }
        if (r < MIN_VALUE)
        {
            return(Fix32.MinValue);
        }
        return((Fix32)(int)r);
    }
Ejemplo n.º 20
0
 public static string ToStringExt(this Fix32 x)
 {
     return(x.ToDouble().ToString("0.##########"));
 }