de.mirkosertic.bytecoder.classlib.java.lang.TMath Maven / Gradle / Ivy
/*
* Copyright 2018 Mirko Sertic
*
* 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 de.mirkosertic.bytecoder.classlib.java.lang;
import de.mirkosertic.bytecoder.api.EmulatedByRuntime;
import de.mirkosertic.bytecoder.api.SubstitutesInClass;
@SubstitutesInClass(completeReplace = true)
public class TMath {
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
private static class FloatExponents {
public static final float[] exponents = { 0x1p1f, 0x1p2f, 0x1p4f, 0x1p8f, 0x1p16f, 0x1p32f, 0x1p64f };
public static final float[] negativeExponents = { 0x1p-1f, 0x1p-2f, 0x1p-4f, 0x1p-8f, 0x1p-16f, 0x1p-32f,
0x1p-64f };
public static final float[] negativeExponents2 = { 0x1p-0f, 0x1p-1f, 0x1p-3f, 0x1p-7f, 0x1p-15f, 0x1p-31f,
0x1p-63f };
}
public static float abs(final float a) {
if (a<0) {
return -a;
}
return a;
}
public static double abs(final double a) {
if (a<0) {
return -a;
}
return a;
}
public static int abs(final int a) {
if (a<0) {
return -a;
}
return a;
}
@EmulatedByRuntime
public static native double sqrt(double aValue);
public static native double cbrt(double aValue);
@EmulatedByRuntime
public static native double ceil(double aValue);
@EmulatedByRuntime
public static native double floor(double aValue);
public static native double sin(double aValue);
public static native double cos(double aValue);
public static native double random();
public static native double toRadians(double aValue);
public static native double toDegrees(double aValue);
public static native double tan(double aValue);
@EmulatedByRuntime
public static native long max(long aValue1, long aValue2);
@EmulatedByRuntime
public static native int max(int aValue1, int aValue2);
@EmulatedByRuntime
public static native float max(float aValue1, float aValue2);
@EmulatedByRuntime
public static native double max(double aValue1, double aValue2);
@EmulatedByRuntime
public static native int min(int aValue1, int aValue2);
@EmulatedByRuntime
public static native long min(long aValue1, long aValue2);
@EmulatedByRuntime
public static native float min(float aValue1, float aValue2);
@EmulatedByRuntime
public static native double min(double aValue1, double aValue2);
public static int getExponent(float f) {
f = abs(f);
int exp = 0;
final float[] exponents = FloatExponents.exponents;
final float[] negativeExponents = FloatExponents.negativeExponents;
final float[] negativeExponents2 = FloatExponents.negativeExponents2;
if (f > 1) {
int expBit = 1 << (exponents.length - 1);
for (int i = exponents.length - 1; i >= 0; --i) {
if (f >= exponents[i]) {
f *= negativeExponents[i];
exp |= expBit;
}
expBit >>>= 1;
}
} else if (f < 1) {
int expBit = 1 << (negativeExponents.length - 1);
int offset = 0;
if (f < 0x1p-126) {
f *= 0x1p23f;
offset = 23;
}
for (int i = negativeExponents2.length - 1; i >= 0; --i) {
if (f < negativeExponents2[i]) {
f *= exponents[i];
exp |= expBit;
}
expBit >>>= 1;
}
exp = -(exp + offset);
}
return exp;
}
public static native double log(double aValue1);
public static int floorMod(final int x, final int y) {
return x - floorDiv(x, y) * y;
}
public static int floorDiv(final int x, final int y) {
int r = x / y;
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
public static long floorDiv(final long x, final long y) {
long r = x / y;
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
public static long floorDiv(final long x, final int y) {
return floorDiv(x, (long)y);
}
public static int floorMod(final long x, final int y) {
// Result cannot overflow the range of int.
return (int)(x - floorDiv(x, y) * y);
}
public static long floorMod(final long x, final long y) {
return x - floorDiv(x, y) * y;
}
public static int addExact(final int x, final int y) {
final int r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
public static long addExact(final long x, final long y) {
final long r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("long overflow");
}
return r;
}
public static int multiplyExact(final int a, final int b) {
return a * b;
}
public static native double pow(double a, double b);
public static int round(final float value) {
return (int) value;
}
public static long round(final double value) {
return (int) value;
}
public static double rint(final double value) {
return (int) value;
}
public static double hypot(final double a, final double b) {
return sqrt(a*a + b*b);
}
public static native double acos(final double value);
public static long abs(final long value) {
if (value < 0) {
return -value;
}
return value;
}
public static double IEEEremainder(final double a, final double b) {
return 0;
}
public static native double atan2(final double a, final double b);
public static double ulp(final double d) {
int exp = getExponent((float) d);
switch(exp) {
case Double.MAX_EXPONENT + 1: // NaN or infinity
return Math.abs(d);
case Double.MIN_EXPONENT - 1: // zero or subnormal
return Double.MIN_VALUE;
default:
assert exp <= Double.MAX_EXPONENT && exp >= Double.MIN_EXPONENT;
// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (53-1);
if (exp >= Double.MIN_EXPONENT) {
return powerOfTwoD(exp);
}
else {
// return a subnormal result; left shift integer
// representation of Double.MIN_VALUE appropriate
// number of positions
return Double.longBitsToDouble(1L <<
(exp - (Double.MIN_EXPONENT - (53-1)) ));
}
}
}
public static float ulp(final float f) {
int exp = getExponent(f);
switch(exp) {
case Float.MAX_EXPONENT+1: // NaN or infinity
return Math.abs(f);
case Float.MIN_EXPONENT-1: // zero or subnormal
return Float.MIN_VALUE;
default:
assert exp <= Float.MAX_EXPONENT && exp >= Float.MIN_EXPONENT;
// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (24-1);
if (exp >= Float.MIN_EXPONENT) {
return powerOfTwoF(exp);
} else {
// return a subnormal result; left shift integer
// representation of FloatConsts.MIN_VALUE appropriate
// number of positions
return Float.intBitsToFloat(1 <<
(exp - (Float.MIN_EXPONENT - (24-1)) ));
}
}
}
static double powerOfTwoD(final int n) {
assert(n >= Double.MIN_EXPONENT && n <= Double.MAX_EXPONENT);
return Double.longBitsToDouble((((long)n + (long)1023) <<
(53-1))
& 9218868437227405312L);
}
static float powerOfTwoF(final int n) {
assert(n >= Float.MIN_EXPONENT && n <= Float.MAX_EXPONENT);
return Float.intBitsToFloat(((n + 127) <<
(42-1))
& 2139095040);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy