United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4755500 REGRESSION: calling Math.round(NaN) can break subsequent calls to Math.round()
JDK-4755500 : REGRESSION: calling Math.round(NaN) can break subsequent calls to Math.round()

Details
Type:
Bug
Submit Date:
2002-09-30
Status:
Resolved
Updated Date:
2002-10-23
Project Name:
JDK
Resolved Date:
2002-10-23
Component:
hotspot
OS:
windows_98,windows_2000
Sub-Component:
compiler
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.1
Fixed Versions:
1.4.2 (mantis)

Related Reports
Duplicate:

Sub Tasks

Description

Name: gm110360			Date: 09/30/2002


FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)


FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

ADDITIONAL OPERATING SYSTEMS :

We tested against Linux and Solaris and did not see the bug.


A DESCRIPTION OF THE PROBLEM :
After calling Math.round(double) a number of times,
including some calls to Math.round(Double.NaN), subsequent
calls to Math.round(double) may incorrectly return 0.

There are a number of ways to reproduce this, but the
easiest thing to do is just to call Math.round(Double.NaN)
2000 times.  The next time you call Math.round(double) the
result will always be 0, regardless of what you supply as
an argument.

Math.round(float) seems to be affected also.


REGRESSION.  Last worked in version 1.4

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Make 2000 calls to Math.round(Double.NaN)
2. Make one call to Math.round(double) using a whole number
argument (e.g. 1d or 12345d)


EXPECTED VERSUS ACTUAL BEHAVIOR :
The result is 0 when it should be equal to the argument
(e.g. 1 or 12345)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
We discovered this bug after experiencing the following two exceptions during
calls to Graphics.drawLine() somewhere inside the paint method of one of our
components:

sun.dc.pr.PRException: endPath: bad path
        at sun.dc.pr.Rasterizer.endPath(Rasterizer.java:537)
        at sun.java2d.pipe.DuctusRenderer.createShapeRasterizer
(DuctusRenderer.java:374)
        at sun.java2d.pipe.DuctusShapeRenderer.renderPath
(DuctusShapeRenderer.java:57)
        at sun.java2d.pipe.DuctusShapeRenderer.draw(DuctusShapeRenderer.java:45)
        at sun.java2d.pipe.PixelToShapeConverter.drawLine
(PixelToShapeConverter.java:34)
        at sun.java2d.SunGraphics2D.drawLine(SunGraphics2D.java:1954)
        ...



sun.dc.pr.PRError: setPenT4: invalid pen transformation (singular)
        at sun.dc.pr.PathStroker.setPenT4(Native Method)
        at sun.dc.pr.Rasterizer.setPenT4(Rasterizer.java:205)
        at sun.java2d.pipe.DuctusRenderer.createShapeRasterizer
(DuctusRenderer.java:260)
        at sun.java2d.pipe.DuctusShapeRenderer.renderPath
(DuctusShapeRenderer.java:57)
        at sun.java2d.pipe.DuctusShapeRenderer.draw(DuctusShapeRenderer.java:45)
        at sun.java2d.pipe.PixelToShapeConverter.drawLine
(PixelToShapeConverter.java:34)
        at sun.java2d.SunGraphics2D.drawLine(SunGraphics2D.java:1954)
        ...


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class MathBugTest {
  
  public static void main(String[] args) {
    System.out.println(Math.round(1d));  // prints "1", as expected
    for (int i=0; i<2000; i++) {
      Math.round(Double.NaN);
    }
    System.out.println(Math.round(1d));  // prints "0", which is wrong
  }
  
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Hack the java.lang.Math.round(float/double) methods so that
they test for NaN prior to calling StrictMath.round()

Release Regression From : 1.4.0_02
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 165064) 
======================================================================

                                    

Comments
EVALUATION

This is a bug in the d2l conversion stub which was introduced for speed in
1.4.1. In the NaN case we weren't popping the argument off the FPU stack, which
for some reason caused subsequent flds to be messed up. Will be fixed in 1.4.2
and recommended to be backported to 1.4.1_02.

###@###.### 2002-10-04

Revised test case with pass/fail result:
public class MathBugTest {
  public static void main(String[] args) {
    // Note: it's really only necessary to run this loop 8 times to
    // reproduce the bug, but the 2000-length loop causes compilation
    // of Math.round() without any other command-line flags.
    // A bug in the d2l NaN case was causing overflow of the FPU
    // stack, yielding subsequent wrong results for flds.
    for (int i=0; i<2000; i++) {
        Math.round(Double.NaN);
    }
    if (Math.round(1d) != 1) {
        throw new RuntimeException("TEST FAILED");
    }
    System.out.println("Test passed.");
  }
}

###@###.### 2002-10-04
                                     
2002-10-04
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
mantis

FIXED IN:
mantis

INTEGRATED IN:
mantis


                                     
2004-06-14



Hardware and Software, Engineered to Work Together