1717
1818import static javaemul .internal .InternalPreconditions .checkCriticalArithmetic ;
1919
20+ import javaemul .internal .JsUtils ;
2021import jsinterop .annotations .JsMethod ;
2122import jsinterop .annotations .JsPackage ;
2223import jsinterop .annotations .JsType ;
2526 * Math utility methods and constants.
2627 */
2728public final class Math {
28- // The following methods are not implemented because JS doesn't provide the
29- // necessary pieces:
30- // public static double ulp (double x)
31- // public static float ulp (float x)
32- // public static int getExponent (double d)
33- // public static int getExponent (float f)
34- // public static double IEEEremainder(double f1, double f2)
3529
3630 public static final double E = 2.7182818284590452354 ;
3731 public static final double PI = 3.14159265358979323846 ;
@@ -52,6 +46,16 @@ public static long abs(long x) {
5246 return x < 0 ? -x : x ;
5347 }
5448
49+ public static int absExact (int v ) {
50+ checkCriticalArithmetic (v != Integer .MIN_VALUE );
51+ return abs (v );
52+ }
53+
54+ public static long absExact (long v ) {
55+ checkCriticalArithmetic (v != Long .MIN_VALUE );
56+ return abs (v );
57+ }
58+
5559 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.acos" )
5660 public static native double acos (double x );
5761
@@ -77,9 +81,8 @@ public static long addExact(long x, long y) {
7781 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.atan2" )
7882 public static native double atan2 (double y , double x );
7983
80- public static double cbrt (double x ) {
81- return x == 0 || !Double .isFinite (x ) ? x : pow (x , 1.0 / 3.0 );
82- }
84+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.cbrt" )
85+ public static native double cbrt (double x );
8386
8487 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.ceil" )
8588 public static native double ceil (double x );
@@ -99,9 +102,8 @@ public static float copySign(float magnitude, float sign) {
99102 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.cos" )
100103 public static native double cos (double x );
101104
102- public static double cosh (double x ) {
103- return (exp (x ) + exp (-x )) / 2 ;
104- }
105+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.cosh" )
106+ public static native double cosh (double x );
105107
106108 public static int decrementExact (int x ) {
107109 checkCriticalArithmetic (x != Integer .MIN_VALUE );
@@ -116,9 +118,8 @@ public static long decrementExact(long x) {
116118 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.exp" )
117119 public static native double exp (double x );
118120
119- public static double expm1 (double d ) {
120- return d == 0 ? d : exp (d ) - 1 ;
121- }
121+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.expm1" )
122+ public static native double expm1 (double d );
122123
123124 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.floor" )
124125 public static native double floor (double x );
@@ -135,6 +136,10 @@ public static long floorDiv(long dividend, long divisor) {
135136 return ((dividend ^ divisor ) >= 0 ? dividend / divisor : ((dividend + 1 ) / divisor ) - 1 );
136137 }
137138
139+ public static long floorDiv (long dividend , int divisor ) {
140+ return floorDiv (dividend , (long ) divisor );
141+ }
142+
138143 public static int floorMod (int dividend , int divisor ) {
139144 checkCriticalArithmetic (divisor != 0 );
140145 return ((dividend % divisor ) + divisor ) % divisor ;
@@ -145,11 +150,53 @@ public static long floorMod(long dividend, long divisor) {
145150 return ((dividend % divisor ) + divisor ) % divisor ;
146151 }
147152
148- public static double hypot (double x , double y ) {
149- return Double .isInfinite (x ) || Double .isInfinite (y ) ?
150- Double .POSITIVE_INFINITY : sqrt (x * x + y * y );
153+ public static long floorMod (long dividend , int divisor ) {
154+ return floorMod (dividend , (long ) divisor );
155+ }
156+
157+ @ SuppressWarnings ("CheckStyle.MethodName" )
158+ public static double IEEEremainder (double v , double m ) {
159+ double ratio = v / m ;
160+ double closest = Math .ceil (ratio );
161+ double frac = Math .abs (closest - ratio );
162+ if (frac > 0.5 || frac == 0.5 && (closest % 2 != 0 )) {
163+ closest = Math .floor (ratio );
164+ }
165+ // if closest == 0 and m == inf, avoid multiplication
166+ return closest == 0 ? v : v - m * closest ;
167+ }
168+
169+ public static int getExponent (double v ) {
170+ int [] intBits = JsUtils .doubleToRawIntBits (v );
171+ return ((intBits [1 ] >> 20 ) & 2047 ) - Double .MAX_EXPONENT ;
172+ }
173+
174+ public static int getExponent (float v ) {
175+ return ((JsUtils .floatToRawIntBits (v ) >> 23 ) & 255 ) - Float .MAX_EXPONENT ;
176+ }
177+
178+ public static double ulp (double v ) {
179+ if (!Double .isFinite (v )) {
180+ return Math .abs (v );
181+ }
182+ int exponent = Math .getExponent (v );
183+ if (exponent == -1023 ) {
184+ return Double .MIN_VALUE ;
185+ }
186+ return Math .pow (2 , exponent - 52 );
187+ }
188+
189+ public static float ulp (float v ) {
190+ int exponent = Math .getExponent (v );
191+ if (exponent == -Float .MAX_EXPONENT ) {
192+ return Float .MIN_VALUE ;
193+ }
194+ return (float ) Math .pow (2 , exponent - 23 );
151195 }
152196
197+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.hypot" )
198+ public static native double hypot (double x , double y );
199+
153200 public static int incrementExact (int x ) {
154201 checkCriticalArithmetic (x != Integer .MAX_VALUE );
155202 return x + 1 ;
@@ -163,13 +210,11 @@ public static long incrementExact(long x) {
163210 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.log" )
164211 public static native double log (double x );
165212
166- public static double log10 (double x ) {
167- return log (x ) * NativeMath .LOG10E ;
168- }
213+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.log10" )
214+ public static native double log10 (double x );
169215
170- public static double log1p (double x ) {
171- return x == 0 ? x : log (x + 1 );
172- }
216+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.log1p" )
217+ public static native double log1p (double x );
173218
174219 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.max" )
175220 public static native double max (double x , double y );
@@ -197,12 +242,28 @@ public static long min(long x, long y) {
197242 return x < y ? x : y ;
198243 }
199244
245+ public static long multiplyFull (int x , int y ) {
246+ return (long ) x * (long ) y ;
247+ }
248+
200249 public static int multiplyExact (int x , int y ) {
201250 double r = (double ) x * (double ) y ;
202251 checkCriticalArithmetic (isSafeIntegerRange (r ));
203252 return (int ) r ;
204253 }
205254
255+ public static long multiplyExact (long x , int y ) {
256+ if (y == -1 ) {
257+ return negateExact (x );
258+ }
259+ if (y == 0 ) {
260+ return 0 ;
261+ }
262+ long r = x * y ;
263+ checkCriticalArithmetic (r / y == x );
264+ return r ;
265+ }
266+
206267 public static long multiplyExact (long x , long y ) {
207268 if (y == -1 ) {
208269 return negateExact (x );
@@ -284,13 +345,8 @@ public static float scalb(float f, int scaleFactor) {
284345 return (float ) scalb ((double ) f , scaleFactor );
285346 }
286347
287- public static double signum (double d ) {
288- if (d == 0 || Double .isNaN (d )) {
289- return d ;
290- } else {
291- return d < 0 ? -1 : 1 ;
292- }
293- }
348+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.sign" )
349+ public static native double signum (double d );
294350
295351 public static float signum (float f ) {
296352 return (float ) signum ((double ) f );
@@ -299,28 +355,17 @@ public static float signum(float f) {
299355 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.sin" )
300356 public static native double sin (double x );
301357
302- public static double sinh (double x ) {
303- return x == 0.0 ? x : (exp (x ) - exp (-x )) / 2 ;
304- }
358+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.sinh" )
359+ public static native double sinh (double x );
305360
306361 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.sqrt" )
307362 public static native double sqrt (double x );
308363
309364 @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.tan" )
310365 public static native double tan (double x );
311366
312- public static double tanh (double x ) {
313- if (x == 0.0 ) {
314- // -0.0 should return -0.0.
315- return x ;
316- }
317-
318- double e2x = exp (2 * x );
319- if (Double .isInfinite (e2x )) {
320- return 1 ;
321- }
322- return (e2x - 1 ) / (e2x + 1 );
323- }
367+ @ JsMethod (namespace = JsPackage .GLOBAL , name = "Math.tanh" )
368+ public static native double tanh (double x );
324369
325370 public static double toDegrees (double x ) {
326371 return x * PI_UNDER_180 ;
@@ -411,7 +456,6 @@ private static boolean isSafeIntegerRange(double value) {
411456
412457 @ JsType (isNative = true , name = "Math" , namespace = JsPackage .GLOBAL )
413458 private static class NativeMath {
414- public static double LOG10E ;
415459 public static native double round (double x );
416460 }
417461}
0 commit comments