ASF Bugzilla – Attachment 28855 Details for
Bug 43940
[PATCH] Faster method for double formatting
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch for both class and test case (DoubleFormatUtil.java and DoubleFormatUtilTest.java)
DoubleFormatUtil-patch2.txt (text/plain), 9.21 KB, created by
Julien Aymé
on 2012-05-29 13:38:52 UTC
(
hide
)
Description:
patch for both class and test case (DoubleFormatUtil.java and DoubleFormatUtilTest.java)
Filename:
MIME Type:
Creator:
Julien Aymé
Created:
2012-05-29 13:38:52 UTC
Size:
9.21 KB
patch
obsolete
>Index: src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java >=================================================================== >--- src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java (revision 1343596) >+++ src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java (working copy) >@@ -79,6 +79,10 @@ > // Will always be rounded to 0 > target.append('0'); > return; >+ } else if (Double.isNaN(source) || Double.isInfinite(source)) { >+ // Cannot be formated >+ target.append(Double.toString(source)); >+ return; > } > > boolean negative = source < 0.0; >@@ -92,7 +96,7 @@ > // The only way to format precisely the double is to use the String > // representation of the double, and then to do mathematical integer operation on it. > String s = Double.toString(source); >- if (source >= 10e-3 && source < 1e7) { >+ if (source >= 1e-3 && source < 1e7) { > // Plain representation of double: "intPart.decimalPart" > int dot = s.indexOf('.'); > String decS = s.substring(dot + 1); >@@ -103,6 +107,10 @@ > target.append(s.substring(0, dot)); > } else { > target.append(s); >+ // Remove trailing zeroes >+ for (int l = target.length() - 1; l >= 0 && target.charAt(l) == '0'; l--) { >+ target.setLength(l); >+ } > } > return; > } else if (scale + 1 < decLength) { >@@ -155,7 +163,8 @@ > long decP = Long.parseLong(intS); > format(target, scale, 0L, decP); > } else { >- long decP = Long.parseLong(intS) * tenPow(digits) + Long.parseLong(decS.substring(0, Math.min(decLength, digits))); >+ long subDecP = decLength <= digits ? Long.parseLong(decS) * tenPow(digits - decLength) : Long.parseLong(decS.substring(0, digits)); >+ long decP = Long.parseLong(intS) * tenPow(digits) + subDecP; > format(target, scale, 0L, decP); > } > } >@@ -177,12 +186,16 @@ > /** > * Most used power of ten (to avoid the cost of Math.pow(10, n) > */ >- private static final long[] tenPows = new long[20]; >+ private static final long[] tenPows = new long[19]; >+ private static final double[] tenPowsDouble = new double[21]; > static { > tenPows[0] = 1L; > for (int i = 1; i < tenPows.length; i++) { > tenPows[i] = tenPows[i - 1] * 10L; > } >+ for (int i = 0; i < tenPowsDouble.length; i++) { >+ tenPowsDouble[i] = Double.parseDouble("1e" + i); >+ } > } > > /** >@@ -196,6 +209,11 @@ > return n < tenPows.length ? tenPows[n] : (long) Math.pow(10, n); > } > >+ private static double tenPowDouble(int n) { >+ assert n >= 0; >+ return n < tenPowsDouble.length ? tenPowsDouble[n] : Math.pow(10, n); >+ } >+ > /** > * Helper method to do the custom rounding used within formatDoublePrecise > * >@@ -205,15 +223,14 @@ > * @param decP the source decimal part, truncated to scale + 1 digit > */ > private static void format(StringBuffer target, int scale, long intP, long decP) { >- long scaleTen = tenPow(scale); > if (decP != 0L) { > // decP is the decimal part of source, truncated to scale + 1 digit. > // Custom rounding: add 5 > decP += 5L; > decP /= 10L; >- if (decP >= scaleTen) { >+ if (decP >= tenPowDouble(scale)) { > intP++; >- decP -= scaleTen; >+ decP -= tenPow(scale); > } > if (decP != 0L) { > // Remove trailing zeroes >@@ -226,7 +243,7 @@ > target.append(intP); > if (decP != 0L) { > target.append('.'); >- while (scale > 0 && decP < tenPow(--scale)) { >+ while (scale > 0 && decP < tenPowDouble(--scale)) { > // Insert leading zeroes > target.append('0'); > } >@@ -251,6 +268,10 @@ > // Will always be rounded to 0 > target.append('0'); > return; >+ } else if (Double.isNaN(source) || Double.isInfinite(source)) { >+ // Cannot be formated >+ target.append(Double.toString(source)); >+ return; > } > > boolean isPositive = source >= 0.0; >@@ -318,7 +339,8 @@ > * @return true if the rounding will potentially use too many digits > */ > private static boolean tooManyDigitsUsed(double source, int scale) { >- return getExponant(source) + scale >= 14; >+ // if scale >= 19, 10^19 > Long.MAX_VALUE >+ return scale >= 19 || getExponant(source) + scale >= 14; > } > > /** >Index: test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java >=================================================================== >--- test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java (revision 1343596) >+++ test/java/org/apache/xmlgraphics/util/DoubleFormatUtilTest.java (working copy) >@@ -118,8 +118,104 @@ > expected = "0.00002"; > actual = format(value, decimals, precision); > assertEquals(value, decimals, precision, expected, actual); >+ >+ // Test added after bug #43940 was reopened >+ value = 0.005859375; >+ expected = "0.00585938"; >+ actual = format(value, 8, 8); >+ assertEquals(value, 8, 8, expected, actual); > } > >+ public void testLimits() { >+ int decimals = 19; >+ int precision = 19; >+ >+ double value = Double.NaN; >+ String expected = "NaN"; >+ String actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = Double.POSITIVE_INFINITY; >+ expected = "Infinity"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = Double.NEGATIVE_INFINITY; >+ expected = "-Infinity"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 1e-3 + Double.MIN_VALUE; >+ expected = "0.001"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 1e-3 - Double.MIN_VALUE; >+ expected = "0.001"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 1e-3; >+ expected = "0.001"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 0.0010000000000000002; // == Math.nextAfter(1e-3, Double.POSITIVE_INFINITY); >+ expected = "0.0010000000000000002"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ expected = "0.001"; >+ actual = format(value, 18, 18); >+ assertEquals(value, 18, 18, expected, actual); >+ >+ value = 0.0009999999999999998; // == Math.nextAfter(1e-3, Double.NEGATIVE_INFINITY); >+ expected = "0.0009999999999999998"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ expected = "0.001"; >+ actual = format(value, 18, 18); >+ assertEquals(value, 18, 18, expected, actual); >+ >+ value = 1e7 + Double.MIN_VALUE; >+ expected = "10000000"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 1e7 - Double.MIN_VALUE; >+ expected = "10000000"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 1e7; >+ expected = "10000000"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ >+ value = 1.0000000000000002E7; // == Math.nextAfter(1e7, Double.POSITIVE_INFINITY); >+ expected = "10000000.000000002"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ expected = "10000000"; >+ actual = format(value, 8, 8); >+ assertEquals(value, 8, 8, expected, actual); >+ >+ value = 9999999.999999998; // == Math.nextAfter(1e7, Double.NEGATIVE_INFINITY); >+ expected = "9999999.999999998"; >+ actual = format(value, decimals, precision); >+ assertEquals(value, decimals, precision, expected, actual); >+ expected = "10000000"; >+ actual = format(value, 8, 8); >+ assertEquals(value, 8, 8, expected, actual); >+ >+ value = 0.000009999999999999997; // Check higher precision >+ expected = "0.000009999999999999997"; >+ actual = format(value, 21, 21); >+ assertEquals(value, 21, 21, expected, actual); >+ expected = "0.00001"; >+ actual = format(value, 20, 20); >+ assertEquals(value, 20, 20, expected, actual); >+ } >+ > /** > * AssertEquals with a more detailed message > */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 43940
:
25508
|
25509
|
25585
|
25586
|
28686
|
28846
|
28850
| 28855