Details

    • Sub-task
    • Resolution: Fixed
    • P4
    • 9
    • 6u29
    • core-libs
    • b84
    • x86
    • windows_xp

    Backports

      Description

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

        Attachments

          Issue Links

            Activity

              People

                darcy Joe Darcy
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: