FastMath { public static double atan2(double y, double x) { if (x != x || y != y) { return Double.NaN; } if (y == 0) { final double result = x * y; final double invx = 1d / x; final double invy = 1d / y; if (invx == 0) { if (x > 0) { return y; } else { return copySign(Math.PI, y); } } if (x < 0 || invx < 0) { if (y < 0 || invy < 0) { return -Math.PI; } else { return Math.PI; } } else { return result; } } if (y == Double.POSITIVE_INFINITY) { if (x == Double.POSITIVE_INFINITY) { return Math.PI * F_1_4; } if (x == Double.NEGATIVE_INFINITY) { return Math.PI * F_3_4; } return Math.PI * F_1_2; } if (y == Double.NEGATIVE_INFINITY) { if (x == Double.POSITIVE_INFINITY) { return -Math.PI * F_1_4; } if (x == Double.NEGATIVE_INFINITY) { return -Math.PI * F_3_4; } return -Math.PI * F_1_2; } if (x == Double.POSITIVE_INFINITY) { if (y > 0 || 1 / y > 0) { return 0d; } if (y < 0 || 1 / y < 0) { return -0d; } } if (x == Double.NEGATIVE_INFINITY) { if (y > 0.0 || 1 / y > 0.0) { return Math.PI; } if (y < 0 || 1 / y < 0) { return -Math.PI; } } if (x == 0) { if (y > 0 || 1 / y > 0) { return Math.PI * F_1_2; } if (y < 0 || 1 / y < 0) { return -Math.PI * F_1_2; } } final double r = y / x; if (Double.isInfinite(r)) { return atan(r, 0, x < 0); } double ra = doubleHighPart(r); double rb = r - ra; final double xa = doubleHighPart(x); final double xb = x - xa; rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x; final double temp = ra + rb; rb = -(temp - ra - rb); ra = temp; if (ra == 0) { ra = copySign(0d, y); } final double result = atan(ra, rb, x < 0); return result; } private  FastMath(); static double sqrt(final double a); static double cosh(double x); static double sinh(double x); static double tanh(double x); static double acosh(final double a); static double asinh(double a); static double atanh(double a); static double signum(final double a); static float signum(final float a); static double nextUp(final double a); static float nextUp(final float a); static double nextDown(final double a); static float nextDown(final float a); static double random(); static double exp(double x); static double expm1(double x); static double log(final double x); static double log1p(final double x); static double log10(final double x); static double log(double base, double x); static double pow(double x, double y); static double pow(double d, int e); static double sin(double x); static double cos(double x); static double tan(double x); static double atan(double x); static double atan2(double y, double x); static double asin(double x); static double acos(double x); static double cbrt(double x); static double toRadians(double x); static double toDegrees(double x); static int abs(final int x); static long abs(final long x); static float abs(final float x); static double abs(double x); static double ulp(double x); static float ulp(float x); static double scalb(final double d, final int n); static float scalb(final float f, final int n); static double nextAfter(double d, double direction); static float nextAfter(final float f, final double direction); static double floor(double x); static double ceil(double x); static double rint(double x); static long round(double x); static int round(final float x); static int min(final int a, final int b); static long min(final long a, final long b); static float min(final float a, final float b); static double min(final double a, final double b); static int max(final int a, final int b); static long max(final long a, final long b); static float max(final float a, final float b); static double max(final double a, final double b); static double hypot(final double x, final double y); static double IEEEremainder(double dividend, double divisor); static int toIntExact(final long n); static int incrementExact(final int n); static long incrementExact(final long n); static int decrementExact(final int n); static long decrementExact(final long n); static int addExact(final int a, final int b); static long addExact(final long a, final long b); static int subtractExact(final int a, final int b); static long subtractExact(final long a, final long b); static int multiplyExact(final int a, final int b); static long multiplyExact(final long a, final long b); static int floorDiv(final int a, final int b); static long floorDiv(final long a, final long b); static int floorMod(final int a, final int b); static long floorMod(final long a, final long b); static double copySign(double magnitude, double sign); static float copySign(float magnitude, float sign); static int getExponent(final double d); static int getExponent(final float f); static void main(String[] a); static final double PI; static final double E; }
@Test public void testAtan2() { double y1 = 1.2713504628280707e10; double x1 = -5.674940885228782e-10; Assert.assertEquals(Math.atan2(y1, x1), FastMath.atan2(y1, x1), 2 * Precision.EPSILON); double y2 = 0.0; double x2 = Double.POSITIVE_INFINITY; Assert.assertEquals(Math.atan2(y2, x2), FastMath.atan2(y2, x2), Precision.SAFE_MIN); }
@Test public void testAtan2SpecialCases() { Assert.assertTrue("atan2(NaN, 0.0) should be NaN", Double.isNaN(FastMath.atan2(Double.NaN, 0.0))); Assert.assertTrue("atan2(0.0, NaN) should be NaN", Double.isNaN(FastMath.atan2(0.0, Double.NaN))); Assert.assertEquals("atan2(0.0, 0.0) should be 0.0", 0.0, FastMath.atan2(0.0, 0.0), Precision.EPSILON); Assert.assertEquals("atan2(0.0, 0.001) should be 0.0", 0.0, FastMath.atan2(0.0, 0.001), Precision.EPSILON); Assert.assertEquals("atan2(0.1, +Inf) should be 0.0", 0.0, FastMath.atan2(0.1, Double.POSITIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(-0.0, 0.0) should be -0.0", -0.0, FastMath.atan2(-0.0, 0.0), Precision.EPSILON); Assert.assertEquals("atan2(-0.0, 0.001) should be -0.0", -0.0, FastMath.atan2(-0.0, 0.001), Precision.EPSILON); Assert.assertEquals("atan2(-0.0, +Inf) should be -0.0", -0.0, FastMath.atan2(-0.1, Double.POSITIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(0.0, -0.0) should be PI", FastMath.PI, FastMath.atan2(0.0, -0.0), Precision.EPSILON); Assert.assertEquals("atan2(0.1, -Inf) should be PI", FastMath.PI, FastMath.atan2(0.1, Double.NEGATIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(-0.0, -0.0) should be -PI", -FastMath.PI, FastMath.atan2(-0.0, -0.0), Precision.EPSILON); Assert.assertEquals("atan2(0.1, -Inf) should be -PI", -FastMath.PI, FastMath.atan2(-0.1, Double.NEGATIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(0.1, 0.0) should be PI/2", FastMath.PI / 2.0, FastMath.atan2(0.1, 0.0), Precision.EPSILON); Assert.assertEquals("atan2(0.1, -0.0) should be PI/2", FastMath.PI / 2.0, FastMath.atan2(0.1, -0.0), Precision.EPSILON); Assert.assertEquals("atan2(Inf, 0.1) should be PI/2", FastMath.PI / 2.0, FastMath.atan2(Double.POSITIVE_INFINITY, 0.1), Precision.EPSILON); Assert.assertEquals("atan2(Inf, -0.1) should be PI/2", FastMath.PI / 2.0, FastMath.atan2(Double.POSITIVE_INFINITY, -0.1), Precision.EPSILON); Assert.assertEquals("atan2(-0.1, 0.0) should be -PI/2", -FastMath.PI / 2.0, FastMath.atan2(-0.1, 0.0), Precision.EPSILON); Assert.assertEquals("atan2(-0.1, -0.0) should be -PI/2", -FastMath.PI / 2.0, FastMath.atan2(-0.1, -0.0), Precision.EPSILON); Assert.assertEquals("atan2(-Inf, 0.1) should be -PI/2", -FastMath.PI / 2.0, FastMath.atan2(Double.NEGATIVE_INFINITY, 0.1), Precision.EPSILON); Assert.assertEquals("atan2(-Inf, -0.1) should be -PI/2", -FastMath.PI / 2.0, FastMath.atan2(Double.NEGATIVE_INFINITY, -0.1), Precision.EPSILON); Assert.assertEquals("atan2(Inf, Inf) should be PI/4", FastMath.PI / 4.0, FastMath.atan2(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(Inf, -Inf) should be PI * 3/4", FastMath.PI * 3.0 / 4.0, FastMath.atan2(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(-Inf, Inf) should be -PI/4", -FastMath.PI / 4.0, FastMath.atan2(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), Precision.EPSILON); Assert.assertEquals("atan2(-Inf, -Inf) should be -PI * 3/4", - FastMath.PI * 3.0 / 4.0, FastMath.atan2(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON); }