Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java version "1.6.0_14" Java(TM) SE Runtime Environment (build 1.6.0_14-b08) Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 6.1.7601] A DESCRIPTION OF THE PROBLEM : Math.hypot is excessively slow. Running it in a simple timing loop gives a run time of about 800 nanoseconds on an i7 2.67 GHz. The pure Java method provided below runs in 40 nanoseconds. REPRODUCIBILITY : This bug can be reproduced always. CUSTOMER SUBMITTED WORKAROUND : /** * <b>hypot</b> * @param x * @param y * @return sqrt(x*x +y*y) without intermediate overflow or underflow. * @Note Math.hypot is unnecessarily slow. This returns the identical result to * Math.hypot with reasonable run times (~40 nsec vs. 800 nsec). * <p>The logic for computing z is copied from "Freely Distributable Math Library" * fdlibm's e_hypot.c. This minimizes rounding error to provide 1 ulb accuracy. */ public static double hypot(double x, double y) { if (Double.isInfinite(x) || Double.isInfinite(y)) return Double.POSITIVE_INFINITY; if (Double.isNaN(x) || Double.isNaN(y)) return Double.NaN; x = Math.abs(x); y = Math.abs(y); if (x < y) { double d = x; x = y; y = d; } int xi = Math.getExponent(x); int yi = Math.getExponent(y); if (xi > yi + 27) return x; int bias = 0; if (xi > 510 || xi < -511) { bias = xi; x = Math.scalb(x, -bias); y = Math.scalb(y, -bias); } // translated from "Freely Distributable Math Library" e_hypot.c to minimize rounding errors double z = 0; if (x > 2*y) { double x1 = Double.longBitsToDouble(Double.doubleToLongBits(x) & 0xffffffff00000000L); double x2 = x - x1; z = Math.sqrt(x1*x1 + (y*y + x2*(x+x1))); } else { double t = 2 * x; double t1 = Double.longBitsToDouble(Double.doubleToLongBits(t) & 0xffffffff00000000L); double t2 = t - t1; double y1 = Double.longBitsToDouble(Double.doubleToLongBits(y) & 0xffffffff00000000L); double y2 = y - y1; double x_y = x - y; z = Math.sqrt(t1*y1 + (x_y*x_y + (t1*y2 + t2*y))); // Note: 2*x*y <= x*x + y*y } if (bias == 0) { return z; } else { return Math.scalb(z, bias); } }
|