diff options
Diffstat (limited to 'javalanglib/src/main/scala/java/lang/Math.scala')
-rw-r--r-- | javalanglib/src/main/scala/java/lang/Math.scala | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/javalanglib/src/main/scala/java/lang/Math.scala b/javalanglib/src/main/scala/java/lang/Math.scala new file mode 100644 index 0000000..c8cd7aa --- /dev/null +++ b/javalanglib/src/main/scala/java/lang/Math.scala @@ -0,0 +1,211 @@ +package java +package lang + +import scala.scalajs.js + +object Math { + private lazy val internalRandom = new java.util.Random() + + final val E = 2.718281828459045 + final val PI = 3.141592653589793 + + @inline def abs(a: scala.Int): scala.Int = if (a < 0) -a else a + @inline def abs(a: scala.Long): scala.Long = if (a < 0) -a else a + @inline def abs(a: scala.Float): scala.Float = if (a < 0) -a else a + @inline def abs(a: scala.Double): scala.Double = if (a < 0) -a else a + + @inline def max(a: scala.Int, b: scala.Int): scala.Int = if (a > b) a else b + @inline def max(a: scala.Long, b: scala.Long): scala.Long = if (a > b) a else b + @inline def max(a: scala.Float, b: scala.Float): scala.Float = if (a > b) a else b + @inline def max(a: scala.Double, b: scala.Double): scala.Double = if (a > b) a else b + + @inline def min(a: scala.Int, b: scala.Int): scala.Int = if (a < b) a else b + @inline def min(a: scala.Long, b: scala.Long): scala.Long = if (a < b) a else b + @inline def min(a: scala.Float, b: scala.Float): scala.Float = if (a < b) a else b + @inline def min(a: scala.Double, b: scala.Double): scala.Double = if (a < b) a else b + + @inline def ceil(a: scala.Double): scala.Double = js.Math.ceil(a) + @inline def floor(a: scala.Double): scala.Double = js.Math.floor(a) + + @inline def round(a: scala.Float): scala.Int = js.Math.round(a).toInt + @inline def round(a: scala.Double): scala.Long = js.Math.round(a).toLong + + @inline def sqrt(a: scala.Double): scala.Double = js.Math.sqrt(a) + @inline def pow(a: scala.Double, b: scala.Double): scala.Double = js.Math.pow(a, b) + + @inline def exp(a: scala.Double): scala.Double = js.Math.exp(a) + @inline def log(a: scala.Double): scala.Double = js.Math.log(a) + @inline def log10(a: scala.Double): scala.Double = log(a) / 2.302585092994046 + @inline def log1p(a: scala.Double): scala.Double = log(a + 1) + + @inline def sin(a: scala.Double): scala.Double = js.Math.sin(a) + @inline def cos(a: scala.Double): scala.Double = js.Math.cos(a) + @inline def tan(a: scala.Double): scala.Double = js.Math.tan(a) + @inline def asin(a: scala.Double): scala.Double = js.Math.asin(a) + @inline def acos(a: scala.Double): scala.Double = js.Math.acos(a) + @inline def atan(a: scala.Double): scala.Double = js.Math.atan(a) + @inline def atan2(y: scala.Double, x: scala.Double): scala.Double = js.Math.atan2(y, x) + + def random(): scala.Double = internalRandom.nextDouble() + + @inline def toDegrees(a: scala.Double): scala.Double = a * 180.0 / PI + @inline def toRadians(a: scala.Double): scala.Double = a / 180.0 * PI + + @inline def signum(a: scala.Double): scala.Double = { + if (a > 0) 1.0 + else if (a < 0) -1.0 + else a + } + + @inline def signum(a: scala.Float): scala.Float = { + if (a > 0) 1.0f + else if (a < 0) -1.0f + else a + } + + def cbrt(a: scala.Double): scala.Double = { + if (a == 0 || a.isNaN) + return a + + val sign = if (a < 0.0) -1.0 else 1.0 + val value = sign * a + + //Initial Approximation + var x = 0.0 + var xi = pow(value, 0.3333333333333333) + + //Halley's Method (http://metamerist.com/cbrt/cbrt.htm) + while (abs(x - xi) >= 1E-16) { + x = xi + val x3 = js.Math.pow(x, 3) + val x3Plusa = x3 + value + xi = x * (x3Plusa + value) / (x3Plusa + x3) + } + return sign * xi + } + + def nextUp(a: scala.Double): scala.Double = { + // js implementation of nextUp https://gist.github.com/Yaffle/4654250 + import scala.Double._ + if (a != a || a == PositiveInfinity) + a + else if (a == NegativeInfinity) + -MaxValue + else if (a == MaxValue) + PositiveInfinity + else if (a == 0) + MinValue + else { + def iter(x: scala.Double, xi: scala.Double, n: scala.Double): scala.Double = { + if (Math.abs(xi - x) >= 1E-16) { + val c0 = (xi + x) / 2 + val c = + if (c0 == NegativeInfinity || c0 == PositiveInfinity) + x + (xi - x) / 2 + else + c0 + if (n == c) xi + else if (a < c) iter(x = x, xi = c, n = c) + else iter(x = c, xi = xi, n = c) + } + else xi + } + val d = Math.max(Math.abs(a) * 2E-16, MinValue) + val ad = a + d + val xi0 = + if (ad == PositiveInfinity) MaxValue + else ad + iter(x = a, xi = xi0, n = a) + } + } + + def nextAfter(a: scala.Double, b: scala.Double): scala.Double = { + if (b < a) + -nextUp(-a) + else if (a < b) + nextUp(a) + else if (a != a || b != b) + scala.Double.NaN + else + b + } + + def ulp(a: scala.Double): scala.Double = { + if (abs(a) == scala.Double.PositiveInfinity) + scala.Double.PositiveInfinity + else if (abs(a) == scala.Double.MaxValue) + pow(2, 971) + else + nextAfter(abs(a), scala.Double.MaxValue) - a + } + + def hypot(a: scala.Double, b: scala.Double): scala.Double = { + // http://en.wikipedia.org/wiki/Hypot#Implementation + if (abs(a) == scala.Double.PositiveInfinity || abs(b) == scala.Double.PositiveInfinity) + scala.Double.PositiveInfinity + else if (a.isNaN || b.isNaN) + scala.Double.NaN + else if (a == 0 && b == 0) + 0.0 + else { + //To Avoid Overflow and UnderFlow + // calculate |x| * sqrt(1 - (y/x)^2) instead of sqrt(x^2 + y^2) + val x = abs(a) + val y = abs(b) + val m = max(x, y) + val t = min(x, y) / m + m * sqrt(1 + t * t) + } + } + + def expm1(a: scala.Double): scala.Double = { + // https://github.com/ghewgill/picomath/blob/master/javascript/expm1.js + if (a == 0 || a.isNaN) + a + // Power Series http://en.wikipedia.org/wiki/Power_series + // for small values of a, exp(a) = 1 + a + (a*a)/2 + else if (abs(a) < 1E-5) + a + 0.5 * a * a + else + exp(a) - 1.0 + } + + def sinh(a: scala.Double): scala.Double = { + if (a.isNaN || a == 0.0 || abs(a) == scala.Double.PositiveInfinity) + a + else + (exp(a) - exp(-a)) / 2.0 + } + + def cosh(a: scala.Double): scala.Double = { + if (a.isNaN) + a + else if (a == 0.0) + 1.0 + else if (abs(a) == scala.Double.PositiveInfinity) + scala.Double.PositiveInfinity + else + (exp(a) + exp(-a)) / 2.0 + } + + def tanh(a: scala.Double): scala.Double = { + if (a.isNaN || a == 0.0) + a + else if (abs(a) == scala.Double.PositiveInfinity) + signum(a) + else { + // sinh(a) / cosh(a) = + // 1 - 2 * (exp(-a)/ (exp(-a) + exp (a))) + val expma = exp(-a) + if (expma == scala.Double.PositiveInfinity) //Infinity / Infinity + -1.0 + else { + val expa = exp(a) + val ret = expma / (expa + expma) + 1.0 - (2.0 * ret) + } + } + } + + // TODO The methods not available in the JavaScript Math object +} |