예제 #1
0
파일: Fix32.cs 프로젝트: forestrf/Fix32
    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);
    }
예제 #2
0
파일: Fix32.cs 프로젝트: forestrf/Fix32
    /// <summary>
    /// Returns the arctan of of the specified number, calculated using Euler series
    /// </summary>
    public static Fix32 Atan(this Fix32 zz)
    {
#if USE_DOUBLES
        return(Math.Atan(z.ToDouble()).ToFix32());
#endif
        Fix32 z = zz;
        if ((int)z == 0)
        {
            return(Fix32.Zero);
        }

        // Force positive values for argument
        // Atan(-z) = -Atan(z).
        bool neg = ((int)z < 0);
        if (neg)
        {
            z = z.Neg();
        }

        Fix32 result;

        if ((int)z == (int)Fix32.One)
        {
            result = Fix32.PiOver4;
        }
        else
        {
            bool invert = (int)z > (int)Fix32.One;
            if (invert)
            {
                z = Fix32.One.Div(z);
            }

            result = Fix32.One;
            Fix32 term = Fix32.One;

            Fix32 zSq        = z.Mul(z);
            Fix32 zSq2       = zSq.Mul(Fix32.Two);
            Fix32 zSqPlusOne = zSq.Add(Fix32.One);
            Fix32 zSq12      = zSqPlusOne.Mul(Fix32.Two);
            Fix32 dividend   = zSq2;
            Fix32 divisor    = zSqPlusOne.Mul(Fix32.Three);

            for (int i = 2; i < 30; i++)
            {
                term   = term.Mul(dividend.Div(divisor));
                result = result.Add(term);

                dividend = dividend.Add(zSq2);
                divisor  = divisor.Add(zSq12);

                if ((int)term == 0)
                {
                    break;
                }
            }

            result = result.Mul(z).Div(zSqPlusOne);

            if (invert)
            {
                result = Fix32.PiOver2.Sub(result);
            }
        }

        if (neg)
        {
            result = result.Neg();
        }
        return(result);
    }