7032154: Performance tuning of sun.misc.FloatingDecimal/FormattedFloatingDecimal
Performance improvements for double/float -> String and decimal/hex String -> double/float conversions. Co-authored-by: Sergey Kuksenko <sergey.kuksenko@oracle.com> Co-authored-by: Dmitry Nadezhin <dmitry.nadezhin@oracle.com> Co-authored-by: Olivier Lagneau <olivier.lagneau@oracle.com> Reviewed-by: martin, iris
This commit is contained in:
parent
854a6b898f
commit
a1fe63768f
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, 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
|
||||
@ -689,7 +689,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public AbstractStringBuilder append(float f) {
|
||||
new FloatingDecimal(f).appendTo(this);
|
||||
FloatingDecimal.appendTo(f,this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -706,7 +706,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public AbstractStringBuilder append(double d) {
|
||||
new FloatingDecimal(d).appendTo(this);
|
||||
FloatingDecimal.appendTo(d,this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ public final class Double extends Number implements Comparable<Double> {
|
||||
* @return a string representation of the argument.
|
||||
*/
|
||||
public static String toString(double d) {
|
||||
return new FloatingDecimal(d).toJavaFormatString();
|
||||
return FloatingDecimal.toJavaFormatString(d);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -509,7 +509,7 @@ public final class Double extends Number implements Comparable<Double> {
|
||||
* parsable number.
|
||||
*/
|
||||
public static Double valueOf(String s) throws NumberFormatException {
|
||||
return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
|
||||
return new Double(parseDouble(s));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -545,7 +545,7 @@ public final class Double extends Number implements Comparable<Double> {
|
||||
* @since 1.2
|
||||
*/
|
||||
public static double parseDouble(String s) throws NumberFormatException {
|
||||
return FloatingDecimal.readJavaFormatString(s).doubleValue();
|
||||
return FloatingDecimal.parseDouble(s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2013, 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
|
||||
@ -203,7 +203,7 @@ public final class Float extends Number implements Comparable<Float> {
|
||||
* @return a string representation of the argument.
|
||||
*/
|
||||
public static String toString(float f) {
|
||||
return new FloatingDecimal(f).toJavaFormatString();
|
||||
return FloatingDecimal.toJavaFormatString(f);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -421,7 +421,7 @@ public final class Float extends Number implements Comparable<Float> {
|
||||
* parsable number.
|
||||
*/
|
||||
public static Float valueOf(String s) throws NumberFormatException {
|
||||
return new Float(FloatingDecimal.readJavaFormatString(s).floatValue());
|
||||
return new Float(parseFloat(s));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -456,7 +456,7 @@ public final class Float extends Number implements Comparable<Float> {
|
||||
* @since 1.2
|
||||
*/
|
||||
public static float parseFloat(String s) throws NumberFormatException {
|
||||
return FloatingDecimal.readJavaFormatString(s).floatValue();
|
||||
return FloatingDecimal.parseFloat(s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -271,7 +271,7 @@ final class DigitList implements Cloneable {
|
||||
* @param maximumFractionDigits The most fractional digits which should
|
||||
* be converted.
|
||||
*/
|
||||
public final void set(boolean isNegative, double source, int maximumFractionDigits) {
|
||||
final void set(boolean isNegative, double source, int maximumFractionDigits) {
|
||||
set(isNegative, source, maximumFractionDigits, true);
|
||||
}
|
||||
|
||||
@ -288,10 +288,11 @@ final class DigitList implements Cloneable {
|
||||
*/
|
||||
final void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoint) {
|
||||
|
||||
FloatingDecimal fd = new FloatingDecimal(source);
|
||||
boolean hasBeenRoundedUp = fd.digitsRoundedUp();
|
||||
boolean allDecimalDigits = fd.decimalDigitsExact();
|
||||
String digitsString = fd.toJavaFormatString();
|
||||
FloatingDecimal.BinaryToASCIIConverter fdConverter = FloatingDecimal.getBinaryToASCIIConverter(source);
|
||||
boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp();
|
||||
boolean allDecimalDigits = fdConverter.decimalDigitsExact();
|
||||
assert !fdConverter.isExceptional();
|
||||
String digitsString = fdConverter.toJavaFormatString();
|
||||
|
||||
set(isNegative, digitsString,
|
||||
hasBeenRoundedUp, allDecimalDigits,
|
||||
@ -305,9 +306,9 @@ final class DigitList implements Cloneable {
|
||||
* @param allDecimalDigits Boolean value indicating if the digits in s are
|
||||
* an exact decimal representation of the double that was passed.
|
||||
*/
|
||||
final void set(boolean isNegative, String s,
|
||||
boolean roundedUp, boolean allDecimalDigits,
|
||||
int maximumDigits, boolean fixedPoint) {
|
||||
private void set(boolean isNegative, String s,
|
||||
boolean roundedUp, boolean allDecimalDigits,
|
||||
int maximumDigits, boolean fixedPoint) {
|
||||
this.isNegative = isNegative;
|
||||
int len = s.length();
|
||||
char[] source = getDataChars(len);
|
||||
@ -607,7 +608,7 @@ final class DigitList implements Cloneable {
|
||||
/**
|
||||
* Utility routine to set the value of the digit list from a long
|
||||
*/
|
||||
public final void set(boolean isNegative, long source) {
|
||||
final void set(boolean isNegative, long source) {
|
||||
set(isNegative, source, 0);
|
||||
}
|
||||
|
||||
@ -620,7 +621,7 @@ final class DigitList implements Cloneable {
|
||||
* If maximumDigits is lower than the number of significant digits
|
||||
* in source, the representation will be rounded. Ignored if <= 0.
|
||||
*/
|
||||
public final void set(boolean isNegative, long source, int maximumDigits) {
|
||||
final void set(boolean isNegative, long source, int maximumDigits) {
|
||||
this.isNegative = isNegative;
|
||||
|
||||
// This method does not expect a negative number. However,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, 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
|
||||
@ -2807,10 +2807,10 @@ public final class Formatter implements Closeable, Flushable {
|
||||
cal = Calendar.getInstance(l == null ? Locale.US : l);
|
||||
cal.setTime((Date)arg);
|
||||
} else if (arg instanceof Calendar) {
|
||||
cal = (Calendar) ((Calendar)arg).clone();
|
||||
cal = (Calendar) ((Calendar) arg).clone();
|
||||
cal.setLenient(true);
|
||||
} else if (arg instanceof TemporalAccessor) {
|
||||
print((TemporalAccessor)arg, c, l);
|
||||
print((TemporalAccessor) arg, c, l);
|
||||
return;
|
||||
} else {
|
||||
failConversion(c, arg);
|
||||
@ -3242,13 +3242,10 @@ public final class Formatter implements Closeable, Flushable {
|
||||
int prec = (precision == -1 ? 6 : precision);
|
||||
|
||||
FormattedFloatingDecimal fd
|
||||
= new FormattedFloatingDecimal(value, prec,
|
||||
FormattedFloatingDecimal.Form.SCIENTIFIC);
|
||||
= FormattedFloatingDecimal.valueOf(value, prec,
|
||||
FormattedFloatingDecimal.Form.SCIENTIFIC);
|
||||
|
||||
char[] v = new char[MAX_FD_CHARS];
|
||||
int len = fd.getChars(v);
|
||||
|
||||
char[] mant = addZeros(mantissa(v, len), prec);
|
||||
char[] mant = addZeros(fd.getMantissa(), prec);
|
||||
|
||||
// If the precision is zero and the '#' flag is set, add the
|
||||
// requested decimal point.
|
||||
@ -3256,7 +3253,7 @@ public final class Formatter implements Closeable, Flushable {
|
||||
mant = addDot(mant);
|
||||
|
||||
char[] exp = (value == 0.0)
|
||||
? new char[] {'+','0','0'} : exponent(v, len);
|
||||
? new char[] {'+','0','0'} : fd.getExponent();
|
||||
|
||||
int newW = width;
|
||||
if (width != -1)
|
||||
@ -3279,15 +3276,10 @@ public final class Formatter implements Closeable, Flushable {
|
||||
int prec = (precision == -1 ? 6 : precision);
|
||||
|
||||
FormattedFloatingDecimal fd
|
||||
= new FormattedFloatingDecimal(value, prec,
|
||||
FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
|
||||
= FormattedFloatingDecimal.valueOf(value, prec,
|
||||
FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
|
||||
|
||||
// MAX_FD_CHARS + 1 (round?)
|
||||
char[] v = new char[MAX_FD_CHARS + 1
|
||||
+ Math.abs(fd.getExponent())];
|
||||
int len = fd.getChars(v);
|
||||
|
||||
char[] mant = addZeros(mantissa(v, len), prec);
|
||||
char[] mant = addZeros(fd.getMantissa(), prec);
|
||||
|
||||
// If the precision is zero and the '#' flag is set, add the
|
||||
// requested decimal point.
|
||||
@ -3306,22 +3298,17 @@ public final class Formatter implements Closeable, Flushable {
|
||||
prec = 1;
|
||||
|
||||
FormattedFloatingDecimal fd
|
||||
= new FormattedFloatingDecimal(value, prec,
|
||||
FormattedFloatingDecimal.Form.GENERAL);
|
||||
= FormattedFloatingDecimal.valueOf(value, prec,
|
||||
FormattedFloatingDecimal.Form.GENERAL);
|
||||
|
||||
// MAX_FD_CHARS + 1 (round?)
|
||||
char[] v = new char[MAX_FD_CHARS + 1
|
||||
+ Math.abs(fd.getExponent())];
|
||||
int len = fd.getChars(v);
|
||||
|
||||
char[] exp = exponent(v, len);
|
||||
char[] exp = fd.getExponent();
|
||||
if (exp != null) {
|
||||
prec -= 1;
|
||||
} else {
|
||||
prec = prec - (value == 0 ? 0 : fd.getExponentRounded()) - 1;
|
||||
}
|
||||
|
||||
char[] mant = addZeros(mantissa(v, len), prec);
|
||||
char[] mant = addZeros(fd.getMantissa(), prec);
|
||||
// If the precision is zero and the '#' flag is set, add the
|
||||
// requested decimal point.
|
||||
if (f.contains(Flags.ALTERNATE) && (prec == 0))
|
||||
@ -3380,30 +3367,6 @@ public final class Formatter implements Closeable, Flushable {
|
||||
}
|
||||
}
|
||||
|
||||
private char[] mantissa(char[] v, int len) {
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (v[i] == 'e')
|
||||
break;
|
||||
}
|
||||
char[] tmp = new char[i];
|
||||
System.arraycopy(v, 0, tmp, 0, i);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private char[] exponent(char[] v, int len) {
|
||||
int i;
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if (v[i] == 'e')
|
||||
break;
|
||||
}
|
||||
if (i == -1)
|
||||
return null;
|
||||
char[] tmp = new char[len - i - 1];
|
||||
System.arraycopy(v, i + 1, tmp, 0, len - i - 1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Add zeros to the requested precision.
|
||||
private char[] addZeros(char[] v, int prec) {
|
||||
// Look for the dot. If we don't find one, the we'll need to add
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -4,9 +4,7 @@
|
||||
*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
* 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
|
||||
@ -23,41 +21,41 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
//package sun.misc;
|
||||
|
||||
/*
|
||||
* A really, really simple bigint package
|
||||
* tailored to the needs of floating base conversion.
|
||||
*/
|
||||
class FDBigInt {
|
||||
class OldFDBigIntForTest {
|
||||
int nWords; // number of words used
|
||||
int data[]; // value: data[0] is least significant
|
||||
|
||||
|
||||
public FDBigInt( int v ){
|
||||
public OldFDBigIntForTest( int v ){
|
||||
nWords = 1;
|
||||
data = new int[1];
|
||||
data[0] = v;
|
||||
}
|
||||
|
||||
public FDBigInt( long v ){
|
||||
public OldFDBigIntForTest( long v ){
|
||||
data = new int[2];
|
||||
data[0] = (int)v;
|
||||
data[1] = (int)(v>>>32);
|
||||
nWords = (data[1]==0) ? 1 : 2;
|
||||
}
|
||||
|
||||
public FDBigInt( FDBigInt other ){
|
||||
public OldFDBigIntForTest( OldFDBigIntForTest other ){
|
||||
data = new int[nWords = other.nWords];
|
||||
System.arraycopy( other.data, 0, data, 0, nWords );
|
||||
}
|
||||
|
||||
private FDBigInt( int [] d, int n ){
|
||||
private OldFDBigIntForTest( int [] d, int n ){
|
||||
data = d;
|
||||
nWords = n;
|
||||
}
|
||||
|
||||
public FDBigInt( long seed, char digit[], int nd0, int nd ){
|
||||
public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){
|
||||
int n= (nd+8)/9; // estimate size needed.
|
||||
if ( n < 2 ) n = 2;
|
||||
data = new int[n]; // allocate enough space
|
||||
@ -189,10 +187,10 @@ class FDBigInt {
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply a FDBigInt by an int.
|
||||
* Result is a new FDBigInt.
|
||||
* Multiply a OldFDBigIntForTest by an int.
|
||||
* Result is a new OldFDBigIntForTest.
|
||||
*/
|
||||
public FDBigInt
|
||||
public OldFDBigIntForTest
|
||||
mult( int iv ) {
|
||||
long v = iv;
|
||||
int r[];
|
||||
@ -207,15 +205,15 @@ class FDBigInt {
|
||||
p >>>= 32;
|
||||
}
|
||||
if ( p == 0L){
|
||||
return new FDBigInt( r, nWords );
|
||||
return new OldFDBigIntForTest( r, nWords );
|
||||
} else {
|
||||
r[nWords] = (int)p;
|
||||
return new FDBigInt( r, nWords+1 );
|
||||
return new OldFDBigIntForTest( r, nWords+1 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply a FDBigInt by an int and add another int.
|
||||
* Multiply a OldFDBigIntForTest by an int and add another int.
|
||||
* Result is computed in place.
|
||||
* Hope it fits!
|
||||
*/
|
||||
@ -240,11 +238,11 @@ class FDBigInt {
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply a FDBigInt by another FDBigInt.
|
||||
* Result is a new FDBigInt.
|
||||
* Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
|
||||
* Result is a new OldFDBigIntForTest.
|
||||
*/
|
||||
public FDBigInt
|
||||
mult( FDBigInt other ){
|
||||
public OldFDBigIntForTest
|
||||
mult( OldFDBigIntForTest other ){
|
||||
// crudely guess adequate size for r
|
||||
int r[] = new int[ nWords + other.nWords ];
|
||||
int i;
|
||||
@ -265,14 +263,14 @@ class FDBigInt {
|
||||
for ( i = r.length-1; i> 0; i--)
|
||||
if ( r[i] != 0 )
|
||||
break;
|
||||
return new FDBigInt( r, i+1 );
|
||||
return new OldFDBigIntForTest( r, i+1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add one FDBigInt to another. Return a FDBigInt
|
||||
* Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
|
||||
*/
|
||||
public FDBigInt
|
||||
add( FDBigInt other ){
|
||||
public OldFDBigIntForTest
|
||||
add( OldFDBigIntForTest other ){
|
||||
int i;
|
||||
int a[], b[];
|
||||
int n, m;
|
||||
@ -304,17 +302,17 @@ class FDBigInt {
|
||||
int s[] = new int[ r.length+1 ];
|
||||
System.arraycopy( r, 0, s, 0, r.length );
|
||||
s[i++] = (int)c;
|
||||
return new FDBigInt( s, i );
|
||||
return new OldFDBigIntForTest( s, i );
|
||||
}
|
||||
return new FDBigInt( r, i );
|
||||
return new OldFDBigIntForTest( r, i );
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract one FDBigInt from another. Return a FDBigInt
|
||||
* Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
|
||||
* Assert that the result is positive.
|
||||
*/
|
||||
public FDBigInt
|
||||
sub( FDBigInt other ){
|
||||
public OldFDBigIntForTest
|
||||
sub( OldFDBigIntForTest other ){
|
||||
int r[] = new int[ this.nWords ];
|
||||
int i;
|
||||
int n = this.nWords;
|
||||
@ -334,10 +332,10 @@ class FDBigInt {
|
||||
}
|
||||
assert c == 0L : c; // borrow out of subtract
|
||||
assert dataInRangeIsZero(i, m, other); // negative result of subtract
|
||||
return new FDBigInt( r, n-nzeros );
|
||||
return new OldFDBigIntForTest( r, n-nzeros );
|
||||
}
|
||||
|
||||
private static boolean dataInRangeIsZero(int i, int m, FDBigInt other) {
|
||||
private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
|
||||
while ( i < m )
|
||||
if (other.data[i++] != 0)
|
||||
return false;
|
||||
@ -345,13 +343,13 @@ class FDBigInt {
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare FDBigInt with another FDBigInt. Return an integer
|
||||
* Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
|
||||
* >0: this > other
|
||||
* 0: this == other
|
||||
* <0: this < other
|
||||
*/
|
||||
public int
|
||||
cmp( FDBigInt other ){
|
||||
cmp( OldFDBigIntForTest other ){
|
||||
int i;
|
||||
if ( this.nWords > other.nWords ){
|
||||
// if any of my high-order words is non-zero,
|
||||
@ -405,7 +403,7 @@ class FDBigInt {
|
||||
* as an integer, 0 <= q < 10.
|
||||
*/
|
||||
public int
|
||||
quoRemIteration( FDBigInt S )throws IllegalArgumentException {
|
||||
quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {
|
||||
// ensure that this and S have the same number of
|
||||
// digits. If S is properly normalized and q < 10 then
|
||||
// this must be so.
|
2436
jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java
Normal file
2436
jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java
Normal file
File diff suppressed because it is too large
Load Diff
426
jdk/test/sun/misc/FloatingDecimal/TestFDBigInteger.java
Normal file
426
jdk/test/sun/misc/FloatingDecimal/TestFDBigInteger.java
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
import sun.misc.FDBigInteger;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 7032154
|
||||
* @summary unit testys of sun.misc.FDBigInteger
|
||||
* @author Dmitry Nadezhin
|
||||
*/
|
||||
public class TestFDBigInteger {
|
||||
|
||||
private static final int MAX_P5 = 413;
|
||||
private static final int MAX_P2 = 65;
|
||||
private static final long LONG_SIGN_MASK = (1L << 63);
|
||||
private static final BigInteger FIVE = BigInteger.valueOf(5);
|
||||
private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
|
||||
private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
|
||||
private static final FDBigInteger IMMUTABLE_MILLION = genMillion1();
|
||||
private static final FDBigInteger IMMUTABLE_BILLION = genBillion1();
|
||||
private static final FDBigInteger IMMUTABLE_TEN18 = genTen18();
|
||||
|
||||
static {
|
||||
IMMUTABLE_ZERO.makeImmutable();
|
||||
IMMUTABLE_MILLION.makeImmutable();
|
||||
IMMUTABLE_BILLION.makeImmutable();
|
||||
IMMUTABLE_TEN18.makeImmutable();
|
||||
}
|
||||
|
||||
private static FDBigInteger mutable(String hex, int offset) {
|
||||
char[] chars = new BigInteger(hex, 16).toString().toCharArray();
|
||||
return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32);
|
||||
}
|
||||
|
||||
private static FDBigInteger immutable(String hex, int offset) {
|
||||
FDBigInteger fd = mutable(hex, offset);
|
||||
fd.makeImmutable();
|
||||
return fd;
|
||||
}
|
||||
|
||||
private static BigInteger biPow52(int p5, int p2) {
|
||||
return FIVE.pow(p5).shiftLeft(p2);
|
||||
}
|
||||
|
||||
// data.length == 1, nWords == 1, offset == 0
|
||||
private static FDBigInteger genMillion1() {
|
||||
return FDBigInteger.valueOfPow52(6, 0).leftShift(6);
|
||||
}
|
||||
|
||||
// data.length == 2, nWords == 1, offset == 0
|
||||
private static FDBigInteger genMillion2() {
|
||||
return FDBigInteger.valueOfMulPow52(1000000L, 0, 0);
|
||||
}
|
||||
|
||||
// data.length == 1, nWords == 1, offset == 0
|
||||
private static FDBigInteger genBillion1() {
|
||||
return FDBigInteger.valueOfPow52(9, 0).leftShift(9);
|
||||
}
|
||||
|
||||
// data.length == 2, nWords == 2, offset == 0
|
||||
private static FDBigInteger genTen18() {
|
||||
return FDBigInteger.valueOfPow52(18, 0).leftShift(18);
|
||||
}
|
||||
|
||||
private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception {
|
||||
if (!expected.equals(actual.toBigInteger())) {
|
||||
throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16));
|
||||
}
|
||||
}
|
||||
|
||||
private static void testValueOfPow52(int p5, int p2) throws Exception {
|
||||
check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2),
|
||||
"valueOfPow52(" + p5 + "," + p2 + ")");
|
||||
}
|
||||
|
||||
private static void testValueOfPow52() throws Exception {
|
||||
for (int p5 = 0; p5 <= MAX_P5; p5++) {
|
||||
for (int p2 = 0; p2 <= MAX_P2; p2++) {
|
||||
testValueOfPow52(p5, p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception {
|
||||
BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK);
|
||||
if (value < 0) {
|
||||
bi = bi.setBit(63);
|
||||
}
|
||||
check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2),
|
||||
"valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")");
|
||||
}
|
||||
|
||||
private static void testValueOfMulPow52(long value, int p5) throws Exception {
|
||||
testValueOfMulPow52(value, p5, 0);
|
||||
testValueOfMulPow52(value, p5, 1);
|
||||
testValueOfMulPow52(value, p5, 30);
|
||||
testValueOfMulPow52(value, p5, 31);
|
||||
testValueOfMulPow52(value, p5, 33);
|
||||
testValueOfMulPow52(value, p5, 63);
|
||||
}
|
||||
|
||||
private static void testValueOfMulPow52() throws Exception {
|
||||
for (int p5 = 0; p5 <= MAX_P5; p5++) {
|
||||
testValueOfMulPow52(0xFFFFFFFFL, p5);
|
||||
testValueOfMulPow52(0x123456789AL, p5);
|
||||
testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5);
|
||||
testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception {
|
||||
BigInteger bt = t.toBigInteger();
|
||||
FDBigInteger r = t.leftShift(shift);
|
||||
if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) {
|
||||
throw new Exception("leftShift doesn't reuse its argument");
|
||||
}
|
||||
if (isImmutable) {
|
||||
check(bt, t, "leftShift corrupts its argument");
|
||||
}
|
||||
check(bt.shiftLeft(shift), r, "leftShift returns wrong result");
|
||||
}
|
||||
|
||||
private static void testLeftShift() throws Exception {
|
||||
testLeftShift(IMMUTABLE_ZERO, 0, true);
|
||||
testLeftShift(IMMUTABLE_ZERO, 10, true);
|
||||
testLeftShift(MUTABLE_ZERO, 0, false);
|
||||
testLeftShift(MUTABLE_ZERO, 10, false);
|
||||
|
||||
testLeftShift(IMMUTABLE_MILLION, 0, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 1, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 12, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 13, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 32, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 33, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 44, true);
|
||||
testLeftShift(IMMUTABLE_MILLION, 45, true);
|
||||
|
||||
testLeftShift(genMillion1(), 0, false);
|
||||
testLeftShift(genMillion1(), 1, false);
|
||||
testLeftShift(genMillion1(), 12, false);
|
||||
testLeftShift(genMillion1(), 13, false);
|
||||
testLeftShift(genMillion1(), 25, false);
|
||||
testLeftShift(genMillion1(), 26, false);
|
||||
testLeftShift(genMillion1(), 32, false);
|
||||
testLeftShift(genMillion1(), 33, false);
|
||||
testLeftShift(genMillion1(), 44, false);
|
||||
testLeftShift(genMillion1(), 45, false);
|
||||
|
||||
testLeftShift(genMillion2(), 0, false);
|
||||
testLeftShift(genMillion2(), 1, false);
|
||||
testLeftShift(genMillion2(), 12, false);
|
||||
testLeftShift(genMillion2(), 13, false);
|
||||
testLeftShift(genMillion2(), 25, false);
|
||||
testLeftShift(genMillion2(), 26, false);
|
||||
testLeftShift(genMillion2(), 32, false);
|
||||
testLeftShift(genMillion2(), 33, false);
|
||||
testLeftShift(genMillion2(), 44, false);
|
||||
testLeftShift(genMillion2(), 45, false);
|
||||
}
|
||||
|
||||
private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception {
|
||||
BigInteger bt = t.toBigInteger();
|
||||
BigInteger bs = s.toBigInteger();
|
||||
int q = t.quoRemIteration(s);
|
||||
BigInteger[] qr = bt.divideAndRemainder(bs);
|
||||
if (!BigInteger.valueOf(q).equals(qr[0])) {
|
||||
throw new Exception("quoRemIteration returns incorrect quo");
|
||||
}
|
||||
check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem");
|
||||
}
|
||||
|
||||
private static void testQuoRemIteration() throws Exception {
|
||||
// IMMUTABLE_TEN18 == 0de0b6b3a7640000
|
||||
// q = 0
|
||||
testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18);
|
||||
// q = 1 -> q = 0
|
||||
testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18);
|
||||
// q = 1
|
||||
testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18);
|
||||
testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18);
|
||||
// q = 18
|
||||
testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18);
|
||||
}
|
||||
|
||||
private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception {
|
||||
BigInteger bt = t.toBigInteger();
|
||||
BigInteger bo = o.toBigInteger();
|
||||
int cmp = t.cmp(o);
|
||||
int bcmp = bt.compareTo(bo);
|
||||
if (bcmp != cmp) {
|
||||
throw new Exception("cmp returns " + cmp + " expected " + bcmp);
|
||||
}
|
||||
check(bt, t, "cmp corrupts this");
|
||||
check(bo, o, "cmp corrupts other");
|
||||
if (o.cmp(t) != -cmp) {
|
||||
throw new Exception("asymmetrical cmp");
|
||||
}
|
||||
check(bt, t, "cmp corrupts this");
|
||||
check(bo, o, "cmp corrupts other");
|
||||
}
|
||||
|
||||
private static void testCmp() throws Exception {
|
||||
testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0));
|
||||
testCmp(mutable("FFFFFFFF", 0), mutable("1", 1));
|
||||
testCmp(mutable("5", 0), mutable("6", 0));
|
||||
testCmp(mutable("5", 0), mutable("5", 0));
|
||||
testCmp(mutable("5000000001", 0), mutable("500000001", 0));
|
||||
testCmp(mutable("5000000001", 0), mutable("6", 1));
|
||||
testCmp(mutable("5000000001", 0), mutable("5", 1));
|
||||
testCmp(mutable("5000000000", 0), mutable("5", 1));
|
||||
}
|
||||
|
||||
private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception {
|
||||
FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2);
|
||||
BigInteger bt = t.toBigInteger();
|
||||
BigInteger bo = biPow52(p5, p2);
|
||||
int cmp = t.cmp(o);
|
||||
int bcmp = bt.compareTo(bo);
|
||||
if (bcmp != cmp) {
|
||||
throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp);
|
||||
}
|
||||
check(bt, t, "cmpPow52 corrupts this");
|
||||
check(bo, o, "cmpPow5 corrupts other");
|
||||
}
|
||||
|
||||
private static void testCmpPow52() throws Exception {
|
||||
testCmpPow52(mutable("00000002", 1), 0, 31);
|
||||
testCmpPow52(mutable("00000002", 1), 0, 32);
|
||||
testCmpPow52(mutable("00000002", 1), 0, 33);
|
||||
testCmpPow52(mutable("00000002", 1), 0, 34);
|
||||
testCmpPow52(mutable("00000002", 1), 0, 64);
|
||||
testCmpPow52(mutable("00000003", 1), 0, 32);
|
||||
testCmpPow52(mutable("00000003", 1), 0, 33);
|
||||
testCmpPow52(mutable("00000003", 1), 0, 34);
|
||||
}
|
||||
|
||||
private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception {
|
||||
BigInteger bt = t.toBigInteger();
|
||||
BigInteger bx = x.toBigInteger();
|
||||
BigInteger by = y.toBigInteger();
|
||||
int cmp = t.addAndCmp(x, y);
|
||||
int bcmp = bt.compareTo(bx.add(by));
|
||||
if (bcmp != cmp) {
|
||||
throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp);
|
||||
}
|
||||
check(bt, t, "addAndCmp corrupts this");
|
||||
check(bx, x, "addAndCmp corrupts x");
|
||||
check(by, y, "addAndCmp corrupts y");
|
||||
}
|
||||
|
||||
private static void testAddAndCmp() throws Exception {
|
||||
testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO);
|
||||
testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO);
|
||||
testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO);
|
||||
testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0));
|
||||
testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO);
|
||||
testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0));
|
||||
testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0));
|
||||
testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0));
|
||||
|
||||
testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1));
|
||||
testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1));
|
||||
|
||||
testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
|
||||
testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
|
||||
testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
|
||||
testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
|
||||
|
||||
testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
|
||||
testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0));
|
||||
testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
|
||||
testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
|
||||
}
|
||||
|
||||
private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception {
|
||||
BigInteger bt = t.toBigInteger();
|
||||
FDBigInteger r = t.multBy10();
|
||||
if ((bt.signum() == 0 || !isImmutable) && r != t) {
|
||||
throw new Exception("multBy10 of doesn't reuse its argument");
|
||||
}
|
||||
if (isImmutable) {
|
||||
check(bt, t, "multBy10 corrupts its argument");
|
||||
}
|
||||
check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result");
|
||||
}
|
||||
|
||||
private static void testMultBy10() throws Exception {
|
||||
for (int p5 = 0; p5 <= MAX_P5; p5++) {
|
||||
for (int p2 = 0; p2 <= MAX_P2; p2++) {
|
||||
// This strange way of creating a value ensures that it is mutable.
|
||||
FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
|
||||
testMultBy10(value, false);
|
||||
value.makeImmutable();
|
||||
testMultBy10(value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception {
|
||||
BigInteger bt = t.toBigInteger();
|
||||
FDBigInteger r = t.multByPow52(p5, p2);
|
||||
if (bt.signum() == 0 && r != t) {
|
||||
throw new Exception("multByPow52 of doesn't reuse its argument");
|
||||
}
|
||||
check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result");
|
||||
}
|
||||
|
||||
private static void testMultByPow52() throws Exception {
|
||||
for (int p5 = 0; p5 <= MAX_P5; p5++) {
|
||||
for (int p2 = 0; p2 <= MAX_P2; p2++) {
|
||||
// This strange way of creating a value ensures that it is mutable.
|
||||
FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
|
||||
testMultByPow52(value, p5, p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
|
||||
BigInteger biLeft = left.toBigInteger();
|
||||
BigInteger biRight = right.toBigInteger();
|
||||
FDBigInteger diff = left.leftInplaceSub(right);
|
||||
if (!isImmutable && diff != left) {
|
||||
throw new Exception("leftInplaceSub of doesn't reuse its argument");
|
||||
}
|
||||
check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result");
|
||||
}
|
||||
|
||||
private static void testLeftInplaceSub() throws Exception {
|
||||
for (int p5 = 0; p5 <= MAX_P5; p5++) {
|
||||
for (int p2 = 0; p2 <= MAX_P2; p2++) {
|
||||
// for (int p5r = 0; p5r <= p5; p5r += 10) {
|
||||
// for (int p2r = 0; p2r <= p2; p2r += 10) {
|
||||
for (int p5r = 0; p5r <= p5; p5r++) {
|
||||
for (int p2r = 0; p2r <= p2; p2r++) {
|
||||
// This strange way of creating a value ensures that it is mutable.
|
||||
FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
|
||||
FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
|
||||
testLeftInplaceSub(left, right, false);
|
||||
left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
|
||||
left.makeImmutable();
|
||||
testLeftInplaceSub(left, right, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
|
||||
BigInteger biLeft = left.toBigInteger();
|
||||
BigInteger biRight = right.toBigInteger();
|
||||
FDBigInteger diff = left.rightInplaceSub(right);
|
||||
if (!isImmutable && diff != right) {
|
||||
throw new Exception("rightInplaceSub of doesn't reuse its argument");
|
||||
}
|
||||
try {
|
||||
check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result");
|
||||
} catch (Exception e) {
|
||||
System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static void testRightInplaceSub() throws Exception {
|
||||
for (int p5 = 0; p5 <= MAX_P5; p5++) {
|
||||
for (int p2 = 0; p2 <= MAX_P2; p2++) {
|
||||
// for (int p5r = 0; p5r <= p5; p5r += 10) {
|
||||
// for (int p2r = 0; p2r <= p2; p2r += 10) {
|
||||
for (int p5r = 0; p5r <= p5; p5r++) {
|
||||
for (int p2r = 0; p2r <= p2; p2r++) {
|
||||
// This strange way of creating a value ensures that it is mutable.
|
||||
FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
|
||||
FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
|
||||
testRightInplaceSub(left, right, false);
|
||||
right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
|
||||
right.makeImmutable();
|
||||
testRightInplaceSub(left, right, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testValueOfPow52();
|
||||
testValueOfMulPow52();
|
||||
testLeftShift();
|
||||
testQuoRemIteration();
|
||||
testCmp();
|
||||
testCmpPow52();
|
||||
testAddAndCmp();
|
||||
// Uncomment the following for more comprehensize but slow testing.
|
||||
// testLeftInplaceSub();
|
||||
// testMultBy10();
|
||||
// testMultByPow52();
|
||||
// testRightInplaceSub();
|
||||
}
|
||||
}
|
324
jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java
Normal file
324
jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
import java.util.Random;
|
||||
import sun.misc.FloatingDecimal;
|
||||
|
||||
/*
|
||||
OldFloatingDecimalForTest
|
||||
|
||||
public class OldFloatingDecimalForTest {
|
||||
public boolean digitsRoundedUp();
|
||||
public OldFloatingDecimalForTest(double);
|
||||
public OldFloatingDecimalForTest(float);
|
||||
public boolean decimalDigitsExact();
|
||||
public java.lang.String toString();
|
||||
public java.lang.String toJavaFormatString();
|
||||
public void appendTo(java.lang.Appendable);
|
||||
public static OldFloatingDecimalForTest readJavaFormatString(java.lang.String) throws java.lang.NumberFormatException;
|
||||
public strictfp double doubleValue();
|
||||
public strictfp float floatValue();
|
||||
}
|
||||
|
||||
sun.misc.FloatingDecimal
|
||||
|
||||
public class sun.misc.FloatingDecimal {
|
||||
public sun.misc.FloatingDecimal();
|
||||
public static java.lang.String toJavaFormatString(double);
|
||||
public static java.lang.String toJavaFormatString(float);
|
||||
public static void appendTo(double, java.lang.Appendable);
|
||||
public static void appendTo(float, java.lang.Appendable);
|
||||
public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
|
||||
public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
|
||||
public static sun.misc.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 7032154
|
||||
* @summary unit tests of sun.misc.FloatingDecimal
|
||||
* @author Brian Burkhalter
|
||||
*/
|
||||
public class TestFloatingDecimal {
|
||||
private static enum ResultType {
|
||||
RESULT_EXCEPTION,
|
||||
RESULT_PRINT
|
||||
}
|
||||
|
||||
private static final ResultType RESULT_TYPE = ResultType.RESULT_PRINT;
|
||||
private static final int NUM_RANDOM_TESTS = 100000;
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
private static void result(String message) {
|
||||
switch (RESULT_TYPE) {
|
||||
case RESULT_EXCEPTION:
|
||||
throw new RuntimeException(message);
|
||||
case RESULT_PRINT:
|
||||
System.err.println(message);
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
private static int check(String test, Object expected, Object actual) {
|
||||
int failures = 0;
|
||||
if(!actual.equals(expected)) {
|
||||
failures++;
|
||||
result("Test "+test+" expected "+expected+" but obtained "+actual);
|
||||
}
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testAppendToDouble() {
|
||||
System.out.println(" testAppendToDouble");
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
double[] d = new double[] {
|
||||
RANDOM.nextLong(),
|
||||
RANDOM.nextGaussian(),
|
||||
RANDOM.nextDouble()*Double.MAX_VALUE
|
||||
};
|
||||
for(int j = 0; j < d.length; j++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ofd.appendTo(sb);
|
||||
String oldString = sb.toString();
|
||||
sb = new StringBuilder();
|
||||
FloatingDecimal.appendTo(d[j], sb);
|
||||
String newString = sb.toString();
|
||||
failures += check("testAppendToDouble", oldString, newString);
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testAppendToFloat() {
|
||||
System.out.println(" testAppendToFloat");
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
float[] f = new float[] {
|
||||
RANDOM.nextLong(),
|
||||
(float)RANDOM.nextGaussian(),
|
||||
RANDOM.nextFloat()*Float.MAX_VALUE
|
||||
};
|
||||
for(int j = 0; j < f.length; j++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ofd.appendTo(sb);
|
||||
String oldString = sb.toString();
|
||||
sb = new StringBuilder();
|
||||
FloatingDecimal.appendTo(f[j], sb);
|
||||
String newString = sb.toString();
|
||||
failures += check("testAppendToFloat", oldString, newString);
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testAppendTo() {
|
||||
System.out.println("testAppendTo");
|
||||
int failures = 0;
|
||||
|
||||
failures += testAppendToDouble();
|
||||
failures += testAppendToFloat();
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testParseDouble() {
|
||||
System.out.println(" testParseDouble");
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
double[] d = new double[] {
|
||||
RANDOM.nextLong(),
|
||||
RANDOM.nextGaussian(),
|
||||
RANDOM.nextDouble()*Double.MAX_VALUE
|
||||
};
|
||||
for(int j = 0; j < d.length; j++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
|
||||
String javaFormatString = ofd.toJavaFormatString();
|
||||
ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
|
||||
double oldDouble = ofd.doubleValue();
|
||||
double newDouble = FloatingDecimal.parseDouble(javaFormatString);
|
||||
failures += check("testParseDouble", oldDouble, newDouble);
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testParseFloat() {
|
||||
System.out.println(" testParseFloat");
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
float[] f = new float[] {
|
||||
RANDOM.nextInt(),
|
||||
(float)RANDOM.nextGaussian(),
|
||||
RANDOM.nextFloat()*Float.MAX_VALUE
|
||||
};
|
||||
for(int j = 0; j < f.length; j++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
|
||||
String javaFormatString = ofd.toJavaFormatString();
|
||||
ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
|
||||
float oldFloat = ofd.floatValue();
|
||||
float newFloat = FloatingDecimal.parseFloat(javaFormatString);
|
||||
failures += check("testParseFloat", oldFloat, newFloat);
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testParse() {
|
||||
System.out.println("testParse");
|
||||
int failures = 0;
|
||||
|
||||
failures += testParseDouble();
|
||||
failures += testParseFloat();
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatStringDoubleFixed() {
|
||||
System.out.println(" testToJavaFormatStringDoubleFixed");
|
||||
int failures = 0;
|
||||
|
||||
double[] d = new double [] {
|
||||
-5.9522650387500933e18, // dtoa() fast path
|
||||
0.872989018674569, // dtoa() fast iterative - long
|
||||
1.1317400099603851e308 // dtoa() slow iterative
|
||||
};
|
||||
|
||||
for(int i = 0; i < d.length; i++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[i]);
|
||||
failures += check("testToJavaFormatStringDoubleFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[i]));
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatStringDoubleRandom() {
|
||||
System.out.println(" testToJavaFormatStringDoubleRandom");
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
double[] d = new double[] {
|
||||
RANDOM.nextLong(),
|
||||
RANDOM.nextGaussian(),
|
||||
RANDOM.nextDouble()*Double.MAX_VALUE
|
||||
};
|
||||
for(int j = 0; j < d.length; j++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
|
||||
failures += check("testToJavaFormatStringDoubleRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[j]));
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatStringDouble() {
|
||||
System.out.println(" testToJavaFormatStringDouble");
|
||||
int failures = 0;
|
||||
failures += testToJavaFormatStringDoubleFixed();
|
||||
failures += testToJavaFormatStringDoubleRandom();
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatStringFloatFixed() {
|
||||
System.out.println(" testToJavaFormatStringFloatFixed");
|
||||
int failures = 0;
|
||||
|
||||
float[] f = new float[] {
|
||||
-9.8784166e8f, // dtoa() fast path
|
||||
0.70443946f, // dtoa() fast iterative - int
|
||||
1.8254228e37f // dtoa() slow iterative
|
||||
};
|
||||
|
||||
for(int i = 0; i < f.length; i++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[i]);
|
||||
failures += check("testToJavaFormatStringFloatFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[i]));
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatStringFloatRandom() {
|
||||
System.out.println(" testToJavaFormatStringFloatRandom");
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
float[] f = new float[] {
|
||||
RANDOM.nextInt(),
|
||||
(float)RANDOM.nextGaussian(),
|
||||
RANDOM.nextFloat()*Float.MAX_VALUE
|
||||
};
|
||||
for(int j = 0; j < f.length; j++) {
|
||||
OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
|
||||
failures += check("testToJavaFormatStringFloatRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[j]));
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatStringFloat() {
|
||||
System.out.println(" testToJavaFormatStringFloat");
|
||||
int failures = 0;
|
||||
|
||||
failures += testToJavaFormatStringFloatFixed();
|
||||
failures += testToJavaFormatStringFloatRandom();
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testToJavaFormatString() {
|
||||
System.out.println("testToJavaFormatString");
|
||||
int failures = 0;
|
||||
|
||||
failures += testToJavaFormatStringDouble();
|
||||
failures += testToJavaFormatStringFloat();
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int failures = 0;
|
||||
|
||||
failures += testAppendTo();
|
||||
failures += testParse();
|
||||
failures += testToJavaFormatString();
|
||||
|
||||
if (failures != 0) {
|
||||
throw new RuntimeException("" + failures + " failures while testing FloatingDecimal");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user