All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.emul.java.lang.Math Maven / Gradle / Ivy

/*
 * 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.JsMethod;
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;

  @JsMethod(namespace = "Math")
  public static native double abs(double x);

  @JsMethod(namespace = "Math")
  public static native float abs(float x);

  @JsMethod(namespace = "Math")
  public static native int abs(int x);

  public static long abs(long x) {
    return x < 0 ? -x : x;
  }

  @JsMethod(namespace = "Math")
  public static native double acos(double x);

  @JsMethod(namespace = "Math")
  public static native double asin(double 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;
  }

  @JsMethod(namespace = "Math")
  public static native double atan(double x);

  @JsMethod(namespace = "Math")
  public static native double atan2(double y, double x);

  public static double cbrt(double x) {
    return x == 0 || !Double.isFinite(x) ? x : pow(x, 1.0 / 3.0);
  }

  @JsMethod(namespace = "Math")
  public static native double ceil(double x);

  public static double copySign(double magnitude, double sign) {
    return isNegative(sign) ? -abs(magnitude) : 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);
  }

  @JsMethod(namespace = "Math")
  public static native double cos(double x);

  public static double cosh(double x) {
    return (exp(x) + 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;
  }

  @JsMethod(namespace = "Math")
  public static native double exp(double x);

  public static double expm1(double d) {
    return d == 0 ? d : exp(d) - 1;
  }

  @JsMethod(namespace = "Math")
  public static native double floor(double 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 : 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;
  }

  @JsMethod(namespace = "Math")
  public static native double log(double x);

  public static double log10(double x) {
    return log(x) * NativeMath.LOG10E;
  }

  public static double log1p(double x) {
    return x == 0 ? x : log(x + 1);
  }

  @JsMethod(namespace = "Math")
  public static native double max(double x, double y);

  @JsMethod(namespace = "Math")
  public static native float max(float x, float y);

  @JsMethod(namespace = "Math")
  public static native int max(int x, int y);

  public static long max(long x, long y) {
    return x > y ? x : y;
  }

  @JsMethod(namespace = "Math")
  public static native double min(double x, double y);

  @JsMethod(namespace = "Math")
  public static native float min(float x, float y);

  @JsMethod(namespace = "Math")
  public static native int min(int x, int 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;
  }

  @JsMethod(namespace = "Math")
  public static native double pow(double x, double exp);

  @JsMethod(namespace = "Math")
  public static native double 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 (abs(x) < (double) (1L << 52)) {
      double mod2 = x % 2;
      if ((mod2 == -1.5) || (mod2 == 0.5)) {
        x = floor(x);
      } else {
        x = 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 * 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);
  }

  @JsMethod(namespace = "Math")
  public static native double sin(double x);

  public static double sinh(double x) {
    return x == 0 ? x : (exp(x) - exp(-x)) / 2;
  }

  @JsMethod(namespace = "Math")
  public static native double sqrt(double x);

  @JsMethod(namespace = "Math")
  public static native double tan(double x);

  public static double tanh(double x) {
    if (x == 0.0) {
      return x;
    } else if (Double.isInfinite(x)) {
      return signum(x);
    } else {
      double e2x = 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 round(double x);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy