8343453: Modernize FloatingDecimal tests
Reviewed-by: darcy
This commit is contained in:
parent
847f65c14a
commit
bf374c33f5
@ -1,491 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 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.
|
||||
*/
|
||||
|
||||
//package jdk.internal.math;
|
||||
|
||||
/*
|
||||
* A really, really simple bigint package
|
||||
* tailored to the needs of floating base conversion.
|
||||
*/
|
||||
class OldFDBigIntForTest {
|
||||
int nWords; // number of words used
|
||||
int data[]; // value: data[0] is least significant
|
||||
|
||||
|
||||
public OldFDBigIntForTest( int v ){
|
||||
nWords = 1;
|
||||
data = new int[1];
|
||||
data[0] = 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 OldFDBigIntForTest( OldFDBigIntForTest other ){
|
||||
data = new int[nWords = other.nWords];
|
||||
System.arraycopy( other.data, 0, data, 0, nWords );
|
||||
}
|
||||
|
||||
private OldFDBigIntForTest( int [] d, int n ){
|
||||
data = d;
|
||||
nWords = n;
|
||||
}
|
||||
|
||||
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
|
||||
data[0] = (int)seed; // starting value
|
||||
data[1] = (int)(seed>>>32);
|
||||
nWords = (data[1]==0) ? 1 : 2;
|
||||
int i = nd0;
|
||||
int limit = nd-5; // slurp digits 5 at a time.
|
||||
int v;
|
||||
while ( i < limit ){
|
||||
int ilim = i+5;
|
||||
v = (int)digit[i++]-(int)'0';
|
||||
while( i <ilim ){
|
||||
v = 10*v + (int)digit[i++]-(int)'0';
|
||||
}
|
||||
multaddMe( 100000, v); // ... where 100000 is 10^5.
|
||||
}
|
||||
int factor = 1;
|
||||
v = 0;
|
||||
while ( i < nd ){
|
||||
v = 10*v + (int)digit[i++]-(int)'0';
|
||||
factor *= 10;
|
||||
}
|
||||
if ( factor != 1 ){
|
||||
multaddMe( factor, v );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Left shift by c bits.
|
||||
* Shifts this in place.
|
||||
*/
|
||||
public void
|
||||
lshiftMe( int c )throws IllegalArgumentException {
|
||||
if ( c <= 0 ){
|
||||
if ( c == 0 )
|
||||
return; // silly.
|
||||
else
|
||||
throw new IllegalArgumentException("negative shift count");
|
||||
}
|
||||
int wordcount = c>>5;
|
||||
int bitcount = c & 0x1f;
|
||||
int anticount = 32-bitcount;
|
||||
int t[] = data;
|
||||
int s[] = data;
|
||||
if ( nWords+wordcount+1 > t.length ){
|
||||
// reallocate.
|
||||
t = new int[ nWords+wordcount+1 ];
|
||||
}
|
||||
int target = nWords+wordcount;
|
||||
int src = nWords-1;
|
||||
if ( bitcount == 0 ){
|
||||
// special hack, since an anticount of 32 won't go!
|
||||
System.arraycopy( s, 0, t, wordcount, nWords );
|
||||
target = wordcount-1;
|
||||
} else {
|
||||
t[target--] = s[src]>>>anticount;
|
||||
while ( src >= 1 ){
|
||||
t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
|
||||
}
|
||||
t[target--] = s[src]<<bitcount;
|
||||
}
|
||||
while( target >= 0 ){
|
||||
t[target--] = 0;
|
||||
}
|
||||
data = t;
|
||||
nWords += wordcount + 1;
|
||||
// may have constructed high-order word of 0.
|
||||
// if so, trim it
|
||||
while ( nWords > 1 && data[nWords-1] == 0 )
|
||||
nWords--;
|
||||
}
|
||||
|
||||
/*
|
||||
* normalize this number by shifting until
|
||||
* the MSB of the number is at 0x08000000.
|
||||
* This is in preparation for quoRemIteration, below.
|
||||
* The idea is that, to make division easier, we want the
|
||||
* divisor to be "normalized" -- usually this means shifting
|
||||
* the MSB into the high words sign bit. But because we know that
|
||||
* the quotient will be 0 < q < 10, we would like to arrange that
|
||||
* the dividend not span up into another word of precision.
|
||||
* (This needs to be explained more clearly!)
|
||||
*/
|
||||
public int
|
||||
normalizeMe() throws IllegalArgumentException {
|
||||
int src;
|
||||
int wordcount = 0;
|
||||
int bitcount = 0;
|
||||
int v = 0;
|
||||
for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
|
||||
wordcount += 1;
|
||||
}
|
||||
if ( src < 0 ){
|
||||
// oops. Value is zero. Cannot normalize it!
|
||||
throw new IllegalArgumentException("zero value");
|
||||
}
|
||||
/*
|
||||
* In most cases, we assume that wordcount is zero. This only
|
||||
* makes sense, as we try not to maintain any high-order
|
||||
* words full of zeros. In fact, if there are zeros, we will
|
||||
* simply SHORTEN our number at this point. Watch closely...
|
||||
*/
|
||||
nWords -= wordcount;
|
||||
/*
|
||||
* Compute how far left we have to shift v s.t. its highest-
|
||||
* order bit is in the right place. Then call lshiftMe to
|
||||
* do the work.
|
||||
*/
|
||||
if ( (v & 0xf0000000) != 0 ){
|
||||
// will have to shift up into the next word.
|
||||
// too bad.
|
||||
for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
|
||||
v >>>= 1;
|
||||
} else {
|
||||
while ( v <= 0x000fffff ){
|
||||
// hack: byte-at-a-time shifting
|
||||
v <<= 8;
|
||||
bitcount += 8;
|
||||
}
|
||||
while ( v <= 0x07ffffff ){
|
||||
v <<= 1;
|
||||
bitcount += 1;
|
||||
}
|
||||
}
|
||||
if ( bitcount != 0 )
|
||||
lshiftMe( bitcount );
|
||||
return bitcount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply a OldFDBigIntForTest by an int.
|
||||
* Result is a new OldFDBigIntForTest.
|
||||
*/
|
||||
public OldFDBigIntForTest
|
||||
mult( int iv ) {
|
||||
long v = iv;
|
||||
int r[];
|
||||
long p;
|
||||
|
||||
// guess adequate size of r.
|
||||
r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
|
||||
p = 0L;
|
||||
for( int i=0; i < nWords; i++ ) {
|
||||
p += v * ((long)data[i]&0xffffffffL);
|
||||
r[i] = (int)p;
|
||||
p >>>= 32;
|
||||
}
|
||||
if ( p == 0L){
|
||||
return new OldFDBigIntForTest( r, nWords );
|
||||
} else {
|
||||
r[nWords] = (int)p;
|
||||
return new OldFDBigIntForTest( r, nWords+1 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply a OldFDBigIntForTest by an int and add another int.
|
||||
* Result is computed in place.
|
||||
* Hope it fits!
|
||||
*/
|
||||
public void
|
||||
multaddMe( int iv, int addend ) {
|
||||
long v = iv;
|
||||
long p;
|
||||
|
||||
// unroll 0th iteration, doing addition.
|
||||
p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
|
||||
data[0] = (int)p;
|
||||
p >>>= 32;
|
||||
for( int i=1; i < nWords; i++ ) {
|
||||
p += v * ((long)data[i]&0xffffffffL);
|
||||
data[i] = (int)p;
|
||||
p >>>= 32;
|
||||
}
|
||||
if ( p != 0L){
|
||||
data[nWords] = (int)p; // will fail noisily if illegal!
|
||||
nWords++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
|
||||
* Result is a new OldFDBigIntForTest.
|
||||
*/
|
||||
public OldFDBigIntForTest
|
||||
mult( OldFDBigIntForTest other ){
|
||||
// crudely guess adequate size for r
|
||||
int r[] = new int[ nWords + other.nWords ];
|
||||
int i;
|
||||
// I think I am promised zeros...
|
||||
|
||||
for( i = 0; i < this.nWords; i++ ){
|
||||
long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
|
||||
long p = 0L;
|
||||
int j;
|
||||
for( j = 0; j < other.nWords; j++ ){
|
||||
p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
|
||||
r[i+j] = (int)p;
|
||||
p >>>= 32;
|
||||
}
|
||||
r[i+j] = (int)p;
|
||||
}
|
||||
// compute how much of r we actually needed for all that.
|
||||
for ( i = r.length-1; i> 0; i--)
|
||||
if ( r[i] != 0 )
|
||||
break;
|
||||
return new OldFDBigIntForTest( r, i+1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
|
||||
*/
|
||||
public OldFDBigIntForTest
|
||||
add( OldFDBigIntForTest other ){
|
||||
int i;
|
||||
int a[], b[];
|
||||
int n, m;
|
||||
long c = 0L;
|
||||
// arrange such that a.nWords >= b.nWords;
|
||||
// n = a.nWords, m = b.nWords
|
||||
if ( this.nWords >= other.nWords ){
|
||||
a = this.data;
|
||||
n = this.nWords;
|
||||
b = other.data;
|
||||
m = other.nWords;
|
||||
} else {
|
||||
a = other.data;
|
||||
n = other.nWords;
|
||||
b = this.data;
|
||||
m = this.nWords;
|
||||
}
|
||||
int r[] = new int[ n ];
|
||||
for ( i = 0; i < n; i++ ){
|
||||
c += (long)a[i] & 0xffffffffL;
|
||||
if ( i < m ){
|
||||
c += (long)b[i] & 0xffffffffL;
|
||||
}
|
||||
r[i] = (int) c;
|
||||
c >>= 32; // signed shift.
|
||||
}
|
||||
if ( c != 0L ){
|
||||
// oops -- carry out -- need longer result.
|
||||
int s[] = new int[ r.length+1 ];
|
||||
System.arraycopy( r, 0, s, 0, r.length );
|
||||
s[i++] = (int)c;
|
||||
return new OldFDBigIntForTest( s, i );
|
||||
}
|
||||
return new OldFDBigIntForTest( r, i );
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
|
||||
* Assert that the result is positive.
|
||||
*/
|
||||
public OldFDBigIntForTest
|
||||
sub( OldFDBigIntForTest other ){
|
||||
int r[] = new int[ this.nWords ];
|
||||
int i;
|
||||
int n = this.nWords;
|
||||
int m = other.nWords;
|
||||
int nzeros = 0;
|
||||
long c = 0L;
|
||||
for ( i = 0; i < n; i++ ){
|
||||
c += (long)this.data[i] & 0xffffffffL;
|
||||
if ( i < m ){
|
||||
c -= (long)other.data[i] & 0xffffffffL;
|
||||
}
|
||||
if ( ( r[i] = (int) c ) == 0 )
|
||||
nzeros++;
|
||||
else
|
||||
nzeros = 0;
|
||||
c >>= 32; // signed shift
|
||||
}
|
||||
assert c == 0L : c; // borrow out of subtract
|
||||
assert dataInRangeIsZero(i, m, other); // negative result of subtract
|
||||
return new OldFDBigIntForTest( r, n-nzeros );
|
||||
}
|
||||
|
||||
private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
|
||||
while ( i < m )
|
||||
if (other.data[i++] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
|
||||
* >0: this > other
|
||||
* 0: this == other
|
||||
* <0: this < other
|
||||
*/
|
||||
public int
|
||||
cmp( OldFDBigIntForTest other ){
|
||||
int i;
|
||||
if ( this.nWords > other.nWords ){
|
||||
// if any of my high-order words is non-zero,
|
||||
// then the answer is evident
|
||||
int j = other.nWords-1;
|
||||
for ( i = this.nWords-1; i > j ; i-- )
|
||||
if ( this.data[i] != 0 ) return 1;
|
||||
}else if ( this.nWords < other.nWords ){
|
||||
// if any of other's high-order words is non-zero,
|
||||
// then the answer is evident
|
||||
int j = this.nWords-1;
|
||||
for ( i = other.nWords-1; i > j ; i-- )
|
||||
if ( other.data[i] != 0 ) return -1;
|
||||
} else{
|
||||
i = this.nWords-1;
|
||||
}
|
||||
for ( ; i > 0 ; i-- )
|
||||
if ( this.data[i] != other.data[i] )
|
||||
break;
|
||||
// careful! want unsigned compare!
|
||||
// use brute force here.
|
||||
int a = this.data[i];
|
||||
int b = other.data[i];
|
||||
if ( a < 0 ){
|
||||
// a is really big, unsigned
|
||||
if ( b < 0 ){
|
||||
return a-b; // both big, negative
|
||||
} else {
|
||||
return 1; // b not big, answer is obvious;
|
||||
}
|
||||
} else {
|
||||
// a is not really big
|
||||
if ( b < 0 ) {
|
||||
// but b is really big
|
||||
return -1;
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute
|
||||
* q = (int)( this / S )
|
||||
* this = 10 * ( this mod S )
|
||||
* Return q.
|
||||
* This is the iteration step of digit development for output.
|
||||
* We assume that S has been normalized, as above, and that
|
||||
* "this" has been lshift'ed accordingly.
|
||||
* Also assume, of course, that the result, q, can be expressed
|
||||
* as an integer, 0 <= q < 10.
|
||||
*/
|
||||
public int
|
||||
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.
|
||||
if ( nWords != S.nWords ){
|
||||
throw new IllegalArgumentException("disparate values");
|
||||
}
|
||||
// estimate q the obvious way. We will usually be
|
||||
// right. If not, then we're only off by a little and
|
||||
// will re-add.
|
||||
int n = nWords-1;
|
||||
long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
|
||||
long diff = 0L;
|
||||
for ( int i = 0; i <= n ; i++ ){
|
||||
diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);
|
||||
data[i] = (int)diff;
|
||||
diff >>= 32; // N.B. SIGNED shift.
|
||||
}
|
||||
if ( diff != 0L ) {
|
||||
// damn, damn, damn. q is too big.
|
||||
// add S back in until this turns +. This should
|
||||
// not be very many times!
|
||||
long sum = 0L;
|
||||
while ( sum == 0L ){
|
||||
sum = 0L;
|
||||
for ( int i = 0; i <= n; i++ ){
|
||||
sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);
|
||||
data[i] = (int) sum;
|
||||
sum >>= 32; // Signed or unsigned, answer is 0 or 1
|
||||
}
|
||||
/*
|
||||
* Originally the following line read
|
||||
* "if ( sum !=0 && sum != -1 )"
|
||||
* but that would be wrong, because of the
|
||||
* treatment of the two values as entirely unsigned,
|
||||
* it would be impossible for a carry-out to be interpreted
|
||||
* as -1 -- it would have to be a single-bit carry-out, or
|
||||
* +1.
|
||||
*/
|
||||
assert sum == 0 || sum == 1 : sum; // carry out of division correction
|
||||
q -= 1;
|
||||
}
|
||||
}
|
||||
// finally, we can multiply this by 10.
|
||||
// it cannot overflow, right, as the high-order word has
|
||||
// at least 4 high-order zeros!
|
||||
long p = 0L;
|
||||
for ( int i = 0; i <= n; i++ ){
|
||||
p += 10*((long)data[i]&0xffffffffL);
|
||||
data[i] = (int)p;
|
||||
p >>= 32; // SIGNED shift.
|
||||
}
|
||||
assert p == 0L : p; // Carry out of *10
|
||||
return (int)q;
|
||||
}
|
||||
|
||||
public long
|
||||
longValue(){
|
||||
// if this can be represented as a long, return the value
|
||||
assert this.nWords > 0 : this.nWords; // longValue confused
|
||||
|
||||
if (this.nWords == 1)
|
||||
return ((long)data[0]&0xffffffffL);
|
||||
|
||||
assert dataInRangeIsZero(2, this.nWords, this); // value too big
|
||||
assert data[1] >= 0; // value too big
|
||||
return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
|
||||
}
|
||||
|
||||
public String
|
||||
toString() {
|
||||
StringBuffer r = new StringBuffer(30);
|
||||
r.append('[');
|
||||
int i = Math.min( nWords-1, data.length-1) ;
|
||||
if ( nWords > data.length ){
|
||||
r.append( "("+data.length+"<"+nWords+"!)" );
|
||||
}
|
||||
for( ; i> 0 ; i-- ){
|
||||
r.append( Integer.toHexString( data[i] ) );
|
||||
r.append(' ');
|
||||
}
|
||||
r.append( Integer.toHexString( data[0] ) );
|
||||
r.append(']');
|
||||
return new String( r );
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2024, 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
|
||||
@ -21,6 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Random;
|
||||
import jdk.internal.math.FloatingDecimal;
|
||||
|
||||
@ -30,46 +31,13 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/*
|
||||
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();
|
||||
}
|
||||
|
||||
jdk.internal.math.FloatingDecimal
|
||||
|
||||
public class jdk.internal.math.FloatingDecimal {
|
||||
public jdk.internal.math.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 jdk.internal.math.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 7032154
|
||||
* @summary unit tests of FloatingDecimal (use -Dseed=X to set PRANDOM seed)
|
||||
* @bug 7032154 8343453
|
||||
* @summary FloatingDecimal parsing methods (use -Dseed=X to set PRANDOM seed)
|
||||
* @modules java.base/jdk.internal.math
|
||||
* @library ..
|
||||
* @library /test/lib
|
||||
* @library /java/lang/Math
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @build DoubleConsts FloatConsts
|
||||
* @run junit TestFloatingDecimal
|
||||
* @author Brian Burkhalter
|
||||
* @key randomness
|
||||
@ -79,184 +47,53 @@ public class TestFloatingDecimal {
|
||||
|
||||
private static final Random RANDOM = RandomFactory.getRandom();
|
||||
|
||||
private static int check(String test, Object expected, Object actual) {
|
||||
int failures = 0;
|
||||
if(!actual.equals(expected)) {
|
||||
failures++;
|
||||
System.err.println("Test " + test +
|
||||
" expected " + expected +
|
||||
" but obtained " + actual);
|
||||
}
|
||||
return failures;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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);
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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);
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
/*
|
||||
* The tests rely on the different conversion implementations
|
||||
* in FloatDecimal and BigDecimal.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testParseDouble() {
|
||||
int failures = 0;
|
||||
|
||||
for (int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
double[] d = new double[] {
|
||||
double[] d = {
|
||||
RANDOM.nextLong(),
|
||||
RANDOM.nextGaussian(),
|
||||
RANDOM.nextDouble()*Double.MAX_VALUE
|
||||
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);
|
||||
}
|
||||
}
|
||||
for (double v : d) {
|
||||
String dec = Double.toString(v);
|
||||
assertEquals(new BigDecimal(dec).doubleValue(), FloatingDecimal.parseDouble(dec));
|
||||
|
||||
assertEquals(0, failures);
|
||||
BigDecimal bd = new BigDecimal(v);
|
||||
String full = bd.toString();
|
||||
assertEquals(bd.doubleValue(), FloatingDecimal.parseDouble(full));
|
||||
|
||||
String hex = Double.toHexString(v);
|
||||
assertEquals(FloatingDecimal.parseDouble(dec), FloatingDecimal.parseDouble(hex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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);
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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]));
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJavaFormatStringDoubleRandom() {
|
||||
int failures = 0;
|
||||
|
||||
for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
|
||||
double[] d = new double[] {
|
||||
float[] f = {
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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]));
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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]));
|
||||
for (float v : f) {
|
||||
String dec = Float.toString(v);
|
||||
assertEquals(new BigDecimal(dec).floatValue(), FloatingDecimal.parseFloat(dec));
|
||||
|
||||
BigDecimal bd = new BigDecimal(v);
|
||||
String full = bd.toString();
|
||||
assertEquals(bd.floatValue(), FloatingDecimal.parseFloat(full));
|
||||
|
||||
String hex = Float.toHexString(v);
|
||||
assertEquals(FloatingDecimal.parseFloat(dec), FloatingDecimal.parseFloat(hex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(0, failures);
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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
|
||||
* @modules java.base/jdk.internal.math
|
||||
*/
|
||||
|
||||
import jdk.internal.math.FloatingDecimal;
|
||||
|
||||
public class ToString {
|
||||
private static int fail = 0;
|
||||
|
||||
private static Throwable first;
|
||||
|
||||
public static void main(String argv[]) {
|
||||
test("10.0");
|
||||
test("1.0");
|
||||
test("0.1");
|
||||
test("0.01");
|
||||
test("0.001");
|
||||
test("1.0E-4");
|
||||
if (fail != 0)
|
||||
throw new RuntimeException(fail + " failure(s), first", first);
|
||||
}
|
||||
|
||||
private static void test(String exp) {
|
||||
float c = Float.parseFloat(exp);
|
||||
String got = FloatingDecimal.toJavaFormatString(c);
|
||||
if (!got.equals(exp))
|
||||
fail("float '" + "': Expected '" + exp + "', got '" + got + "'");
|
||||
|
||||
double d = Double.parseDouble(exp);
|
||||
got = FloatingDecimal.toJavaFormatString(d);
|
||||
if (!got.equals(exp))
|
||||
fail("double '" + "': Expected '" + exp + "', got '" + got + "'");
|
||||
}
|
||||
|
||||
private static void fail(String s) {
|
||||
if (first == null)
|
||||
setFirst(s);
|
||||
System.err.println("FAILED: " + s);
|
||||
fail++;
|
||||
}
|
||||
|
||||
private static void setFirst(String s) {
|
||||
try {
|
||||
throw new RuntimeException(s);
|
||||
} catch (RuntimeException x) {
|
||||
first = x;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user