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:
@@ -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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|||||||
92
src/test/java/lua/io/LoadStateTest.java
Normal file
92
src/test/java/lua/io/LoadStateTest.java
Normal 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
Reference in New Issue
Block a user