| /* |
| * Copyright 2008 Google Inc. |
| * |
| * 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 java.lang; |
| |
| import static javaemul.internal.InternalPreconditions.checkCriticalArithmetic; |
| |
| import jsinterop.annotations.JsPackage; |
| import jsinterop.annotations.JsType; |
| |
| /** |
| * Math utility methods and constants. |
| */ |
| public final class Math { |
| // The following methods are not implemented because JS doesn't provide the |
| // necessary pieces: |
| // public static double ulp (double x) |
| // public static float ulp (float x) |
| // public static int getExponent (double d) |
| // public static int getExponent (float f) |
| // public static double IEEEremainder(double f1, double f2) |
| // public static double nextAfter(double start, double direction) |
| // public static float nextAfter(float start, float direction) |
| // public static double nextUp(double start) { |
| // return nextAfter(start, 1.0d); |
| // } |
| // public static float nextUp(float start) { |
| // return nextAfter(start,1.0f); |
| // } |
| |
| public static final double E = 2.7182818284590452354; |
| public static final double PI = 3.14159265358979323846; |
| |
| private static final double PI_OVER_180 = PI / 180.0; |
| private static final double PI_UNDER_180 = 180.0 / PI; |
| |
| public static double abs(double x) { |
| return NativeMath.abs(x); |
| } |
| |
| public static float abs(float x) { |
| return (float) NativeMath.abs(x); |
| } |
| |
| public static int abs(int x) { |
| return x < 0 ? -x : x; |
| } |
| |
| public static long abs(long x) { |
| return x < 0 ? -x : x; |
| } |
| |
| public static double acos(double x) { |
| return NativeMath.acos(x); |
| } |
| |
| public static double asin(double x) { |
| return NativeMath.asin(x); |
| } |
| |
| public static int addExact(int x, int y) { |
| double r = (double) x + (double) y; |
| checkCriticalArithmetic(isSafeIntegerRange(r)); |
| return (int) r; |
| } |
| |
| public static long addExact(long x, long y) { |
| long r = x + y; |
| // "Hacker's Delight" 2-12 Overflow if both arguments have the opposite sign of the result |
| checkCriticalArithmetic(((x ^ r) & (y ^ r)) >= 0); |
| return r; |
| } |
| |
| public static double atan(double x) { |
| return NativeMath.atan(x); |
| } |
| |
| public static double atan2(double y, double x) { |
| return NativeMath.atan2(y, x); |
| } |
| |
| public static double cbrt(double x) { |
| return x == 0 || !Double.isFinite(x) ? x : NativeMath.pow(x, 1.0 / 3.0); |
| } |
| |
| public static double ceil(double x) { |
| return NativeMath.ceil(x); |
| } |
| |
| public static double copySign(double magnitude, double sign) { |
| return isNegative(sign) ? -NativeMath.abs(magnitude) : NativeMath.abs(magnitude); |
| } |
| |
| private static boolean isNegative(double d) { |
| return d < 0 || 1 / d < 0; |
| } |
| |
| public static float copySign(float magnitude, float sign) { |
| return (float) copySign((double) magnitude, (double) sign); |
| } |
| |
| public static double cos(double x) { |
| return NativeMath.cos(x); |
| } |
| |
| public static double cosh(double x) { |
| return (NativeMath.exp(x) + NativeMath.exp(-x)) / 2; |
| } |
| |
| public static int decrementExact(int x) { |
| checkCriticalArithmetic(x != Integer.MIN_VALUE); |
| return x - 1; |
| } |
| |
| public static long decrementExact(long x) { |
| checkCriticalArithmetic(x != Long.MIN_VALUE); |
| return x - 1; |
| } |
| |
| public static double exp(double x) { |
| return NativeMath.exp(x); |
| } |
| |
| public static double expm1(double d) { |
| return d == 0 ? d : NativeMath.exp(d) - 1; |
| } |
| |
| public static double floor(double x) { |
| return NativeMath.floor(x); |
| } |
| |
| public static int floorDiv(int dividend, int divisor) { |
| checkCriticalArithmetic(divisor != 0); |
| // round down division if the signs are different and modulo not zero |
| return ((dividend ^ divisor) >= 0 ? dividend / divisor : ((dividend + 1) / divisor) - 1); |
| } |
| |
| public static long floorDiv(long dividend, long divisor) { |
| checkCriticalArithmetic(divisor != 0); |
| // round down division if the signs are different and modulo not zero |
| return ((dividend ^ divisor) >= 0 ? dividend / divisor : ((dividend + 1) / divisor) - 1); |
| } |
| |
| public static int floorMod(int dividend, int divisor) { |
| checkCriticalArithmetic(divisor != 0); |
| return ((dividend % divisor) + divisor) % divisor; |
| } |
| |
| public static long floorMod(long dividend, long divisor) { |
| checkCriticalArithmetic(divisor != 0); |
| return ((dividend % divisor) + divisor) % divisor; |
| } |
| |
| public static double hypot(double x, double y) { |
| return Double.isInfinite(x) || Double.isInfinite(y) ? |
| Double.POSITIVE_INFINITY : NativeMath.sqrt(x * x + y * y); |
| } |
| |
| public static int incrementExact(int x) { |
| checkCriticalArithmetic(x != Integer.MAX_VALUE); |
| return x + 1; |
| } |
| |
| public static long incrementExact(long x) { |
| checkCriticalArithmetic(x != Long.MAX_VALUE); |
| return x + 1; |
| } |
| |
| public static double log(double x) { |
| return NativeMath.log(x); |
| } |
| |
| public static double log10(double x) { |
| return NativeMath.log(x) * NativeMath.LOG10E; |
| } |
| |
| public static double log1p(double x) { |
| return x == 0 ? x : NativeMath.log(x + 1); |
| } |
| |
| public static double max(double x, double y) { |
| return NativeMath.max(x, y); |
| } |
| |
| public static float max(float x, float y) { |
| return (float) NativeMath.max(x, y); |
| } |
| |
| public static int max(int x, int y) { |
| return x > y ? x : y; |
| } |
| |
| public static long max(long x, long y) { |
| return x > y ? x : y; |
| } |
| |
| public static double min(double x, double y) { |
| return NativeMath.min(x, y); |
| } |
| |
| public static float min(float x, float y) { |
| return (float) NativeMath.min(x, y); |
| } |
| |
| public static int min(int x, int y) { |
| return x < y ? x : y; |
| } |
| |
| public static long min(long x, long y) { |
| return x < y ? x : y; |
| } |
| |
| public static int multiplyExact(int x, int y) { |
| double r = (double) x * (double) y; |
| checkCriticalArithmetic(isSafeIntegerRange(r)); |
| return (int) r; |
| } |
| |
| public static long multiplyExact(long x, long y) { |
| if (y == -1) { |
| return negateExact(x); |
| } |
| if (y == 0) { |
| return 0; |
| } |
| long r = x * y; |
| checkCriticalArithmetic(r / y == x); |
| return r; |
| } |
| |
| public static int negateExact(int x) { |
| checkCriticalArithmetic(x != Integer.MIN_VALUE); |
| return -x; |
| } |
| |
| public static long negateExact(long x) { |
| checkCriticalArithmetic(x != Long.MIN_VALUE); |
| return -x; |
| } |
| |
| public static double pow(double x, double exp) { |
| return NativeMath.pow(x, exp); |
| } |
| |
| public static double random() { |
| return NativeMath.random(); |
| } |
| |
| public static double rint(double x) { |
| // Floating point has a mantissa with an accuracy of 52 bits so |
| // any number bigger than 2^52 is effectively a finite integer value. |
| // This case also filters out NaN and infinite values. |
| if (NativeMath.abs(x) < (double) (1L << 52)) { |
| double mod2 = x % 2; |
| if ((mod2 == -1.5) || (mod2 == 0.5)) { |
| x = NativeMath.floor(x); |
| } else { |
| x = NativeMath.round(x); |
| } |
| } |
| return x; |
| } |
| |
| public static long round(double x) { |
| return (long) NativeMath.round(x); |
| } |
| |
| public static int round(float x) { |
| return (int) NativeMath.round(x); |
| } |
| |
| public static int subtractExact(int x, int y) { |
| double r = (double) x - (double) y; |
| checkCriticalArithmetic(isSafeIntegerRange(r)); |
| return (int) r; |
| } |
| |
| public static long subtractExact(long x, long y) { |
| long r = x - y; |
| // "Hacker's Delight" Overflow if the arguments have different signs and |
| // the sign of the result is different than the sign of x |
| checkCriticalArithmetic(((x ^ y) & (x ^ r)) >= 0); |
| return r; |
| } |
| |
| public static double scalb(double d, int scaleFactor) { |
| if (scaleFactor >= 31 || scaleFactor <= -31) { |
| return d * NativeMath.pow(2, scaleFactor); |
| } else if (scaleFactor > 0) { |
| return d * (1 << scaleFactor); |
| } else if (scaleFactor == 0) { |
| return d; |
| } else { |
| return d / (1 << -scaleFactor); |
| } |
| } |
| |
| public static float scalb(float f, int scaleFactor) { |
| return (float) scalb((double) f, scaleFactor); |
| } |
| |
| public static double signum(double d) { |
| if (d == 0 || Double.isNaN(d)) { |
| return d; |
| } else { |
| return d < 0 ? -1 : 1; |
| } |
| } |
| |
| public static float signum(float f) { |
| return (float) signum((double) f); |
| } |
| |
| public static double sin(double x) { |
| return NativeMath.sin(x); |
| } |
| |
| public static double sinh(double x) { |
| return x == 0 ? x : (NativeMath.exp(x) - NativeMath.exp(-x)) / 2; |
| } |
| |
| public static double sqrt(double x) { |
| return NativeMath.sqrt(x); |
| } |
| |
| public static double tan(double x) { |
| return NativeMath.tan(x); |
| } |
| |
| public static double tanh(double x) { |
| if (x == 0.0) { |
| return x; |
| } else if (Double.isInfinite(x)) { |
| return signum(x); |
| } else { |
| double e2x = NativeMath.exp(2 * x); |
| return (e2x - 1) / (e2x + 1); |
| } |
| } |
| |
| public static double toDegrees(double x) { |
| return x * PI_UNDER_180; |
| } |
| |
| public static int toIntExact(long x) { |
| int ix = (int) x; |
| checkCriticalArithmetic(ix == x); |
| return ix; |
| } |
| |
| public static double toRadians(double x) { |
| return x * PI_OVER_180; |
| } |
| |
| private static boolean isSafeIntegerRange(double value) { |
| return Integer.MIN_VALUE <= value && value <= Integer.MAX_VALUE; |
| } |
| |
| @JsType(isNative = true, name = "Math", namespace = JsPackage.GLOBAL) |
| private static class NativeMath { |
| public static double LOG10E; |
| public static native double abs(double x); |
| public static native double acos(double x); |
| public static native double asin(double x); |
| public static native double atan(double x); |
| public static native double atan2(double y, double x); |
| public static native double ceil(double x); |
| public static native double cos(double x); |
| public static native double exp(double x); |
| public static native double floor(double x); |
| public static native double log(double x); |
| public static native double max(double x, double y); |
| public static native double min(double x, double y); |
| public static native double pow(double x, double exp); |
| public static native double random(); |
| public static native double round(double x); |
| public static native double sin(double x); |
| public static native double sqrt(double x); |
| public static native double tan(double x); |
| } |
| } |