You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by ga...@apache.org on 2012/06/05 17:35:10 UTC

svn commit: r1346428 - in /xmlgraphics/commons/trunk: src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java status.xml test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java

Author: gadams
Date: Tue Jun  5 15:35:10 2012
New Revision: 1346428

URL: http://svn.apache.org/viewvc?rev=1346428&view=rev
Log:
Bugzilla #53327: Fix corner cases involving long/double conversion and rounding error in double division when rounding 5E-N for certain N. Submitted by Julien Aymé.

Modified:
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java
    xmlgraphics/commons/trunk/status.xml
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java?rev=1346428&r1=1346427&r2=1346428&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java Tue Jun  5 15:35:10 2012
@@ -188,14 +188,15 @@ public final class DoubleFormatUtil {
      * @return true if the source value will be rounded to zero
      */
     private static boolean isRoundedToZero(double source, int decimals, int precision) {
-        return source == 0.0 || Math.abs(source) < 5.0 / tenPowDouble(Math.max(decimals, precision) + 1);
+        // Use 4.999999999999999 instead of 5 since in some cases, 5.0 / 1eN > 5e-N (e.g. for N = 37, 42, 45, 66, ...)
+        return source == 0.0 || Math.abs(source) < 4.999999999999999 / tenPowDouble(Math.max(decimals, precision) + 1);
     }
 
     /**
      * Most used power of ten (to avoid the cost of Math.pow(10, n)
      */
     private static final long[] POWERS_OF_TEN_LONG = new long[19];
-    private static final double[] POWERS_OF_TEN_DOUBLE = new double[21];
+    private static final double[] POWERS_OF_TEN_DOUBLE = new double[30];
     static {
         POWERS_OF_TEN_LONG[0] = 1L;
         for (int i = 1; i < POWERS_OF_TEN_LONG.length; i++) {
@@ -251,7 +252,11 @@ public final class DoubleFormatUtil {
         target.append(intP);
         if (decP != 0L) {
             target.append('.');
-            while (scale > 0 && decP < tenPowDouble(--scale)) {
+            // Use tenPow instead of tenPowDouble for scale below 18,
+            // since the casting of decP to double may cause some imprecisions:
+            // E.g. for decP = 9999999999999999L and scale = 17,
+            // decP < tenPow(16) while (double) decP == tenPowDouble(16)
+            while (scale > 0 && (scale > 18 ? decP < tenPowDouble(--scale) : decP < tenPow(--scale))) {
                 // Insert leading zeroes
                 target.append('0');
             }

Modified: xmlgraphics/commons/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/status.xml?rev=1346428&r1=1346427&r2=1346428&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/status.xml (original)
+++ xmlgraphics/commons/trunk/status.xml Tue Jun  5 15:35:10 2012
@@ -42,6 +42,9 @@
   <changes>
     <release version="Trunk" date="n/a">
       <action context="Code" dev="GA" type="update" fixes-bug="53327" due-to="Julien Aymé">
+        Fix corner cases involving long/double conversion and rounding error in double division when rounding 5E-N for certain N.
+      </action>
+      <action context="Code" dev="GA" type="update" fixes-bug="53327" due-to="Julien Aymé">
         Fix determination of use of precise vs fast formatting in order to fix regression with value 5.22534294505995E-4, decimals: 17, precision: 17.
       </action>
       <action context="Code" dev="GA" type="fix" fixes-bug="53352">

Modified: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java?rev=1346428&r1=1346427&r2=1346428&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java (original)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java Tue Jun  5 15:35:10 2012
@@ -139,6 +139,16 @@ public class DoubleFormatUtilTest extend
         expected = refFormat(value, 294, 294);
         actual = format(value, 294, 294);
         assertEquals(value, 294, 294, expected, actual);
+
+        value = 5E-304;
+        expected = refFormat(value, 303, 303);
+        actual = format(value, 303, 303);
+        assertEquals(value, 303, 303, expected, actual);
+
+        value = 9.999999999999999E-250;
+        expected = refFormat(value, 265, 265);
+        actual = format(value, 265, 265);
+        assertEquals(value, 265, 265, expected, actual);
     }
 
     public void testLimits() {
@@ -535,16 +545,36 @@ public class DoubleFormatUtilTest extend
     }
 
     public void testAllDoubleRanges() {
+        double[] values = {0, 1, 5, 4.9999, 5.0001, 9.9999, 1234567890, 0 /* The last one is random */};
         Random r = new Random();
         double value;
         String expected, actual;
+        int minScale, maxScale;
         for (int i = -330; i <= 315; i++) {
-            value = r.nextDouble() * Math.pow(10.0, i);
-            for (int scale = 1; scale <= 350; scale++) {
-                expected = refFormat(value, scale, scale);
-                actual = format(value, scale, scale);
-                assertEquals(value, scale, scale, expected, actual);
+            values[values.length - 1] = r.nextDouble();
+            double pow = Math.pow(10.0, i);
+            for (double d : values) {
+                value = d * pow;
+                minScale = 1;
+                maxScale = 350;
+                // Reduce scales (unnecessary tests)
+                if (i < -30) {
+                    minScale = -i - 30;
+                    maxScale = -i + 30;
+                } else if (i <= 0) {
+                    minScale = 1;
+                    maxScale = -i + 30;
+                } else {
+                    minScale = 1;
+                    maxScale = 30;
+                }
+                for (int scale = minScale; scale <= maxScale; scale++) {
+                    expected = refFormat(value, scale, scale);
+                    actual = format(value, scale, scale);
+                    assertEquals(value, scale, scale, expected, actual);
+                }
             }
+            
         }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org