src/share/classes/java/lang/StrictMath.java
Print this page
@@ -24,10 +24,11 @@
*/
package java.lang;
import java.util.Random;
import sun.misc.FpUtils;
+import sun.misc.DoubleConsts;
/**
* The class {@code StrictMath} contains methods for performing basic
* numeric operations such as the elementary exponential, logarithm,
* square root, and trigonometric functions.
@@ -314,11 +315,13 @@
* @param a a value.
* @return the smallest (closest to negative infinity)
* floating-point value that is greater than or equal to
* the argument and is equal to a mathematical integer.
*/
- public static native double ceil(double a);
+ public static double ceil(double a) {
+ return floorOrCeil(a, -0.0, 1.0, 1.0);
+ }
/**
* Returns the largest (closest to positive infinity)
* {@code double} value that is less than or equal to the
* argument and is equal to a mathematical integer. Special cases:
@@ -331,11 +334,58 @@
* @param a a value.
* @return the largest (closest to positive infinity)
* floating-point value that less than or equal to the argument
* and is equal to a mathematical integer.
*/
- public static native double floor(double a);
+ public static double floor(double a) {
+ return floorOrCeil(a, -1.0, 0.0, -1.0);
+ }
+
+ /**
+ * Internal method to share logic between floor and ceil.
+ *
+ * @param a the value to be floored or ceiled
+ * @param negativeBoundary result for values in (-1, 0)
+ * @param positiveBoundary result for values in (0, 1)
+ * @param increment value to add when the argument is non-integral
+ */
+ private static double floorOrCeil(double a,
+ double negativeBoundary,
+ double positiveBoundary,
+ double sign) {
+ int exponent = Math.getExponent(a);
+
+ if (exponent < 0) {
+ /*
+ * Absolute value of argument is less than 1.
+ * floorOrceil(-0.0) => -0.0
+ * floorOrceil(+0.0) => +0.0
+ */
+ return ((a == 0.0) ? a :
+ ( (a < 0.0) ? negativeBoundary : positiveBoundary) );
+ } else if (exponent >= 52) {
+ /*
+ * Infinity, NaN, or a value so large it must be integral.
+ */
+ return a;
+ }
+ // Else the argument is either an integral value already XOR it
+ // has to be rounded to one.
+ assert exponent >= 0 && exponent <= 51;
+
+ long doppel = Double.doubleToRawLongBits(a);
+ long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+
+ if ( (mask & doppel) == 0L )
+ return a; // integral value
+ else {
+ double result = Double.longBitsToDouble(doppel & (~mask));
+ if (sign*a > 0.0)
+ result = result + sign;
+ return result;
+ }
+ }
/**
* Returns the {@code double} value that is closest in value
* to the argument and is equal to a mathematical integer. If two
* {@code double} values that are mathematical integers are