mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Use JS typed arrays to reinterpret floats and ints.
Also, drop IE9 support
This commit is contained in:
parent
b9ec21a667
commit
cf9090e0fa
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.backend.javascript.spi.Injector;
|
||||||
|
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public class DoubleGenerator implements Injector {
|
||||||
|
@Override
|
||||||
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
|
context.getWriter().append("$rt_").append(methodRef.getName()).append("(");
|
||||||
|
context.writeExpr(context.getArgument(0));
|
||||||
|
context.getWriter().append(")");
|
||||||
|
}
|
||||||
|
}
|
|
@ -415,9 +415,13 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
|
||||||
exp = 0;
|
exp = 0;
|
||||||
double digit = 1;
|
double digit = 1;
|
||||||
for (int i = negDoublePowersOfTen.length - 1; i >= 0; --i) {
|
for (int i = negDoublePowersOfTen.length - 1; i >= 0; --i) {
|
||||||
if ((exp | bit) <= DOUBLE_MAX_EXPONENT && negDoublePowersOfTen[i] * digit * 10 > value) {
|
if ((exp | bit) <= 324 && negDoublePowersOfTen[i] * digit * 10 > value) {
|
||||||
digit *= negDoublePowersOfTen[i];
|
|
||||||
exp |= bit;
|
exp |= bit;
|
||||||
|
if (exp == 324) {
|
||||||
|
value /= negDoublePowersOfTen[i];
|
||||||
|
} else {
|
||||||
|
digit *= negDoublePowersOfTen[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bit >>= 1;
|
bit >>= 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||||
import org.teavm.interop.Import;
|
import org.teavm.interop.Import;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
|
|
||||||
|
@ -241,52 +242,11 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
return doubleToLongBits(value);
|
return doubleToLongBits(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long doubleToLongBits(double value) {
|
@InjectedBy(DoubleGenerator.class)
|
||||||
if (value == POSITIVE_INFINITY) {
|
public static native long doubleToLongBits(double value);
|
||||||
return 0x7FF0000000000000L;
|
|
||||||
} else if (value == NEGATIVE_INFINITY) {
|
|
||||||
return 0xFFF0000000000000L;
|
|
||||||
} else if (isNaN(value)) {
|
|
||||||
return 0x7FF8000000000000L;
|
|
||||||
}
|
|
||||||
double abs = TMath.abs(value);
|
|
||||||
int exp = TMath.getExponent(abs);
|
|
||||||
int negExp = -exp + 52;
|
|
||||||
if (exp < -1022) {
|
|
||||||
exp = -1023;
|
|
||||||
negExp = 1022 + 52;
|
|
||||||
}
|
|
||||||
double doubleMantissa;
|
|
||||||
if (negExp <= 1022) {
|
|
||||||
doubleMantissa = abs * binaryExponent(negExp);
|
|
||||||
} else {
|
|
||||||
doubleMantissa = abs * 0x1p1022 * binaryExponent(negExp - 1022);
|
|
||||||
}
|
|
||||||
long mantissa = (long) (doubleMantissa + 0.5) & 0xFFFFFFFFFFFFFL;
|
|
||||||
return mantissa | ((exp + 1023L) << 52) | (value < 0 || 1 / value == NEGATIVE_INFINITY ? (1L << 63) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double longBitsToDouble(long bits) {
|
@InjectedBy(DoubleGenerator.class)
|
||||||
if ((bits & 0x7FF0000000000000L) == 0x7FF0000000000000L) {
|
public static native double longBitsToDouble(long bits);
|
||||||
if (bits == 0x7FF0000000000000L) {
|
|
||||||
return POSITIVE_INFINITY;
|
|
||||||
} else if (bits == 0xFFF0000000000000L) {
|
|
||||||
return NEGATIVE_INFINITY;
|
|
||||||
} else {
|
|
||||||
return NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
boolean negative = (bits & (1L << 63)) != 0;
|
|
||||||
int rawExp = (int) ((bits >> 52) & 0x7FFL);
|
|
||||||
long mantissa = bits & 0xFFFFFFFFFFFFFL;
|
|
||||||
if (rawExp == 0) {
|
|
||||||
mantissa <<= 1;
|
|
||||||
} else {
|
|
||||||
mantissa |= 1L << 52;
|
|
||||||
}
|
|
||||||
double value = mantissa * binaryExponent(rawExp - 1023 - 52);
|
|
||||||
return !negative ? value : -value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TString toHexString(double d) {
|
public static TString toHexString(double d) {
|
||||||
if (isNaN(d)) {
|
if (isNaN(d)) {
|
||||||
|
@ -351,29 +311,4 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
|
|
||||||
return new TString(buffer, 0, sz);
|
return new TString(buffer, 0, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double binaryExponent(int n) {
|
|
||||||
double result = 1;
|
|
||||||
if (n >= 0) {
|
|
||||||
double d = 2;
|
|
||||||
while (n != 0) {
|
|
||||||
if (n % 2 != 0) {
|
|
||||||
result *= d;
|
|
||||||
}
|
|
||||||
n /= 2;
|
|
||||||
d *= d;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
n = -n;
|
|
||||||
double d = 0.5;
|
|
||||||
while (n != 0) {
|
|
||||||
if (n % 2 != 0) {
|
|
||||||
result *= d;
|
|
||||||
}
|
|
||||||
n /= 2;
|
|
||||||
d *= d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,77 +246,11 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
return floatToIntBits(value);
|
return floatToIntBits(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int floatToIntBits(float value) {
|
@JSBody(params = "value", script = "return $rt_floatToIntBits(value);")
|
||||||
if (value == POSITIVE_INFINITY) {
|
public static native int floatToIntBits(float value);
|
||||||
return 0x7F800000;
|
|
||||||
} else if (value == NEGATIVE_INFINITY) {
|
|
||||||
return 0xFF800000;
|
|
||||||
} else if (isNaN(value)) {
|
|
||||||
return 0x7FC00000;
|
|
||||||
}
|
|
||||||
float abs = TMath.abs(value);
|
|
||||||
int exp = TMath.getExponent(abs);
|
|
||||||
int negExp = -exp + 23;
|
|
||||||
if (exp < -126) {
|
|
||||||
exp = -127;
|
|
||||||
negExp = 126 + 23;
|
|
||||||
}
|
|
||||||
float doubleMantissa;
|
|
||||||
if (negExp <= 126) {
|
|
||||||
doubleMantissa = abs * binaryExponent(negExp);
|
|
||||||
} else {
|
|
||||||
doubleMantissa = abs * 0x1p126f * binaryExponent(negExp - 126);
|
|
||||||
}
|
|
||||||
int mantissa = (int) (doubleMantissa + 0.5f) & 0x7FFFFF;
|
|
||||||
return mantissa | ((exp + 127) << 23) | (value < 0 || 1 / value == NEGATIVE_INFINITY ? (1 << 31) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float intBitsToFloat(int bits) {
|
@JSBody(params = "bits", script = "return $rt_intBitsToFloat(bits);")
|
||||||
if ((bits & 0x7F800000) == 0x7F800000) {
|
public static native float intBitsToFloat(int bits);
|
||||||
if (bits == 0x7F800000) {
|
|
||||||
return POSITIVE_INFINITY;
|
|
||||||
} else if (bits == 0xFF800000) {
|
|
||||||
return NEGATIVE_INFINITY;
|
|
||||||
} else {
|
|
||||||
return NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
boolean negative = (bits & (1 << 31)) != 0;
|
|
||||||
int rawExp = (bits >> 23) & 0xFF;
|
|
||||||
int mantissa = bits & 0x7FFFFF;
|
|
||||||
if (rawExp == 0) {
|
|
||||||
mantissa <<= 1;
|
|
||||||
} else {
|
|
||||||
mantissa |= 1L << 23;
|
|
||||||
}
|
|
||||||
float value = mantissa * binaryExponent(rawExp - 127 - 23);
|
|
||||||
return !negative ? value : -value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float binaryExponent(int n) {
|
|
||||||
float result = 1;
|
|
||||||
if (n >= 0) {
|
|
||||||
float d = 2;
|
|
||||||
while (n != 0) {
|
|
||||||
if (n % 2 != 0) {
|
|
||||||
result *= d;
|
|
||||||
}
|
|
||||||
n /= 2;
|
|
||||||
d *= d;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
n = -n;
|
|
||||||
float d = 0.5f;
|
|
||||||
while (n != 0) {
|
|
||||||
if (n % 2 != 0) {
|
|
||||||
result *= d;
|
|
||||||
}
|
|
||||||
n /= 2;
|
|
||||||
d *= d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TString toHexString(float f) {
|
public static TString toHexString(float f) {
|
||||||
if (isNaN(f)) {
|
if (isNaN(f)) {
|
||||||
|
|
|
@ -67,56 +67,31 @@ function $rt_createLongArray(sz) {
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
var $rt_createNumericArray;
|
function $rt_createNumericArray(cls, nativeArray) {
|
||||||
var $rt_createCharArray;
|
|
||||||
var $rt_createByteArray;
|
|
||||||
var $rt_createShortArray;
|
|
||||||
var $rt_createIntArray;
|
|
||||||
var $rt_createBooleanArray;
|
|
||||||
var $rt_createFloatArray;
|
|
||||||
var $rt_createDoubleArray;
|
|
||||||
if (typeof 'ArrayBuffer' !== 'undefined') {
|
|
||||||
$rt_createNumericArray = function(cls, nativeArray) {
|
|
||||||
return new ($rt_arraycls(cls))(nativeArray);
|
return new ($rt_arraycls(cls))(nativeArray);
|
||||||
};
|
}
|
||||||
$rt_createCharArray = function(sz) {
|
function $rt_createCharArray(sz) {
|
||||||
return $rt_createNumericArray($rt_charcls(), new Uint16Array(sz));
|
return $rt_createNumericArray($rt_charcls(), new Uint16Array(sz));
|
||||||
};
|
}
|
||||||
$rt_createByteArray = function(sz) {
|
function $rt_createByteArray(sz) {
|
||||||
return $rt_createNumericArray($rt_bytecls(), new Int8Array(sz));
|
return $rt_createNumericArray($rt_bytecls(), new Int8Array(sz));
|
||||||
};
|
}
|
||||||
$rt_createShortArray = function(sz) {
|
function $rt_createShortArray(sz) {
|
||||||
return $rt_createNumericArray($rt_shortcls(), new Int16Array(sz));
|
return $rt_createNumericArray($rt_shortcls(), new Int16Array(sz));
|
||||||
};
|
}
|
||||||
$rt_createIntArray = function(sz) {
|
function $rt_createIntArray(sz) {
|
||||||
return $rt_createNumericArray($rt_intcls(), new Int32Array(sz));
|
return $rt_createNumericArray($rt_intcls(), new Int32Array(sz));
|
||||||
};
|
}
|
||||||
$rt_createBooleanArray = function(sz) {
|
function $rt_createBooleanArray(sz) {
|
||||||
return $rt_createNumericArray($rt_booleancls(), new Int8Array(sz));
|
return $rt_createNumericArray($rt_booleancls(), new Int8Array(sz));
|
||||||
};
|
}
|
||||||
$rt_createFloatArray = function(sz) {
|
function $rt_createFloatArray(sz) {
|
||||||
return $rt_createNumericArray($rt_floatcls(), new Float32Array(sz));
|
return $rt_createNumericArray($rt_floatcls(), new Float32Array(sz));
|
||||||
};
|
}
|
||||||
$rt_createDoubleArray = function(sz) {
|
function $rt_createDoubleArray(sz) {
|
||||||
return $rt_createNumericArray($rt_doublecls(), new Float64Array(sz));
|
return $rt_createNumericArray($rt_doublecls(), new Float64Array(sz));
|
||||||
};
|
|
||||||
} else {
|
|
||||||
$rt_createNumericArray = function(cls, sz) {
|
|
||||||
var data = new Array(sz);
|
|
||||||
var arr = new ($rt_arraycls(cls))(data);
|
|
||||||
for (var i = 0; i < sz; i = (i + 1) | 0) {
|
|
||||||
data[i] = 0;
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
$rt_createByteArray = function(sz) { return $rt_createNumericArray($rt_bytecls(), sz); };
|
|
||||||
$rt_createShortArray = function(sz) { return $rt_createNumericArray($rt_shortcls(), sz); };
|
|
||||||
$rt_createIntArray = function(sz) { return $rt_createNumericArray($rt_intcls(), sz); };
|
|
||||||
$rt_createBooleanArray = function(sz) { return $rt_createNumericArray($rt_booleancls(), sz); };
|
|
||||||
$rt_createFloatArray = function(sz) { return $rt_createNumericArray($rt_floatcls(), sz); };
|
|
||||||
$rt_createDoubleArray = function(sz) { return $rt_createNumericArray($rt_doublecls(), sz); };
|
|
||||||
$rt_createCharArray = function(sz) { return $rt_createNumericArray($rt_charcls(), sz); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function $rt_arraycls(cls) {
|
function $rt_arraycls(cls) {
|
||||||
var result = cls.$array;
|
var result = cls.$array;
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
|
@ -615,6 +590,27 @@ function $rt_nativeThread() {
|
||||||
function $rt_invalidPointer() {
|
function $rt_invalidPointer() {
|
||||||
throw new Error("Invalid recorded state");
|
throw new Error("Invalid recorded state");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var $rt_numberConversionView = new DataView(new ArrayBuffer(8));
|
||||||
|
|
||||||
|
function $rt_doubleToLongBits(n) {
|
||||||
|
$rt_numberConversionView.setFloat64(0, n, true);
|
||||||
|
return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true));
|
||||||
|
}
|
||||||
|
function $rt_longBitsToDouble(n) {
|
||||||
|
$rt_numberConversionView.setInt32(0, n.lo, true);
|
||||||
|
$rt_numberConversionView.setInt32(4, n.hi, true);
|
||||||
|
return $rt_numberConversionView.getFloat64(0, true);
|
||||||
|
}
|
||||||
|
function $rt_floatToIntBits(n) {
|
||||||
|
$rt_numberConversionView.setFloat32(0, n);
|
||||||
|
return $rt_numberConversionView.getInt32(0);
|
||||||
|
}
|
||||||
|
function $rt_intBitsToFloat(n) {
|
||||||
|
$rt_numberConversionView.setInt32(0, n);
|
||||||
|
return $rt_numberConversionView.getFloat32(0);
|
||||||
|
}
|
||||||
|
|
||||||
function $dbg_class(obj) {
|
function $dbg_class(obj) {
|
||||||
var cls = obj.constructor;
|
var cls = obj.constructor;
|
||||||
var arrayDegree = 0;
|
var arrayDegree = 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user