While loading chunks, check if double values can be represented as integers,

and load them as LIntegers instead of LDoubles if so. Also change test2 so that
it does not fail because of the rounding problem. With these changes, 4 out of
7 test cases in LuaJTest now pass.
This commit is contained in:
Ian Farmer
2007-07-09 01:31:31 +00:00
parent 241edfbf37
commit 62022d5881
4 changed files with 115 additions and 4 deletions

View File

@@ -189,14 +189,33 @@ public class LoadState {
return new LString( s ); return new LString( s );
} }
static LNumber longBitsToLuaNumber( long bits ) {
if ( ( bits & ( ( 1L << 63 ) - 1 ) ) == 0L ) {
return new LInteger( 0 );
}
int e = (int)((bits >> 52) & 0x7ffL) - 1023;
if ( e >= 0 && e < 31 ) {
long f = bits & 0xFFFFFFFFFFFFFL;
int shift = 52 - e;
long intPrecMask = ( 1L << shift ) - 1;
if ( ( f & intPrecMask ) == 0 ) {
int intValue = (int)( f >> shift ) | ( 1 << e );
return new LInteger( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue );
}
}
double value = Double.longBitsToDouble(bits);
return new LDouble( value );
}
LNumber loadNumber() throws IOException { LNumber loadNumber() throws IOException {
if ( this.luacIsNumberIntegral ) { if ( this.luacIsNumberIntegral ) {
int value = loadInt(); int value = loadInt();
return new LInteger( value ); return new LInteger( value );
} else { } else {
long bits = loadInt64(); return longBitsToLuaNumber( loadInt64() );
double value = Double.longBitsToDouble(bits);
return new LDouble( value );
} }
} }
// //

View File

@@ -0,0 +1,92 @@
package lua.io;
import java.util.Random;
import junit.framework.TestCase;
import lua.value.LDouble;
import lua.value.LInteger;
import lua.value.LNumber;
public class LoadStateTest extends TestCase {
double[] DOUBLE_VALUES = {
0.0,
1.0,
2.5,
10.0,
16.0,
16.125,
-1.0,
2.0,
-2.0,
-10.0,
-0.25,
-25,
Integer.MAX_VALUE,
Integer.MAX_VALUE - 1,
(double)Integer.MAX_VALUE + 1.0,
Integer.MIN_VALUE,
Integer.MIN_VALUE + 1,
(double)Integer.MIN_VALUE - 1.0,
Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
Double.MAX_VALUE,
Double.MIN_NORMAL
};
public void testLongBitsToLuaNumber() {
for ( int i = 0; i < DOUBLE_VALUES.length; ++i ) {
double v = DOUBLE_VALUES[i];
long bits = Double.doubleToLongBits( v );
LNumber luaNumber = LoadState.longBitsToLuaNumber( bits );
assertEquals( v, luaNumber.luaAsDouble() );
if ( v != Integer.MIN_VALUE ) {
// Special case of MIN_VALUE is probably not worth dealing with.
// (Unlike zero, which is also a special case but much more common.)
assertEquals( "Value "+v+" (at index "+i+") can be represented as integer but was not",
luaNumber instanceof LInteger, v == (double)( (int) v ) );
}
}
}
private LNumber simpleBitsToLuaNumber( long bits ) {
double value = Double.longBitsToDouble( bits );
int valueAsInt = (int) value;
if ( value == (double) valueAsInt ) {
return new LInteger( valueAsInt );
} else {
return new LDouble( value );
}
}
public void testLongBitsToLuaNumberSpeed() {
long[] BITS = new long[ 500000 ];
Random r = new Random();
for ( int i = 0; i < DOUBLE_VALUES.length; ++i ) {
BITS[i] = Double.doubleToLongBits( DOUBLE_VALUES[i] );
}
for ( int i = DOUBLE_VALUES.length; i < BITS.length; i += 2 ) {
BITS[i ] = r.nextLong();
BITS[i+1] = Double.doubleToLongBits( r.nextDouble() );
}
long startTime = System.currentTimeMillis();
for ( int j = 0; j < BITS.length; ++j ) {
LoadState.longBitsToLuaNumber( BITS[j] );
}
long endTime = System.currentTimeMillis();
long complexConversionTime = endTime - startTime;
startTime = System.currentTimeMillis();
for ( int j = 0; j < BITS.length; ++j ) {
simpleBitsToLuaNumber( BITS[j] );
}
endTime = System.currentTimeMillis();
long simpleConversionTime = endTime - startTime;
assertTrue( complexConversionTime < simpleConversionTime );
}
}

View File

@@ -11,7 +11,7 @@ function myfunc(x)
return x*x; return x*x;
end end
print( myfunc(0.1) ) print( myfunc(0.25) )
do do
local oldMyfunc = myfunc local oldMyfunc = myfunc

Binary file not shown.