3

Why the math operation Math.sqrt(x*x+y*y) is much faster than Math.hypo(x,y)?

public class Teste {
    public static void main(String[] args) {
        long ta = System.currentTimeMillis();
        for( double x=0,y=0; x<5000000; x++,y+=2 ){
            double d = Math.sqrt(x*x+y*y);
        }
        long tb = System.currentTimeMillis();

        System.err.println((tb-ta));
        ta = System.currentTimeMillis();
        for( double x=0,y=0; x<5000000; x++,y+=2 ){
            double d = Math.hypot(x,y);
        }
        tb = System.currentTimeMillis();
        System.err.println((tb-ta));
    }
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
heron
  • 31
  • 2

1 Answers1

3

hypot is usually implemented in a special way to avoid issues with overflow and underflow. Notice that sqrt(x*x+y*y) returns infinity when x or y is too large and zero when both x and y are too small.

I think the usual way to get around this difficulty is by computing z = x/y, checking if z*z is in a reasonable range, and then finding sqrt(1 + z*z) * y. If z*z is too big, you can simply return x, and if z*z is too small, you can return y.

Looking at the comment at the top of __ieee754_hypot in eglibc-2.11.3, I see the following chunk of a comment:

   So, compute sqrt(x*x+y*y) with some care as
   follows to get the error below 1 ulp:

   Assume x>y>0;
   (if possible, set rounding to round-to-nearest)
   1. if x > 2y  use
           x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
   where x1 = x with lower 32 bits cleared, x2 = x-x1; else
   2. if x <= 2y use
           t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
   where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
   y1= y with lower 32 bits chopped, y2 = y-y1.

I can't see a reason for why eglibc does all this unless x*x+y*y overflows or underflows.

tmyklebu
  • 13,915
  • 3
  • 28
  • 57