undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
83
test/jdk/java/lang/Double/BitwiseConversion.java
Normal file
83
test/jdk/java/lang/Double/BitwiseConversion.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 5037596
|
||||
* @summary Verify bitwise conversion works for non-canonical NaN values
|
||||
* @library ../Math
|
||||
* @build DoubleConsts
|
||||
* @run main BitwiseConversion
|
||||
*/
|
||||
|
||||
import static java.lang.Double.*;
|
||||
|
||||
public class BitwiseConversion {
|
||||
static int testNanCase(long x) {
|
||||
int errors = 0;
|
||||
// Strip out sign and exponent bits
|
||||
long y = x & DoubleConsts.SIGNIF_BIT_MASK;
|
||||
|
||||
double values[] = {
|
||||
longBitsToDouble(DoubleConsts.EXP_BIT_MASK | y),
|
||||
longBitsToDouble(DoubleConsts.SIGN_BIT_MASK | DoubleConsts.EXP_BIT_MASK | y)
|
||||
};
|
||||
|
||||
for(double value: values) {
|
||||
if (!isNaN(value)) {
|
||||
throw new RuntimeException("Invalid input " + y +
|
||||
"yielded non-NaN" + value);
|
||||
}
|
||||
long converted = doubleToLongBits(value);
|
||||
if (converted != 0x7ff8000000000000L) {
|
||||
errors++;
|
||||
System.err.format("Non-canoncial NaN bits returned: %x%n",
|
||||
converted);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static void main(String... argv) {
|
||||
int errors = 0;
|
||||
|
||||
for (int i = 0; i < DoubleConsts.SIGNIFICAND_WIDTH-1; i++) {
|
||||
errors += testNanCase(1L<<i);
|
||||
}
|
||||
|
||||
if (doubleToLongBits(Double.POSITIVE_INFINITY)
|
||||
!= 0x7ff0000000000000L) {
|
||||
errors++;
|
||||
System.err.println("Bad conversion for +infinity.");
|
||||
}
|
||||
|
||||
if (doubleToLongBits(Double.NEGATIVE_INFINITY)
|
||||
!= 0xfff0000000000000L) {
|
||||
errors++;
|
||||
System.err.println("Bad conversion for -infinity.");
|
||||
}
|
||||
|
||||
if (errors > 0)
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
68
test/jdk/java/lang/Double/Constants.java
Normal file
68
test/jdk/java/lang/Double/Constants.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @compile Constants.java
|
||||
* @bug 4397405 4826652
|
||||
* @summary Testing constant-ness of Double.{MIN_VALUE, MAX_VALUE}, etc.
|
||||
*/
|
||||
|
||||
public class Constants {
|
||||
/*
|
||||
* This compile-only test is to make sure that the primitive
|
||||
* public static final fields in java.lang.Double are "constant
|
||||
* expressions" as defined by "The Java Language Specification,
|
||||
* 2nd edition" section 15.28; a different test checks the values
|
||||
* of those fields.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
int i = 0;
|
||||
switch (i) {
|
||||
case (int)Double.NaN: // 0
|
||||
System.out.println("Double.NaN is a constant!");
|
||||
break;
|
||||
case (int)Double.MIN_VALUE + 1: // 0 + 1
|
||||
System.out.println("Double.MIN_VALUE is a constant!");
|
||||
break;
|
||||
case (int)Double.MIN_NORMAL + 2: // 0 + 2
|
||||
System.out.println("Double.MIN_NORMAL is a constant!");
|
||||
break;
|
||||
case Double.MIN_EXPONENT: // -1022
|
||||
System.out.println("Double.MIN_EXPONENT is a constant!");
|
||||
break;
|
||||
case Double.MAX_EXPONENT: // 1023
|
||||
System.out.println("Double.MAX_EXPONENT is a constant!");
|
||||
break;
|
||||
case (int)Double.MAX_VALUE - 1: // Integer.MAX_VALUE - 1
|
||||
System.out.println("Double.MAX_VALUE is a constant!");
|
||||
break;
|
||||
case (int)Double.POSITIVE_INFINITY: // Integer.MAX_VALUE
|
||||
System.out.println("Double.POSITIVE_INFINITY is a constant!");
|
||||
break;
|
||||
case (int)Double.NEGATIVE_INFINITY: // Integer.MIN_VALUE
|
||||
System.out.println("Double.NEGATIVE_INFINITY is a constant!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
test/jdk/java/lang/Double/Extrema.java
Normal file
44
test/jdk/java/lang/Double/Extrema.java
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4408489 4826652
|
||||
* @summary Testing values of Double.{MIN_VALUE, MIN_NORMAL, MAX_VALUE}
|
||||
*/
|
||||
|
||||
public class Extrema {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (Double.MIN_VALUE != Double.longBitsToDouble(0x1L))
|
||||
throw new RuntimeException("Double.MIN_VALUE is not equal "+
|
||||
"to longBitsToDouble(0x1L).");
|
||||
|
||||
if (Double.MIN_NORMAL != Double.longBitsToDouble(0x0010000000000000L))
|
||||
throw new RuntimeException("Double.MIN_NORMAL is not equal "+
|
||||
"to longBitsToDouble(0x0010000000000000L).");
|
||||
|
||||
if (Double.MAX_VALUE != Double.longBitsToDouble(0x7fefffffffffffffL))
|
||||
throw new RuntimeException("Double.MAX_VALUE is not equal "+
|
||||
"to longBitsToDouble(0x7fefffffffffffffL).");
|
||||
}
|
||||
}
|
||||
168
test/jdk/java/lang/Double/NaNInfinityParsing.java
Normal file
168
test/jdk/java/lang/Double/NaNInfinityParsing.java
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4428772
|
||||
* @summary Testing recognition of "NaN" and "Infinity" strings
|
||||
*/
|
||||
|
||||
|
||||
public class NaNInfinityParsing {
|
||||
/*
|
||||
* Regression tests for:
|
||||
* 4428772 -- Establish invariant for Float & Double classes and
|
||||
* their string representations
|
||||
*
|
||||
* Added capability for parse{Float, Double} and related methods
|
||||
* to recognize "NaN" and "Infinity" strings so that
|
||||
* parseDouble(toString(d)) will always return the original
|
||||
* floating-point value.
|
||||
*/
|
||||
|
||||
static String NaNStrings[] = {
|
||||
"NaN",
|
||||
"+NaN",
|
||||
"-NaN"
|
||||
};
|
||||
|
||||
static String infinityStrings[] = {
|
||||
"Infinity",
|
||||
"+Infinity",
|
||||
"-Infinity",
|
||||
};
|
||||
|
||||
static String invalidStrings[] = {
|
||||
"+",
|
||||
"-",
|
||||
"@",
|
||||
"N",
|
||||
"Na",
|
||||
"Nan",
|
||||
"NaNf",
|
||||
"NaNd",
|
||||
"NaNF",
|
||||
"NaND",
|
||||
"+N",
|
||||
"+Na",
|
||||
"+Nan",
|
||||
"+NaNf",
|
||||
"+NaNd",
|
||||
"+NaNF",
|
||||
"+NaND",
|
||||
"-N",
|
||||
"-Na",
|
||||
"-Nan",
|
||||
"-NaNf",
|
||||
"-NaNd",
|
||||
"-NaNF",
|
||||
"-NaND",
|
||||
"I",
|
||||
"In",
|
||||
"Inf",
|
||||
"Infi",
|
||||
"Infin",
|
||||
"Infini",
|
||||
"Infinit",
|
||||
"InfinitY",
|
||||
"Infinityf",
|
||||
"InfinityF",
|
||||
"Infinityd",
|
||||
"InfinityD",
|
||||
"+I",
|
||||
"+In",
|
||||
"+Inf",
|
||||
"+Infi",
|
||||
"+Infin",
|
||||
"+Infini",
|
||||
"+Infinit",
|
||||
"+InfinitY",
|
||||
"+Infinityf",
|
||||
"+InfinityF",
|
||||
"+Infinityd",
|
||||
"+InfinityD",
|
||||
"-I",
|
||||
"-In",
|
||||
"-Inf",
|
||||
"-Infi",
|
||||
"-Infin",
|
||||
"-Infini",
|
||||
"-Infinit",
|
||||
"-InfinitY",
|
||||
"-Infinityf",
|
||||
"-InfinityF",
|
||||
"-Infinityd",
|
||||
"-InfinityD",
|
||||
"NaNInfinity",
|
||||
"InfinityNaN",
|
||||
"nan",
|
||||
"infinity"
|
||||
};
|
||||
|
||||
public static void main(String [] argv) throws Exception {
|
||||
int i;
|
||||
double d;
|
||||
|
||||
// Test valid NaN strings
|
||||
for(i = 0; i < NaNStrings.length; i++) {
|
||||
if(!Double.isNaN(d=Double.parseDouble(NaNStrings[i]))) {
|
||||
throw new RuntimeException("NaN string ``" + NaNStrings[i]
|
||||
+ "'' did not parse as a NaN; returned " +
|
||||
d + " instead.");
|
||||
}
|
||||
}
|
||||
|
||||
// Test valid Infinity strings
|
||||
for(i = 0; i < infinityStrings.length; i++) {
|
||||
if(!Double.isInfinite(d=Double.parseDouble(infinityStrings[i]))) {
|
||||
throw new RuntimeException("Infinity string ``" +
|
||||
infinityStrings[i] +
|
||||
"'' did not parse as infinity; returned " +
|
||||
d + "instead.");
|
||||
}
|
||||
// check sign of result
|
||||
|
||||
boolean negative = (infinityStrings[i].charAt(0) == '-');
|
||||
if(d != (negative?Double.NEGATIVE_INFINITY:
|
||||
Double.POSITIVE_INFINITY))
|
||||
throw new RuntimeException("Infinity has wrong sign;" +
|
||||
(negative?"positive instead of negative.":
|
||||
"negative instead of positive."));
|
||||
}
|
||||
|
||||
// Test almost valid strings
|
||||
for(i = 0; i < invalidStrings.length; i++) {
|
||||
try {
|
||||
double result;
|
||||
d = Double.parseDouble(invalidStrings[i]);
|
||||
throw new RuntimeException("Invalid string ``" +
|
||||
invalidStrings[i]
|
||||
+"'' parsed as " + d + ".");
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
816
test/jdk/java/lang/Double/ParseDouble.java
Normal file
816
test/jdk/java/lang/Double/ParseDouble.java
Normal file
|
|
@ -0,0 +1,816 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4160406 4705734 4707389 4826774 4895911 4421494 6358355 7021568
|
||||
* 7039369 4396272 8366017
|
||||
* @summary Test for Double.parseDouble method and acceptance regex
|
||||
*/
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.regex.*;
|
||||
|
||||
public class ParseDouble {
|
||||
|
||||
private static final BigDecimal HALF = BigDecimal.valueOf(0.5);
|
||||
|
||||
private static void fail(String val, double n) {
|
||||
throw new RuntimeException("Double.parseDouble failed. String:" +
|
||||
val + " Result:" + n);
|
||||
}
|
||||
|
||||
private static void check(String val) {
|
||||
double n = Double.parseDouble(val);
|
||||
boolean isNegativeN = n < 0 || n == 0 && 1/n < 0;
|
||||
double na = Math.abs(n);
|
||||
String s = val.trim().toLowerCase();
|
||||
switch (s.charAt(s.length() - 1)) {
|
||||
case 'd':
|
||||
case 'f':
|
||||
s = s.substring(0, s.length() - 1);
|
||||
break;
|
||||
}
|
||||
boolean isNegative = false;
|
||||
if (s.charAt(0) == '+') {
|
||||
s = s.substring(1);
|
||||
} else if (s.charAt(0) == '-') {
|
||||
s = s.substring(1);
|
||||
isNegative = true;
|
||||
}
|
||||
if (s.equals("nan")) {
|
||||
if (!Double.isNaN(n)) {
|
||||
fail(val, n);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (Double.isNaN(n)) {
|
||||
fail(val, n);
|
||||
}
|
||||
if (isNegativeN != isNegative)
|
||||
fail(val, n);
|
||||
if (s.equals("infinity")) {
|
||||
if (na != Double.POSITIVE_INFINITY) {
|
||||
fail(val, n);
|
||||
}
|
||||
return;
|
||||
}
|
||||
BigDecimal bd;
|
||||
if (s.startsWith("0x")) {
|
||||
s = s.substring(2);
|
||||
int indP = s.indexOf('p');
|
||||
long exp = Long.parseLong(s.substring(indP + 1));
|
||||
int indD = s.indexOf('.');
|
||||
String significand;
|
||||
if (indD >= 0) {
|
||||
significand = s.substring(0, indD) + s.substring(indD + 1, indP);
|
||||
exp -= 4*(indP - indD - 1);
|
||||
} else {
|
||||
significand = s.substring(0, indP);
|
||||
}
|
||||
bd = new BigDecimal(new BigInteger(significand, 16));
|
||||
if (exp >= 0) {
|
||||
bd = bd.multiply(BigDecimal.valueOf(2).pow((int)exp));
|
||||
} else {
|
||||
bd = bd.divide(BigDecimal.valueOf(2).pow((int)-exp));
|
||||
}
|
||||
} else {
|
||||
bd = new BigDecimal(s);
|
||||
}
|
||||
BigDecimal l, u;
|
||||
if (Double.isInfinite(na)) {
|
||||
l = new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF));
|
||||
u = null;
|
||||
} else {
|
||||
l = new BigDecimal(na).subtract(new BigDecimal(Math.ulp(Math.nextUp(-na))).multiply(HALF));
|
||||
u = new BigDecimal(na).add(new BigDecimal(Math.ulp(n)).multiply(HALF));
|
||||
}
|
||||
int cmpL = bd.compareTo(l);
|
||||
int cmpU = u != null ? bd.compareTo(u) : -1;
|
||||
if ((Double.doubleToLongBits(n) & 1) != 0) {
|
||||
if (cmpL <= 0 || cmpU >= 0) {
|
||||
fail(val, n);
|
||||
}
|
||||
} else {
|
||||
if (cmpL < 0 || cmpU > 0) {
|
||||
fail(val, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void check(String val, double expected) {
|
||||
double n = Double.parseDouble(val);
|
||||
if (n != expected)
|
||||
fail(val, n);
|
||||
check(val);
|
||||
}
|
||||
|
||||
private static void rudimentaryTest() {
|
||||
check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE);
|
||||
check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE);
|
||||
|
||||
check("10", (double) 10.0);
|
||||
check("10.0", (double) 10.0);
|
||||
check("10.01", (double) 10.01);
|
||||
|
||||
check("-10", (double) -10.0);
|
||||
check("-10.00", (double) -10.0);
|
||||
check("-10.01", (double) -10.01);
|
||||
}
|
||||
|
||||
|
||||
static String badStrings[] = {
|
||||
"",
|
||||
"+",
|
||||
"-",
|
||||
"+e",
|
||||
"-e",
|
||||
"+e170",
|
||||
"-e170",
|
||||
|
||||
// Make sure intermediate white space is not deleted.
|
||||
"1234 e10",
|
||||
"-1234 e10",
|
||||
|
||||
// Control characters in the interior of a string are not legal
|
||||
"1\u0007e1",
|
||||
"1e\u00071",
|
||||
|
||||
// NaN and infinity can't have trailing type suffices or exponents
|
||||
"NaNf",
|
||||
"NaNF",
|
||||
"NaNd",
|
||||
"NaND",
|
||||
"-NaNf",
|
||||
"-NaNF",
|
||||
"-NaNd",
|
||||
"-NaND",
|
||||
"+NaNf",
|
||||
"+NaNF",
|
||||
"+NaNd",
|
||||
"+NaND",
|
||||
"Infinityf",
|
||||
"InfinityF",
|
||||
"Infinityd",
|
||||
"InfinityD",
|
||||
"-Infinityf",
|
||||
"-InfinityF",
|
||||
"-Infinityd",
|
||||
"-InfinityD",
|
||||
"+Infinityf",
|
||||
"+InfinityF",
|
||||
"+Infinityd",
|
||||
"+InfinityD",
|
||||
|
||||
"NaNe10",
|
||||
"-NaNe10",
|
||||
"+NaNe10",
|
||||
"Infinitye10",
|
||||
"-Infinitye10",
|
||||
"+Infinitye10",
|
||||
|
||||
// Non-ASCII digits are not recognized
|
||||
"\u0661e\u0661", // 1e1 in Arabic-Indic digits
|
||||
"\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits
|
||||
"\u0967e\u0967", // 1e1 in Devanagari digits
|
||||
"\uD835\uDFD9e\uD835\uDFD9", // 1e1 in Mathematical Alphanumeric Symbols
|
||||
|
||||
// JCK test lex03592m3
|
||||
".",
|
||||
|
||||
// JCK test lex03592m4
|
||||
"e42",
|
||||
|
||||
// JCK test lex03592m5
|
||||
".e42",
|
||||
|
||||
// JCK test lex03592m6
|
||||
"d",
|
||||
|
||||
// JCK test lex03592m7
|
||||
".d",
|
||||
|
||||
// JCK test lex03592m8
|
||||
"e42d",
|
||||
|
||||
// JCK test lex03592m9
|
||||
".e42d",
|
||||
|
||||
// JCK test lex03593m10
|
||||
"1A01.01125e-10d",
|
||||
|
||||
// JCK test lex03593m11
|
||||
"2;3.01125e-10d",
|
||||
|
||||
// JCK test lex03593m12
|
||||
"1_34.01125e-10d",
|
||||
|
||||
// JCK test lex03593m14
|
||||
"202..01125e-10d",
|
||||
|
||||
// JCK test lex03593m15
|
||||
"202,01125e-10d",
|
||||
|
||||
// JCK test lex03593m16
|
||||
"202.03b4e-10d",
|
||||
|
||||
// JCK test lex03593m18
|
||||
"202.06_3e-10d",
|
||||
|
||||
// JCK test lex03593m20
|
||||
"202.01125e-f0d",
|
||||
|
||||
// JCK test lex03593m21
|
||||
"202.01125e_3d",
|
||||
|
||||
// JCK test lex03593m22
|
||||
"202.01125e -5d",
|
||||
|
||||
// JCK test lex03593m24
|
||||
"202.01125e-10r",
|
||||
|
||||
// JCK test lex03593m25
|
||||
"202.01125e-10ff",
|
||||
|
||||
// JCK test lex03593m26
|
||||
"1234L.01",
|
||||
|
||||
// JCK test lex03593m27
|
||||
"12ee-2",
|
||||
|
||||
// JCK test lex03593m28
|
||||
"12e-2.2.2",
|
||||
|
||||
// JCK test lex03593m29
|
||||
"12.01e+",
|
||||
|
||||
// JCK test lex03593m30
|
||||
"12.01E",
|
||||
|
||||
// Bad hexadecimal-style strings
|
||||
|
||||
// Two leading zeros
|
||||
"00x1.0p1",
|
||||
|
||||
// Must have hex specifier
|
||||
"1.0p1",
|
||||
"00010p1",
|
||||
"deadbeefp1",
|
||||
|
||||
// Need an explicit fully-formed exponent
|
||||
"0x1.0p",
|
||||
"0x1.0",
|
||||
|
||||
// Exponent must be in decimal
|
||||
"0x1.0pa",
|
||||
"0x1.0pf",
|
||||
|
||||
// Exponent separated by "p"
|
||||
"0x1.0e22",
|
||||
"0x1.0e22",
|
||||
|
||||
// Need a signifcand
|
||||
"0xp22"
|
||||
};
|
||||
|
||||
static String goodStrings[] = {
|
||||
"NaN",
|
||||
"+NaN",
|
||||
"-NaN",
|
||||
"Infinity",
|
||||
"+Infinity",
|
||||
"-Infinity",
|
||||
"1.1e-23f",
|
||||
".1e-23f",
|
||||
"1e-23",
|
||||
"1f",
|
||||
"0",
|
||||
"-0",
|
||||
"+0",
|
||||
"00",
|
||||
"00",
|
||||
"-00",
|
||||
"+00",
|
||||
"0000000000",
|
||||
"-0000000000",
|
||||
"+0000000000",
|
||||
"1",
|
||||
"2",
|
||||
"1234",
|
||||
"-1234",
|
||||
"+1234",
|
||||
"2147483647", // Integer.MAX_VALUE
|
||||
"2147483648",
|
||||
"-2147483648", // Integer.MIN_VALUE
|
||||
"-2147483649",
|
||||
|
||||
"16777215",
|
||||
"16777216", // 2^24
|
||||
"16777217",
|
||||
|
||||
"-16777215",
|
||||
"-16777216", // -2^24
|
||||
"-16777217",
|
||||
|
||||
"9007199254740991",
|
||||
"9007199254740992", // 2^53
|
||||
"9007199254740993",
|
||||
|
||||
"-9007199254740991",
|
||||
"-9007199254740992", // -2^53
|
||||
"-9007199254740993",
|
||||
|
||||
"9223372036854775807",
|
||||
"9223372036854775808", // Long.MAX_VALUE
|
||||
"9223372036854775809",
|
||||
|
||||
"-9223372036854775808",
|
||||
"-9223372036854775809", // Long.MIN_VALUE
|
||||
"-9223372036854775810",
|
||||
|
||||
// Culled from JCK test lex03591m1
|
||||
"54.07140d",
|
||||
"7.01e-324d",
|
||||
"2147483647.01d",
|
||||
"1.2147483647f",
|
||||
"000000000000000000000000001.F",
|
||||
"1.00000000000000000000000000e-2F",
|
||||
|
||||
// Culled from JCK test lex03592m2
|
||||
"2.",
|
||||
".0909",
|
||||
"122112217090.0",
|
||||
"7090e-5",
|
||||
"2.E-20",
|
||||
".0909e42",
|
||||
"122112217090.0E+100",
|
||||
"7090f",
|
||||
"2.F",
|
||||
".0909d",
|
||||
"122112217090.0D",
|
||||
"7090e-5f",
|
||||
"2.E-20F",
|
||||
".0909e42d",
|
||||
"122112217090.0E+100D",
|
||||
|
||||
// Culled from JCK test lex03594m31 -- unicode escapes
|
||||
"\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D",
|
||||
"1290873\u002E12301e100",
|
||||
"1.1E-10\u0066",
|
||||
|
||||
// Culled from JCK test lex03595m1
|
||||
"0.0E-10",
|
||||
"1E10",
|
||||
|
||||
// Culled from JCK test lex03691m1
|
||||
"0.f",
|
||||
"1f",
|
||||
"0.F",
|
||||
"1F",
|
||||
"0.12d",
|
||||
"1e-0d",
|
||||
"12.e+1D",
|
||||
"0e-0D",
|
||||
"12.e+01",
|
||||
"1e-01",
|
||||
|
||||
// Good hex strings
|
||||
// Vary capitalization of separators.
|
||||
|
||||
"0x1p1",
|
||||
"0X1p1",
|
||||
"0x1P1",
|
||||
"0X1P1",
|
||||
"0x1p1f",
|
||||
"0X1p1f",
|
||||
"0x1P1f",
|
||||
"0X1P1f",
|
||||
"0x1p1F",
|
||||
"0X1p1F",
|
||||
"0x1P1F",
|
||||
"0X1P1F",
|
||||
"0x1p1d",
|
||||
"0X1p1d",
|
||||
"0x1P1d",
|
||||
"0X1P1d",
|
||||
"0x1p1D",
|
||||
"0X1p1D",
|
||||
"0x1P1D",
|
||||
"0X1P1D",
|
||||
|
||||
"-0x1p1",
|
||||
"-0X1p1",
|
||||
"-0x1P1",
|
||||
"-0X1P1",
|
||||
"-0x1p1f",
|
||||
"-0X1p1f",
|
||||
"-0x1P1f",
|
||||
"-0X1P1f",
|
||||
"-0x1p1F",
|
||||
"-0X1p1F",
|
||||
"-0x1P1F",
|
||||
"-0X1P1F",
|
||||
"-0x1p1d",
|
||||
"-0X1p1d",
|
||||
"-0x1P1d",
|
||||
"-0X1P1d",
|
||||
"-0x1p1D",
|
||||
"-0X1p1D",
|
||||
"-0x1P1D",
|
||||
"-0X1P1D",
|
||||
|
||||
"0x1p-1",
|
||||
"0X1p-1",
|
||||
"0x1P-1",
|
||||
"0X1P-1",
|
||||
"0x1p-1f",
|
||||
"0X1p-1f",
|
||||
"0x1P-1f",
|
||||
"0X1P-1f",
|
||||
"0x1p-1F",
|
||||
"0X1p-1F",
|
||||
"0x1P-1F",
|
||||
"0X1P-1F",
|
||||
"0x1p-1d",
|
||||
"0X1p-1d",
|
||||
"0x1P-1d",
|
||||
"0X1P-1d",
|
||||
"0x1p-1D",
|
||||
"0X1p-1D",
|
||||
"0x1P-1D",
|
||||
"0X1P-1D",
|
||||
|
||||
"-0x1p-1",
|
||||
"-0X1p-1",
|
||||
"-0x1P-1",
|
||||
"-0X1P-1",
|
||||
"-0x1p-1f",
|
||||
"-0X1p-1f",
|
||||
"-0x1P-1f",
|
||||
"-0X1P-1f",
|
||||
"-0x1p-1F",
|
||||
"-0X1p-1F",
|
||||
"-0x1P-1F",
|
||||
"-0X1P-1F",
|
||||
"-0x1p-1d",
|
||||
"-0X1p-1d",
|
||||
"-0x1P-1d",
|
||||
"-0X1P-1d",
|
||||
"-0x1p-1D",
|
||||
"-0X1p-1D",
|
||||
"-0x1P-1D",
|
||||
"-0X1P-1D",
|
||||
|
||||
|
||||
// Try different significand combinations
|
||||
"0xap1",
|
||||
"0xbp1",
|
||||
"0xcp1",
|
||||
"0xdp1",
|
||||
"0xep1",
|
||||
"0xfp1",
|
||||
|
||||
"0x1p1",
|
||||
"0x.1p1",
|
||||
"0x1.1p1",
|
||||
|
||||
"0x001p23",
|
||||
"0x00.1p1",
|
||||
"0x001.1p1",
|
||||
|
||||
"0x100p1",
|
||||
"0x.100p1",
|
||||
"0x1.100p1",
|
||||
|
||||
"0x00100p1",
|
||||
"0x00.100p1",
|
||||
"0x001.100p1",
|
||||
|
||||
// Limits
|
||||
|
||||
"1.7976931348623157E308", // Double.MAX_VALUE
|
||||
"4.9e-324", // Double.MIN_VALUE
|
||||
"2.2250738585072014e-308", // Double.MIN_NORMAL
|
||||
|
||||
"2.2250738585072012e-308", // near Double.MIN_NORMAL
|
||||
|
||||
"1.7976931348623158e+308", // near MAX_VALUE + ulp(MAX_VALUE)/2
|
||||
"1.7976931348623159e+308", // near MAX_VALUE + ulp(MAX_VALUE)
|
||||
|
||||
"2.4703282292062329e-324", // above MIN_VALUE/2
|
||||
"2.4703282292062327e-324", // MIN_VALUE/2
|
||||
"2.4703282292062325e-324", // below MIN_VALUE/2
|
||||
|
||||
// 1e308 with leading zeros
|
||||
|
||||
"0.0000000000001e321",
|
||||
"00.000000000000000001e326",
|
||||
"00000.000000000000000001e326",
|
||||
"000.0000000000000000001e327",
|
||||
"0.00000000000000000001e328",
|
||||
};
|
||||
|
||||
static String paddedBadStrings[];
|
||||
static String paddedGoodStrings[];
|
||||
static {
|
||||
String pad = " \t\n\r\f\u0001\u000b\u001f";
|
||||
paddedBadStrings = new String[badStrings.length];
|
||||
for(int i = 0 ; i < badStrings.length; i++)
|
||||
paddedBadStrings[i] = pad + badStrings[i] + pad;
|
||||
|
||||
paddedGoodStrings = new String[goodStrings.length];
|
||||
for(int i = 0 ; i < goodStrings.length; i++)
|
||||
paddedGoodStrings[i] = pad + goodStrings[i] + pad;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Throws an exception if <code>Input</code> is
|
||||
* <code>exceptionalInput</code> and {@link Double.parseDouble
|
||||
* parseDouble} does <em>not</em> throw an exception or if
|
||||
* <code>Input</code> is not <code>exceptionalInput</code> and
|
||||
* <code>parseDouble</code> throws an exception. This method does
|
||||
* not attempt to test whether the string is converted to the
|
||||
* proper value; just whether the input is accepted appropriately
|
||||
* or not.
|
||||
*/
|
||||
private static void testParsing(String [] input,
|
||||
boolean exceptionalInput) {
|
||||
for (String s : input) {
|
||||
try {
|
||||
Double.parseDouble(s);
|
||||
check(s);
|
||||
} catch (NumberFormatException e) {
|
||||
if (!exceptionalInput) {
|
||||
throw new RuntimeException("Double.parseDouble rejected " +
|
||||
"good string `" + s +
|
||||
"'.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (exceptionalInput) {
|
||||
throw new RuntimeException("Double.parseDouble accepted " +
|
||||
"bad string `" + s +
|
||||
"'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Throws an exception if <code>Input</code> is
|
||||
* <code>exceptionalInput</code> and the regular expression
|
||||
* matches one of the strings or if <code>Input</code> is not
|
||||
* <code>exceptionalInput</code> and the regular expression fails
|
||||
* to match an input string.
|
||||
*/
|
||||
private static void testRegex(String [] input, boolean exceptionalInput) {
|
||||
/*
|
||||
* The regex below is taken from the JavaDoc for
|
||||
* Double.valueOf.
|
||||
*/
|
||||
|
||||
final String Digits = "(\\p{Digit}+)";
|
||||
final String HexDigits = "(\\p{XDigit}+)";
|
||||
// an exponent is 'e' or 'E' followed by an optionally
|
||||
// signed decimal integer.
|
||||
final String Exp = "[eE][+-]?"+Digits;
|
||||
final String fpRegex =
|
||||
("[\\x00-\\x20]*"+ // Optional leading "whitespace"
|
||||
"[+-]?(" + // Optional sign character
|
||||
"NaN|" + // "NaN" string
|
||||
"Infinity|" + // "Infinity" string
|
||||
|
||||
// A floating-point string representing a finite positive
|
||||
// number without a leading sign has at most five basic pieces:
|
||||
// Digits . Digits ExponentPart FloatTypeSuffix
|
||||
//
|
||||
// Since this method allows integer-only strings as input
|
||||
// in addition to strings of floating-point literals, the
|
||||
// two sub-patterns below are simplifications of the grammar
|
||||
// productions from the Java Language Specification, 2nd
|
||||
// edition, section 3.10.2.
|
||||
|
||||
|
||||
// A decimal floating-point string representing a finite positive
|
||||
// number without a leading sign has at most five basic pieces:
|
||||
// Digits . Digits ExponentPart FloatTypeSuffix
|
||||
//
|
||||
// Since this method allows integer-only strings as input
|
||||
// in addition to strings of floating-point literals, the
|
||||
// two sub-patterns below are simplifications of the grammar
|
||||
// productions from the Java Language Specification, 2nd
|
||||
// edition, section 3.10.2.
|
||||
|
||||
// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
|
||||
"(((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
|
||||
|
||||
// . Digits ExponentPart_opt FloatTypeSuffix_opt
|
||||
"(\\.("+Digits+")("+Exp+")?))|"+
|
||||
|
||||
// Hexadecimal strings
|
||||
"((" +
|
||||
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
|
||||
"(0[xX]" + HexDigits + "(\\.)?)|" +
|
||||
|
||||
// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
|
||||
"(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
|
||||
|
||||
")[pP][+-]?" + Digits + "))" +
|
||||
"[fFdD]?))" +
|
||||
"[\\x00-\\x20]*");// Optional trailing "whitespace"
|
||||
Pattern fpPattern = Pattern.compile(fpRegex);
|
||||
|
||||
for(int i = 0; i < input.length; i++) {
|
||||
Matcher m = fpPattern.matcher(input[i]);
|
||||
if (m.matches() != ! exceptionalInput) {
|
||||
throw new RuntimeException("Regular expression " +
|
||||
(exceptionalInput?
|
||||
"accepted bad":
|
||||
"rejected good") +
|
||||
" string `" +
|
||||
input[i] + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* For each subnormal power of two, test at boundaries of
|
||||
* region that should convert to that value.
|
||||
*/
|
||||
private static void testSubnormalPowers() {
|
||||
boolean failed = false;
|
||||
BigDecimal TWO = BigDecimal.valueOf(2);
|
||||
// An ulp is the same for all subnormal values
|
||||
BigDecimal ulp_BD = new BigDecimal(Double.MIN_VALUE);
|
||||
|
||||
// Test subnormal powers of two (except Double.MIN_VALUE)
|
||||
for(int i = -1073; i <= -1022; i++) {
|
||||
double d = Math.scalb(1.0, i);
|
||||
|
||||
/*
|
||||
* The region [d - ulp/2, d + ulp/2] should round to d.
|
||||
*/
|
||||
BigDecimal d_BD = new BigDecimal(d);
|
||||
|
||||
BigDecimal lowerBound = d_BD.subtract(ulp_BD.divide(TWO));
|
||||
BigDecimal upperBound = d_BD.add(ulp_BD.divide(TWO));
|
||||
|
||||
double convertedLowerBound = Double.parseDouble(lowerBound.toString());
|
||||
double convertedUpperBound = Double.parseDouble(upperBound.toString());
|
||||
if (convertedLowerBound != d) {
|
||||
failed = true;
|
||||
System.out.printf("2^%d lowerBound converts as %a %s%n",
|
||||
i, convertedLowerBound, lowerBound);
|
||||
}
|
||||
if (convertedUpperBound != d) {
|
||||
failed = true;
|
||||
System.out.printf("2^%d upperBound converts as %a %s%n",
|
||||
i, convertedUpperBound, upperBound);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Double.MIN_VALUE
|
||||
* The region ]0.5*Double.MIN_VALUE, 1.5*Double.MIN_VALUE[ should round to Double.MIN_VALUE .
|
||||
*/
|
||||
BigDecimal minValue = new BigDecimal(Double.MIN_VALUE);
|
||||
if (Double.parseDouble(minValue.multiply(new BigDecimal(0.5)).toString()) != 0.0) {
|
||||
failed = true;
|
||||
System.out.printf("0.5*MIN_VALUE doesn't convert 0%n");
|
||||
}
|
||||
if (Double.parseDouble(minValue.multiply(new BigDecimal(0.50000000001)).toString()) != Double.MIN_VALUE) {
|
||||
failed = true;
|
||||
System.out.printf("0.50000000001*MIN_VALUE doesn't convert to MIN_VALUE%n");
|
||||
}
|
||||
if (Double.parseDouble(minValue.multiply(new BigDecimal(1.49999999999)).toString()) != Double.MIN_VALUE) {
|
||||
failed = true;
|
||||
System.out.printf("1.49999999999*MIN_VALUE doesn't convert to MIN_VALUE%n");
|
||||
}
|
||||
if (Double.parseDouble(minValue.multiply(new BigDecimal(1.5)).toString()) != 2*Double.MIN_VALUE) {
|
||||
failed = true;
|
||||
System.out.printf("1.5*MIN_VALUE doesn't convert to 2*MIN_VALUE%n");
|
||||
}
|
||||
|
||||
if (failed)
|
||||
throw new RuntimeException("Inconsistent conversion");
|
||||
}
|
||||
|
||||
/**
|
||||
* For each power of two, test at boundaries of
|
||||
* region that should convert to that value.
|
||||
*/
|
||||
private static void testPowers() {
|
||||
for(int i = -1074; i <= +1023; i++) {
|
||||
double d = Math.scalb(1.0, i);
|
||||
BigDecimal d_BD = new BigDecimal(d);
|
||||
|
||||
BigDecimal lowerBound = d_BD.subtract(new BigDecimal(Math.ulp(Math.nextUp(-d))).multiply(HALF));
|
||||
BigDecimal upperBound = d_BD.add(new BigDecimal(Math.ulp(d)).multiply(HALF));
|
||||
|
||||
check(lowerBound.toString());
|
||||
check(upperBound.toString());
|
||||
}
|
||||
check(new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF)).toString());
|
||||
}
|
||||
|
||||
private static void testStrictness() {
|
||||
final double expected = 0x0.0000008000000p-1022;
|
||||
// final double expected = 0x0.0000008000001p-1022;
|
||||
boolean failed = false;
|
||||
double conversion = 0.0;
|
||||
double sum = 0.0; // Prevent conversion from being optimized away
|
||||
|
||||
//2^-1047 + 2^-1075 rounds to 2^-1047
|
||||
String decimal = "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316";
|
||||
|
||||
for(int i = 0; i <= 12_000; i++) {
|
||||
conversion = Double.parseDouble(decimal);
|
||||
sum += conversion;
|
||||
if (conversion != expected) {
|
||||
failed = true;
|
||||
System.out.printf("Iteration %d converts as %a%n",
|
||||
i, conversion);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Sum = " + sum);
|
||||
if (failed)
|
||||
throw new RuntimeException("Inconsistent conversion");
|
||||
}
|
||||
|
||||
private static void testFastPaths() {
|
||||
/* Exercises the fast paths in jdk.internal.math.FloatingDecimal. */
|
||||
check("1", 0x1.0p0); // 1.0
|
||||
check("2.34000e2", 0x1.d4p7); // 234.0
|
||||
check("9.223e18", 0x1.fffab689adb6p62); // 9.223e18
|
||||
check("9.876e18", 0x1.121d33597384p63); // 9.876e18
|
||||
check("9223372036854776833", 0x1.0000000000001p63); // 9.223372036854778E18
|
||||
check("9223372036854776832", 0x1.0p63); // 9.223372036854776E18
|
||||
|
||||
check("1.23", 0x1.3ae147ae147aep0); // 1.23
|
||||
check("0.000234", 0x1.eabbcb1cc9646p-13); // 2.34E-4
|
||||
check("3.45e23", 0x1.2439f32cbea41p78); // 3.45E23
|
||||
check("576460752303423616e20", 0x1.5af1d78b58c41p125); // 5.764607523034236E37
|
||||
|
||||
check("1e37", 0x1.e17b84357691bp122); // 1.0E37
|
||||
check("8999e34", 0x1.0ecdc63717fbdp126); // 8.999E37
|
||||
check("0.9999e36", 0x1.8125c09cb78b7p119); // 9.999E35
|
||||
check("0.9876e37", 0x1.db831933296cep122); // 9.876E36
|
||||
|
||||
check("1.2e-200", 0x1.d64af4cc52935p-665); // 1.2E-200
|
||||
check("2.3e100", 0x1.507ed84d17a69p333); // 2.3E100
|
||||
check("1.2000000000000000003e-200", 0x1.d64af4cc52935p-665); // 1.2E-200
|
||||
check("2.3000000000000000004e100", 0x1.507ed84d17a69p333); // 2.3E100
|
||||
check("5.249320425370670463e308", Double.POSITIVE_INFINITY);
|
||||
check("5.2493204253706704633e308", Double.POSITIVE_INFINITY);
|
||||
|
||||
check("1.2e-320", 0x0.000000000097dp-1022); // 1.2E-320
|
||||
check("1.2000000000000000003e-320", 0x0.000000000097dp-1022); // 1.2E-320
|
||||
|
||||
check("2.225073858507201383e-308", Double.MIN_NORMAL);
|
||||
check("2.2250738585072013831e-308", Double.MIN_NORMAL);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
rudimentaryTest();
|
||||
|
||||
testParsing(goodStrings, false);
|
||||
testParsing(paddedGoodStrings, false);
|
||||
testParsing(badStrings, true);
|
||||
testParsing(paddedBadStrings, true);
|
||||
|
||||
testRegex(goodStrings, false);
|
||||
testRegex(paddedGoodStrings, false);
|
||||
testRegex(badStrings, true);
|
||||
testRegex(paddedBadStrings, true);
|
||||
|
||||
testSubnormalPowers();
|
||||
testPowers();
|
||||
testStrictness();
|
||||
|
||||
testFastPaths();
|
||||
}
|
||||
|
||||
}
|
||||
448
test/jdk/java/lang/Double/ParseHexFloatingPoint.java
Normal file
448
test/jdk/java/lang/Double/ParseHexFloatingPoint.java
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main ParseHexFloatingPoint
|
||||
* @bug 4826774 8078672
|
||||
* @summary Numerical tests for hexadecimal inputs to parse{Double, Float} (use -Dseed=X to set PRNG seed)
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import jdk.test.lib.RandomFactory;
|
||||
|
||||
public class ParseHexFloatingPoint {
|
||||
private ParseHexFloatingPoint(){}
|
||||
|
||||
public static final double infinityD = Double.POSITIVE_INFINITY;
|
||||
public static final double NaND = Double.NaN;
|
||||
|
||||
static int test(String testName, String input,
|
||||
double result, double expected) {
|
||||
int failures =0;
|
||||
|
||||
if (Double.compare(result, expected) != 0 ) {
|
||||
System.err.println("Failure for " + testName +
|
||||
": For input " + input +
|
||||
" expected " + expected +
|
||||
" got " + result + ".");
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
static int testCase(String input, double expected) {
|
||||
int failures =0;
|
||||
|
||||
|
||||
// Try different combination of letter components
|
||||
input = input.toLowerCase(java.util.Locale.US);
|
||||
|
||||
String [] suffices = {"", "f", "F", "d", "D"};
|
||||
String [] signs = {"", "-", "+"};
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
String s1 = input;
|
||||
if(i == 1)
|
||||
s1 = s1.replace('x', 'X');
|
||||
|
||||
for(int j = 0; j < 2; j++) {
|
||||
String s2 = s1;
|
||||
if(j == 1)
|
||||
s2 = s2.replace('p', 'P');
|
||||
|
||||
for(int k = 0; k < 2; k++) {
|
||||
String s3 = s2;
|
||||
if(k == 1)
|
||||
s3 = upperCaseHex(s3);
|
||||
|
||||
|
||||
for(int m = 0; m < suffices.length; m++) {
|
||||
String s4 = s3 + suffices[m];
|
||||
|
||||
|
||||
for(int n = 0; n < signs.length; n++) {
|
||||
String s5 = signs[n] + s4;
|
||||
|
||||
double result = Double.parseDouble(s5);
|
||||
failures += test("Double.parseDouble",
|
||||
s5, result, (signs[n].equals("-") ?
|
||||
-expected:
|
||||
expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
static String upperCaseHex(String s) {
|
||||
return s.replace('a', 'A').replace('b', 'B').replace('c', 'C').
|
||||
replace('d', 'D').replace('e','E').replace('f', 'F');
|
||||
}
|
||||
|
||||
/*
|
||||
* Test easy and tricky double rounding cases.
|
||||
*/
|
||||
static int doubleTests() {
|
||||
|
||||
/*
|
||||
* A String, double pair
|
||||
*/
|
||||
class PairSD {
|
||||
public String s;
|
||||
public double d;
|
||||
PairSD(String s, double d) {
|
||||
this.s = s;
|
||||
this.d = d;
|
||||
}
|
||||
}
|
||||
int failures = 0;
|
||||
|
||||
|
||||
|
||||
// Hex strings that convert to three; test basic functionality
|
||||
// of significand and exponent shift adjusts along with the
|
||||
// no-op of adding leading zeros. These cases don't exercise
|
||||
// the rounding code.
|
||||
String leadingZeros = "0x0000000000000000000";
|
||||
String [] threeTests = {
|
||||
"0x.003p12",
|
||||
"0x.006p11",
|
||||
"0x.00cp10",
|
||||
"0x.018p9",
|
||||
|
||||
"0x.3p4",
|
||||
"0x.6p3",
|
||||
"0x.cp2",
|
||||
"0x1.8p1",
|
||||
|
||||
"0x3p0",
|
||||
"0x6.0p-1",
|
||||
"0xc.0p-2",
|
||||
"0x18.0p-3",
|
||||
|
||||
"0x3000000p-24",
|
||||
"0x3.0p0",
|
||||
"0x3.000000p0",
|
||||
};
|
||||
for(int i=0; i < threeTests.length; i++) {
|
||||
String input = threeTests[i];
|
||||
failures += testCase(input, 3.0);
|
||||
|
||||
input.replaceFirst("^0x", leadingZeros);
|
||||
failures += testCase(input, 3.0);
|
||||
}
|
||||
|
||||
long bigExponents [] = {
|
||||
2*Double.MAX_EXPONENT,
|
||||
2*Double.MIN_EXPONENT,
|
||||
|
||||
(long)Integer.MAX_VALUE-1,
|
||||
(long)Integer.MAX_VALUE,
|
||||
(long)Integer.MAX_VALUE+1,
|
||||
|
||||
(long)Integer.MIN_VALUE-1,
|
||||
(long)Integer.MIN_VALUE,
|
||||
(long)Integer.MIN_VALUE+1,
|
||||
|
||||
Long.MAX_VALUE-1,
|
||||
Long.MAX_VALUE,
|
||||
|
||||
Long.MIN_VALUE+1,
|
||||
Long.MIN_VALUE,
|
||||
};
|
||||
|
||||
// Test zero significand with large exponents.
|
||||
for(int i = 0; i < bigExponents.length; i++) {
|
||||
failures += testCase("0x0.0p"+Long.toString(bigExponents[i]) , 0.0);
|
||||
}
|
||||
|
||||
// Test nonzero significand with large exponents.
|
||||
for(int i = 0; i < bigExponents.length; i++) {
|
||||
long exponent = bigExponents[i];
|
||||
failures += testCase("0x10000.0p"+Long.toString(exponent) ,
|
||||
(exponent <0?0.0:infinityD));
|
||||
}
|
||||
|
||||
// Test significands with different lengths and bit patterns.
|
||||
{
|
||||
long signif = 0;
|
||||
for(int i = 1; i <= 0xe; i++) {
|
||||
signif = (signif <<4) | (long)i;
|
||||
failures += testCase("0x"+Long.toHexString(signif)+"p0", signif);
|
||||
}
|
||||
}
|
||||
|
||||
PairSD [] testCases = {
|
||||
new PairSD("0x0.0p0", 0.0/16.0),
|
||||
new PairSD("0x0.1p0", 1.0/16.0),
|
||||
new PairSD("0x0.2p0", 2.0/16.0),
|
||||
new PairSD("0x0.3p0", 3.0/16.0),
|
||||
new PairSD("0x0.4p0", 4.0/16.0),
|
||||
new PairSD("0x0.5p0", 5.0/16.0),
|
||||
new PairSD("0x0.6p0", 6.0/16.0),
|
||||
new PairSD("0x0.7p0", 7.0/16.0),
|
||||
new PairSD("0x0.8p0", 8.0/16.0),
|
||||
new PairSD("0x0.9p0", 9.0/16.0),
|
||||
new PairSD("0x0.ap0", 10.0/16.0),
|
||||
new PairSD("0x0.bp0", 11.0/16.0),
|
||||
new PairSD("0x0.cp0", 12.0/16.0),
|
||||
new PairSD("0x0.dp0", 13.0/16.0),
|
||||
new PairSD("0x0.ep0", 14.0/16.0),
|
||||
new PairSD("0x0.fp0", 15.0/16.0),
|
||||
|
||||
// Half-way case between zero and MIN_VALUE rounds down to
|
||||
// zero
|
||||
new PairSD("0x1.0p-1075", 0.0),
|
||||
|
||||
// Slighly more than half-way case between zero and
|
||||
// MIN_VALUES rounds up to zero.
|
||||
new PairSD("0x1.1p-1075", Double.MIN_VALUE),
|
||||
new PairSD("0x1.000000000001p-1075", Double.MIN_VALUE),
|
||||
new PairSD("0x1.000000000000001p-1075", Double.MIN_VALUE),
|
||||
|
||||
// More subnormal rounding tests
|
||||
new PairSD("0x0.fffffffffffff7fffffp-1022", Math.nextDown(Double.MIN_NORMAL)),
|
||||
new PairSD("0x0.fffffffffffff8p-1022", Double.MIN_NORMAL),
|
||||
new PairSD("0x0.fffffffffffff800000001p-1022",Double.MIN_NORMAL),
|
||||
new PairSD("0x0.fffffffffffff80000000000000001p-1022",Double.MIN_NORMAL),
|
||||
new PairSD("0x1.0p-1022", Double.MIN_NORMAL),
|
||||
|
||||
|
||||
// Large value and overflow rounding tests
|
||||
new PairSD("0x1.fffffffffffffp1023", Double.MAX_VALUE),
|
||||
new PairSD("0x1.fffffffffffff0000000p1023", Double.MAX_VALUE),
|
||||
new PairSD("0x1.fffffffffffff4p1023", Double.MAX_VALUE),
|
||||
new PairSD("0x1.fffffffffffff7fffffp1023", Double.MAX_VALUE),
|
||||
new PairSD("0x1.fffffffffffff8p1023", infinityD),
|
||||
new PairSD("0x1.fffffffffffff8000001p1023", infinityD),
|
||||
|
||||
new PairSD("0x1.ffffffffffffep1023", Math.nextDown(Double.MAX_VALUE)),
|
||||
new PairSD("0x1.ffffffffffffe0000p1023", Math.nextDown(Double.MAX_VALUE)),
|
||||
new PairSD("0x1.ffffffffffffe8p1023", Math.nextDown(Double.MAX_VALUE)),
|
||||
new PairSD("0x1.ffffffffffffe7p1023", Math.nextDown(Double.MAX_VALUE)),
|
||||
new PairSD("0x1.ffffffffffffeffffffp1023", Double.MAX_VALUE),
|
||||
new PairSD("0x1.ffffffffffffe8000001p1023", Double.MAX_VALUE),
|
||||
};
|
||||
|
||||
for (int i = 0; i < testCases.length; i++) {
|
||||
failures += testCase(testCases[i].s,testCases[i].d);
|
||||
}
|
||||
|
||||
failures += significandAlignmentTests();
|
||||
|
||||
{
|
||||
java.util.Random rand = RandomFactory.getRandom();
|
||||
// Consistency check; double => hexadecimal => double
|
||||
// preserves the original value.
|
||||
for(int i = 0; i < 1000; i++) {
|
||||
double d = rand.nextDouble();
|
||||
failures += testCase(Double.toHexString(d), d);
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify rounding works the same regardless of how the
|
||||
* significand is aligned on input. A useful extension could be
|
||||
* to have this sort of test for strings near the overflow
|
||||
* threshold.
|
||||
*/
|
||||
static int significandAlignmentTests() {
|
||||
int failures = 0;
|
||||
// baseSignif * 2^baseExp = nextDown(2.0)
|
||||
long [] baseSignifs = {
|
||||
0x1ffffffffffffe00L,
|
||||
0x1fffffffffffff00L
|
||||
};
|
||||
|
||||
double [] answers = {
|
||||
Math.nextDown(Math.nextDown(2.0)),
|
||||
Math.nextDown(2.0),
|
||||
2.0
|
||||
};
|
||||
|
||||
int baseExp = -60;
|
||||
int count = 0;
|
||||
for(int i = 0; i < 2; i++) {
|
||||
for(long j = 0; j <= 0xfL; j++) {
|
||||
for(long k = 0; k <= 8; k+= 4) { // k = {0, 4, 8}
|
||||
long base = baseSignifs[i];
|
||||
long testValue = base | (j<<4) | k;
|
||||
|
||||
int offset = 0;
|
||||
// Calculate when significand should be incremented
|
||||
// see table 4.7 in Koren book
|
||||
|
||||
if ((base & 0x100L) == 0L ) { // lsb is 0
|
||||
if ( (j >= 8L) && // round is 1
|
||||
((j & 0x7L) != 0 || k != 0 ) ) // sticky is 1
|
||||
offset = 1;
|
||||
}
|
||||
else { // lsb is 1
|
||||
if (j >= 8L) // round is 1
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
double expected = answers[i+offset];
|
||||
|
||||
for(int m = -2; m <= 3; m++) {
|
||||
count ++;
|
||||
|
||||
// Form equal value string and evaluate it
|
||||
String s = "0x" +
|
||||
Long.toHexString((m >=0) ?(testValue<<m):(testValue>>(-m))) +
|
||||
"p" + (baseExp - m);
|
||||
|
||||
failures += testCase(s, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test tricky float rounding cases. The code which
|
||||
* reads in a hex string converts the string to a double value.
|
||||
* If a float value is needed, the double value is cast to float.
|
||||
* However, the cast be itself not always guaranteed to return the
|
||||
* right result since:
|
||||
*
|
||||
* 1. hex string => double can discard a sticky bit which would
|
||||
* influence a direct hex string => float conversion.
|
||||
*
|
||||
* 2. hex string => double => float can have a rounding to double
|
||||
* precision which results in a larger float value while a direct
|
||||
* hex string => float conversion would not round up.
|
||||
*
|
||||
* This method includes tests of the latter two possibilities.
|
||||
*/
|
||||
static int floatTests(){
|
||||
int failures = 0;
|
||||
|
||||
/*
|
||||
* A String, float pair
|
||||
*/
|
||||
class PairSD {
|
||||
public String s;
|
||||
public float f;
|
||||
PairSD(String s, float f) {
|
||||
this.s = s;
|
||||
this.f = f;
|
||||
}
|
||||
}
|
||||
|
||||
String [][] roundingTestCases = {
|
||||
// Target float value hard rouding version
|
||||
|
||||
{"0x1.000000p0", "0x1.0000000000001p0"},
|
||||
|
||||
// Try some values that should round up to nextUp(1.0f)
|
||||
{"0x1.000002p0", "0x1.0000010000001p0"},
|
||||
{"0x1.000002p0", "0x1.00000100000008p0"},
|
||||
{"0x1.000002p0", "0x1.0000010000000fp0"},
|
||||
{"0x1.000002p0", "0x1.00000100000001p0"},
|
||||
{"0x1.000002p0", "0x1.00000100000000000000000000000000000000001p0"},
|
||||
{"0x1.000002p0", "0x1.0000010000000fp0"},
|
||||
|
||||
// Potential double rounding cases
|
||||
{"0x1.000002p0", "0x1.000002fffffffp0"},
|
||||
{"0x1.000002p0", "0x1.000002fffffff8p0"},
|
||||
{"0x1.000002p0", "0x1.000002ffffffffp0"},
|
||||
|
||||
{"0x1.000002p0", "0x1.000002ffff0ffp0"},
|
||||
{"0x1.000002p0", "0x1.000002ffff0ff8p0"},
|
||||
{"0x1.000002p0", "0x1.000002ffff0fffp0"},
|
||||
|
||||
|
||||
{"0x1.000000p0", "0x1.000000fffffffp0"},
|
||||
{"0x1.000000p0", "0x1.000000fffffff8p0"},
|
||||
{"0x1.000000p0", "0x1.000000ffffffffp0"},
|
||||
|
||||
{"0x1.000000p0", "0x1.000000ffffffep0"},
|
||||
{"0x1.000000p0", "0x1.000000ffffffe8p0"},
|
||||
{"0x1.000000p0", "0x1.000000ffffffefp0"},
|
||||
|
||||
// Float subnormal cases
|
||||
{"0x0.000002p-126", "0x0.0000010000001p-126"},
|
||||
{"0x0.000002p-126", "0x0.00000100000000000001p-126"},
|
||||
|
||||
{"0x0.000006p-126", "0x0.0000050000001p-126"},
|
||||
{"0x0.000006p-126", "0x0.00000500000000000001p-126"},
|
||||
|
||||
{"0x0.0p-149", "0x0.7ffffffffffffffp-149"},
|
||||
{"0x1.0p-148", "0x1.3ffffffffffffffp-148"},
|
||||
{"0x1.cp-147", "0x1.bffffffffffffffp-147"},
|
||||
|
||||
{"0x1.fffffcp-127", "0x1.fffffdffffffffp-127"},
|
||||
};
|
||||
|
||||
String [] signs = {"", "-"};
|
||||
|
||||
for(int i = 0; i < roundingTestCases.length; i++) {
|
||||
for(int j = 0; j < signs.length; j++) {
|
||||
String expectedIn = signs[j]+roundingTestCases[i][0];
|
||||
String resultIn = signs[j]+roundingTestCases[i][1];
|
||||
|
||||
float expected = Float.parseFloat(expectedIn);
|
||||
float result = Float.parseFloat(resultIn);
|
||||
|
||||
if( Float.compare(expected, result) != 0) {
|
||||
failures += 1;
|
||||
System.err.println("" + (i+1));
|
||||
System.err.println("Expected = " + Float.toHexString(expected));
|
||||
System.err.println("Rounded = " + Float.toHexString(result));
|
||||
System.err.println("Double = " + Double.toHexString(Double.parseDouble(resultIn)));
|
||||
System.err.println("Input = " + resultIn);
|
||||
System.err.println("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
int failures = 0;
|
||||
|
||||
failures += doubleTests();
|
||||
failures += floatTests();
|
||||
|
||||
if (failures != 0) {
|
||||
throw new RuntimeException("" + failures + " failures while " +
|
||||
"testing hexadecimal floating-point " +
|
||||
"parsing.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
273
test/jdk/java/lang/Double/ToHexString.java
Normal file
273
test/jdk/java/lang/Double/ToHexString.java
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4826774 4926547
|
||||
* @summary Tests for {Float, Double}.toHexString methods
|
||||
* @library ../Math
|
||||
* @build DoubleConsts
|
||||
* @run main ToHexString
|
||||
*/
|
||||
|
||||
import java.util.regex.*;
|
||||
|
||||
public class ToHexString {
|
||||
private ToHexString() {}
|
||||
|
||||
/*
|
||||
* Given a double value, create a hexadecimal floating-point
|
||||
* string via an intermediate long hex string.
|
||||
*/
|
||||
static String doubleToHexString(double d) {
|
||||
return hexLongStringtoHexDoubleString(Long.toHexString(Double.doubleToLongBits(d)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform the hexadecimal long output into the equivalent
|
||||
* hexadecimal double value.
|
||||
*/
|
||||
static String hexLongStringtoHexDoubleString(String transString) {
|
||||
transString = transString.toLowerCase();
|
||||
|
||||
String zeros = "";
|
||||
StringBuffer result = new StringBuffer(24);
|
||||
|
||||
for(int i = 0; i < (16 - transString.length()); i++, zeros += "0");
|
||||
transString = zeros + transString;
|
||||
|
||||
// assert transString.length == 16;
|
||||
|
||||
char topChar;
|
||||
// Extract sign
|
||||
if((topChar=transString.charAt(0)) >= '8' ) {// 8, 9, a, A, b, B, ...
|
||||
result.append("-");
|
||||
// clear sign bit
|
||||
transString =
|
||||
Character.toString(Character.forDigit(Character.digit(topChar, 16) - 8, 16)) +
|
||||
transString.substring(1,16);
|
||||
}
|
||||
|
||||
// check for NaN and infinity
|
||||
String signifString = transString.substring(3,16);
|
||||
|
||||
if( transString.substring(0,3).equals("7ff") ) {
|
||||
if(signifString.equals("0000000000000")) {
|
||||
result.append("Infinity");
|
||||
}
|
||||
else
|
||||
result.append("NaN");
|
||||
}
|
||||
else { // finite value
|
||||
// Extract exponent
|
||||
int exponent = Integer.parseInt(transString.substring(0,3), 16) -
|
||||
DoubleConsts.EXP_BIAS;
|
||||
result.append("0x");
|
||||
|
||||
if (exponent == Double.MIN_EXPONENT - 1) { // zero or subnormal
|
||||
if(signifString.equals("0000000000000")) {
|
||||
result.append("0.0p0");
|
||||
}
|
||||
else {
|
||||
result.append("0." + signifString.replaceFirst("0+$", "").replaceFirst("^$", "0") +
|
||||
"p-1022");
|
||||
}
|
||||
}
|
||||
else { // normal value
|
||||
result.append("1." + signifString.replaceFirst("0+$", "").replaceFirst("^$", "0") +
|
||||
"p" + exponent);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static int toHexStringTests() {
|
||||
int failures = 0;
|
||||
String [][] testCases1 = {
|
||||
{"Infinity", "Infinity"},
|
||||
{"-Infinity", "-Infinity"},
|
||||
{"NaN", "NaN"},
|
||||
{"-NaN", "NaN"},
|
||||
{"0.0", "0x0.0p0"},
|
||||
{"-0.0", "-0x0.0p0"},
|
||||
{"1.0", "0x1.0p0"},
|
||||
{"-1.0", "-0x1.0p0"},
|
||||
{"2.0", "0x1.0p1"},
|
||||
{"3.0", "0x1.8p1"},
|
||||
{"0.5", "0x1.0p-1"},
|
||||
{"0.25", "0x1.0p-2"},
|
||||
{"1.7976931348623157e+308", "0x1.fffffffffffffp1023"}, // MAX_VALUE
|
||||
{"2.2250738585072014E-308", "0x1.0p-1022"}, // MIN_NORMAL
|
||||
{"2.225073858507201E-308", "0x0.fffffffffffffp-1022"}, // MAX_SUBNORMAL
|
||||
{"4.9e-324", "0x0.0000000000001p-1022"} // MIN_VALUE
|
||||
};
|
||||
|
||||
// Compare decimal string -> double -> hex string to hex string
|
||||
for (int i = 0; i < testCases1.length; i++) {
|
||||
String result;
|
||||
if(! (result=Double.toHexString(Double.parseDouble(testCases1[i][0]))).
|
||||
equals(testCases1[i][1])) {
|
||||
failures ++;
|
||||
System.err.println("For floating-point string " + testCases1[i][0] +
|
||||
", expected hex output " + testCases1[i][1] + ", got " + result +".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Except for float subnormals, the output for numerically
|
||||
// equal float and double values should be the same.
|
||||
// Therefore, we will explicitly test float subnormal values.
|
||||
String [][] floatTestCases = {
|
||||
{"Infinity", "Infinity"},
|
||||
{"-Infinity", "-Infinity"},
|
||||
{"NaN", "NaN"},
|
||||
{"-NaN", "NaN"},
|
||||
{"0.0", "0x0.0p0"},
|
||||
{"-0.0", "-0x0.0p0"},
|
||||
{"1.0", "0x1.0p0"},
|
||||
{"-1.0", "-0x1.0p0"},
|
||||
{"2.0", "0x1.0p1"},
|
||||
{"3.0", "0x1.8p1"},
|
||||
{"0.5", "0x1.0p-1"},
|
||||
{"0.25", "0x1.0p-2"},
|
||||
{"3.4028235e+38f", "0x1.fffffep127"}, // MAX_VALUE
|
||||
{"1.17549435E-38f", "0x1.0p-126"}, // MIN_NORMAL
|
||||
{"1.1754942E-38", "0x0.fffffep-126"}, // MAX_SUBNORMAL
|
||||
{"1.4e-45f", "0x0.000002p-126"} // MIN_VALUE
|
||||
};
|
||||
// Compare decimal string -> double -> hex string to hex string
|
||||
for (int i = 0; i < floatTestCases.length; i++) {
|
||||
String result;
|
||||
if(! (result=Float.toHexString(Float.parseFloat(floatTestCases[i][0]))).
|
||||
equals(floatTestCases[i][1])) {
|
||||
failures++;
|
||||
System.err.println("For floating-point string " + floatTestCases[i][0] +
|
||||
", expected hex output\n" + floatTestCases[i][1] + ", got\n" + result +".");
|
||||
}
|
||||
}
|
||||
|
||||
// Particular floating-point values and hex equivalents, mostly
|
||||
// taken from fdlibm source.
|
||||
String [][] testCases2 = {
|
||||
{"+0.0", "0000000000000000"},
|
||||
{"-0.0", "8000000000000000"},
|
||||
{"+4.9e-324", "0000000000000001"},
|
||||
{"-4.9e-324", "8000000000000001"},
|
||||
|
||||
// Test cases for trailing zeros in significand
|
||||
// These test the removal of trailing zeros in the hexadecimal representation
|
||||
// The comments indicate the number of trailing zeros removed from the significand
|
||||
// For "0x1.0p1", there are 13 trailing zeros in the significand, but only 12 are removed
|
||||
// as we always keep at least one hex digit in the significand
|
||||
{"0x1.0p1", "4000000000000000"}, // 12 trailing zeros removed (13 total, but only 12 removed)
|
||||
{"0x1.1p1", "4001000000000000"}, // 12 trailing zeros removed (all zeros after '1')
|
||||
{"0x1.01p1", "4000100000000000"}, // 11 trailing zeros removed
|
||||
{"0x1.001p1", "4000010000000000"}, // 10 trailing zeros removed
|
||||
{"0x1.0001p1", "4000001000000000"}, // 9 trailing zeros removed
|
||||
{"0x1.00001p1", "4000000100000000"}, // 8 trailing zeros removed
|
||||
{"0x1.000001p1", "4000000010000000"}, // 7 trailing zeros removed
|
||||
{"0x1.0000001p1", "4000000001000000"}, // 6 trailing zeros removed
|
||||
{"0x1.00000001p1", "4000000000100000"}, // 5 trailing zeros removed
|
||||
{"0x1.000000001p1", "4000000000010000"}, // 4 trailing zeros removed
|
||||
{"0x1.0000000001p1", "4000000000001000"}, // 3 trailing zeros removed
|
||||
{"0x1.00000000001p1", "4000000000000100"}, // 2 trailing zeros removed
|
||||
{"0x1.000000000001p1", "4000000000000010"}, // 1 trailing zero removed (minimum)
|
||||
{"0x1.0000000000001p1", "4000000000000001"}, // 0 trailing zeros removed (no trailing zeros to remove)
|
||||
|
||||
// fdlibm k_sin.c
|
||||
{"+5.00000000000000000000e-01", "3FE0000000000000"},
|
||||
{"-1.66666666666666324348e-01", "BFC5555555555549"},
|
||||
{"+8.33333333332248946124e-03", "3F8111111110F8A6"},
|
||||
{"-1.98412698298579493134e-04", "BF2A01A019C161D5"},
|
||||
{"+2.75573137070700676789e-06", "3EC71DE357B1FE7D"},
|
||||
{"-2.50507602534068634195e-08", "BE5AE5E68A2B9CEB"},
|
||||
{"+1.58969099521155010221e-10", "3DE5D93A5ACFD57C"},
|
||||
|
||||
// fdlibm k_cos.c
|
||||
{"+4.16666666666666019037e-02", "3FA555555555554C"},
|
||||
{"-1.38888888888741095749e-03", "BF56C16C16C15177"},
|
||||
{"+2.48015872894767294178e-05", "3EFA01A019CB1590"},
|
||||
{"-2.75573143513906633035e-07", "BE927E4F809C52AD"},
|
||||
{"+2.08757232129817482790e-09", "3E21EE9EBDB4B1C4"},
|
||||
{"-1.13596475577881948265e-11", "BDA8FAE9BE8838D4"},
|
||||
|
||||
// fdlibm e_rempio.c
|
||||
{"1.67772160000000000000e+07", "4170000000000000"},
|
||||
{"6.36619772367581382433e-01", "3FE45F306DC9C883"},
|
||||
{"1.57079632673412561417e+00", "3FF921FB54400000"},
|
||||
{"6.07710050650619224932e-11", "3DD0B4611A626331"},
|
||||
{"6.07710050630396597660e-11", "3DD0B4611A600000"},
|
||||
{"2.02226624879595063154e-21", "3BA3198A2E037073"},
|
||||
{"2.02226624871116645580e-21", "3BA3198A2E000000"},
|
||||
{"8.47842766036889956997e-32", "397B839A252049C1"},
|
||||
|
||||
|
||||
// fdlibm s_cbrt.c
|
||||
{"+5.42857142857142815906e-01", "3FE15F15F15F15F1"},
|
||||
{"-7.05306122448979611050e-01", "BFE691DE2532C834"},
|
||||
{"+1.41428571428571436819e+00", "3FF6A0EA0EA0EA0F"},
|
||||
{"+1.60714285714285720630e+00", "3FF9B6DB6DB6DB6E"},
|
||||
{"+3.57142857142857150787e-01", "3FD6DB6DB6DB6DB7"},
|
||||
};
|
||||
|
||||
// Compare decimal string -> double -> hex string to
|
||||
// long hex string -> double hex string
|
||||
for (int i = 0; i < testCases2.length; i++) {
|
||||
String result;
|
||||
String expected;
|
||||
if(! (result=Double.toHexString(Double.parseDouble(testCases2[i][0]))).
|
||||
equals( expected=hexLongStringtoHexDoubleString(testCases2[i][1]) )) {
|
||||
failures ++;
|
||||
System.err.println("For floating-point string " + testCases2[i][0] +
|
||||
", expected hex output " + expected + ", got " + result +".");
|
||||
}
|
||||
}
|
||||
|
||||
// Test random double values;
|
||||
// compare double -> Double.toHexString with local doubleToHexString
|
||||
java.util.Random rand = new java.util.Random(0);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
String result;
|
||||
String expected;
|
||||
double d = rand.nextDouble();
|
||||
if(! (expected=doubleToHexString(d)).equals(result=Double.toHexString(d)) ) {
|
||||
failures ++;
|
||||
System.err.println("For floating-point value " + d +
|
||||
", expected hex output " + expected + ", got " + result +".");
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
int failures = 0;
|
||||
|
||||
failures = toHexStringTests();
|
||||
|
||||
if (failures != 0) {
|
||||
throw new RuntimeException("" + failures + " failures while testing Double.toHexString");
|
||||
}
|
||||
}
|
||||
}
|
||||
39
test/jdk/java/lang/Double/ToString.java
Normal file
39
test/jdk/java/lang/Double/ToString.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4428022
|
||||
* @summary Tests for Double.toString
|
||||
* @author Andrew Haley <aph@redhat.com>
|
||||
*/
|
||||
|
||||
public class ToString {
|
||||
|
||||
public static void main(String args[]) {
|
||||
if (!Double.toString(0.001).equals("0.001"))
|
||||
throw new RuntimeException("Double.toString(0.001) is not \"0.001\"");
|
||||
if (!Double.toString(0.002).equals("0.002"))
|
||||
throw new RuntimeException("Double.toString(0.001) is not \"0.002\"");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue