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); }
/// <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); }