mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
classlib: replace usage of Math.log10 with custom implementation of int log10 algorithm
This fixes BigDecimal support on WASI, which does not support log10 at the moment
This commit is contained in:
parent
a9af6e4f33
commit
bb837bd020
|
@ -22,10 +22,21 @@ public final class DoubleAnalyzer {
|
|||
public static final int DECIMAL_PRECISION = 18;
|
||||
public static final long DOUBLE_MAX_POS = 100000000000000000L;
|
||||
private static final long MAX_MANTISSA = Long.divideUnsigned(-1, 10);
|
||||
private static final Result resultForLog10 = new Result();
|
||||
|
||||
private DoubleAnalyzer() {
|
||||
}
|
||||
|
||||
public static int fastIntLog10(double d) {
|
||||
var result = resultForLog10;
|
||||
analyze(d, result);
|
||||
var exponent = result.exponent;
|
||||
if (exponent < 0 && result.mantissa > 100000000000000000L) {
|
||||
++exponent;
|
||||
}
|
||||
return exponent;
|
||||
}
|
||||
|
||||
public static void analyze(double d, Result result) {
|
||||
long bits = Double.doubleToLongBits(d);
|
||||
result.sign = (bits & (1L << 63)) != 0;
|
||||
|
|
|
@ -23,11 +23,6 @@ import org.teavm.classlib.java.util.TArrays;
|
|||
|
||||
class TAbstractStringBuilder implements TSerializable, TCharSequence {
|
||||
static class Constants {
|
||||
static int[] intPowersOfTen = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
|
||||
1000000000 };
|
||||
static long[] longPowersOfTen = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
|
||||
1000000000, 10000000000L, 100000000000L, 1000000000000L, 10000000000000L, 100000000000000L,
|
||||
1000000000000000L, 10000000000000000L, 100000000000000000L, 1000000000000000000L };
|
||||
static final long[] longLogPowersOfTen = { 1, 10, 100, 10000, 100000000, 10000000000000000L, };
|
||||
|
||||
static final DoubleAnalyzer.Result doubleAnalysisResult = new DoubleAnalyzer.Result();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.classlib.java.math;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.teavm.classlib.impl.text.DoubleAnalyzer;
|
||||
|
||||
/**
|
||||
* This class represents immutable arbitrary precision decimal numbers. Each
|
||||
|
@ -1691,7 +1692,7 @@ public class TBigDecimal extends Number implements Comparable<TBigDecimal>, Seri
|
|||
// The ANSI standard X3.274-1996 algorithm
|
||||
int m = Math.abs(n);
|
||||
int mcPrecision = mc.getPrecision();
|
||||
int elength = (int) Math.log10(m) + 1; // decimal digits in 'n'
|
||||
int elength = (int) DoubleAnalyzer.fastIntLog10(m) + 1; // decimal digits in 'n'
|
||||
int oneBitMask; // mask of bits
|
||||
TBigDecimal accum; // the single accumulator
|
||||
TMathContext newPrecision = mc; // MathContext by default
|
||||
|
@ -1850,7 +1851,7 @@ public class TBigDecimal extends Number implements Comparable<TBigDecimal>, Seri
|
|||
} else if (bitLength >= 1) {
|
||||
doubleUnsc = smallValue;
|
||||
}
|
||||
decimalDigits += Math.log10(Math.abs(doubleUnsc));
|
||||
decimalDigits += DoubleAnalyzer.fastIntLog10(Math.abs(doubleUnsc));
|
||||
} else {
|
||||
// (bitLength >= 1024)
|
||||
/* To calculate the precision for large numbers
|
||||
|
@ -2816,7 +2817,7 @@ public class TBigDecimal extends Number implements Comparable<TBigDecimal>, Seri
|
|||
Long.signum(fraction) * (5 + compRem),
|
||||
mc.getRoundingMode());
|
||||
// If after to add the increment the precision changed, we normalize the size
|
||||
if (Math.log10(Math.abs(integer)) >= mc.getPrecision()) {
|
||||
if (DoubleAnalyzer.fastIntLog10(Math.abs(integer)) >= mc.getPrecision()) {
|
||||
integer /= 10;
|
||||
newScale--;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2023 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.impl.text;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DoubleAnalyzerTest {
|
||||
@Test
|
||||
public void decimalExponent() {
|
||||
var numbers = new double[] { 1e-200, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e200 };
|
||||
var result = new DoubleAnalyzer.Result();
|
||||
for (var number : numbers) {
|
||||
var e = number / 100;
|
||||
assertEquals((int) Math.log10(number), DoubleAnalyzer.fastIntLog10(number));
|
||||
assertEquals((int) Math.log10(number + e), DoubleAnalyzer.fastIntLog10(number + e));
|
||||
assertEquals((int) Math.log10(number - e), DoubleAnalyzer.fastIntLog10(number - e));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,12 +41,9 @@ import java.math.MathContext;
|
|||
import java.math.RoundingMode;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class BigDecimalArithmeticTest {
|
||||
/**
|
||||
* Add two numbers of equal positive scales
|
||||
|
|
|
@ -46,12 +46,9 @@ import java.math.MathContext;
|
|||
import java.math.RoundingMode;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class BigDecimalCompareTest {
|
||||
/**
|
||||
* Abs() of a negative BigDecimal
|
||||
|
|
|
@ -44,12 +44,9 @@ import java.math.MathContext;
|
|||
import java.math.RoundingMode;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class BigDecimalConstructorsTest {
|
||||
/**
|
||||
* check ONE
|
||||
|
|
|
@ -44,12 +44,9 @@ import java.math.BigInteger;
|
|||
import java.math.RoundingMode;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class BigDecimalScaleOperationsTest {
|
||||
/**
|
||||
* Check the default scale
|
||||
|
|
|
@ -40,12 +40,9 @@ import static org.junit.Assert.assertTrue;
|
|||
import java.math.BigInteger;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class BigIntegerToStringTest {
|
||||
/**
|
||||
* If 36 < radix < 2 it should be set to 10
|
||||
|
|
|
@ -27,15 +27,12 @@ import java.util.Currency;
|
|||
import java.util.Locale;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMProperties;
|
||||
import org.teavm.junit.TeaVMProperty;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@TeaVMProperties(@TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, en_GB, ru, ru_RU"))
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class DecimalFormatTest {
|
||||
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
||||
|
||||
|
|
|
@ -23,16 +23,13 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.EachTestCompiledSeparately;
|
||||
import org.teavm.junit.SkipJVM;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
import org.teavm.junit.TeaVMProperties;
|
||||
import org.teavm.junit.TeaVMProperty;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
import org.teavm.junit.TestPlatform;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
@TeaVMProperties(@TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, en_GB, ru, ru_RU"))
|
||||
@EachTestCompiledSeparately
|
||||
@SkipPlatform(TestPlatform.WASI)
|
||||
public class NumberFormatTest {
|
||||
@Test
|
||||
public void formatsNumber() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user