1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.marlin;
  27 
  28 /**
  29  * Faster Math ceil / floor routines derived from StrictMath
  30  */
  31 public final class FloatMath implements MarlinConst {
  32 
  33     // overflow / NaN handling enabled:
  34     static final boolean CHECK_OVERFLOW = true;
  35     static final boolean CHECK_NAN = true;
  36     // Copied from sun.misc.FloatConsts:
  37     public static final int FLOAT_SIGNIFICAND_WIDTH = 24;   // sun.misc.FloatConsts.SIGNIFICAND_WIDTH
  38     public static final int FLOAT_EXP_BIAS = 127;           // sun.misc.FloatConsts.EXP_BIAS
  39     public static final int FLOAT_EXP_BIT_MASK = 2139095040;// sun.misc.FloatConsts.EXP_BIT_MASK
  40     public static final int FLOAT_SIGNIF_BIT_MASK = 8388607;// sun.misc.FloatConsts.SIGNIF_BIT_MASK
  41 
  42     private FloatMath() {
  43         // utility class
  44     }
  45 
  46     // faster inlined min/max functions in the branch prediction is high
  47     static int max(final int a, final int b) {
  48         return (a >= b) ? a : b;
  49     }
  50 
  51     static int min(final int a, final int b) {
  52         return (a <= b) ? a : b;
  53     }
  54 
  55     /**
  56      * Returns the smallest (closest to negative infinity) {@code float} value
  57      * that is greater than or equal to the argument and is equal to a
  58      * mathematical integer. Special cases:
  59      * <ul><li>If the argument value is already equal to a mathematical integer,
  60      * then the result is the same as the argument.  <li>If the argument is NaN
  61      * or an infinity or positive zero or negative zero, then the result is the
  62      * same as the argument.  <li>If the argument value is less than zero but
  63      * greater than -1.0, then the result is negative zero.</ul> Note that the
  64      * value of {@code StrictMath.ceil(x)} is exactly the value of
  65      * {@code -StrictMath.floor(-x)}.
  66      *
  67      * @param a a value.
  68      * @return the smallest (closest to negative infinity) floating-point value
  69      * that is greater than or equal to the argument and is equal to a
  70      * mathematical integer.
  71      */
  72     public static float ceil_f(final float a) {
  73         // Derived from StrictMath.ceil(double):
  74 
  75         // Inline call to Math.getExponent(a) to
  76         // compute only once Float.floatToRawIntBits(a)
  77         final int doppel = Float.floatToRawIntBits(a);
  78 
  79         final int exponent = ((doppel & FLOAT_EXP_BIT_MASK)
  80                 >> (FLOAT_SIGNIFICAND_WIDTH - 1))
  81                 - FLOAT_EXP_BIAS;
  82 
  83         if (exponent < 0) {
  84             /*
  85              * Absolute value of argument is less than 1.
  86              * floorOrceil(-0.0) => -0.0
  87              * floorOrceil(+0.0) => +0.0
  88              */
  89             return ((a == 0.0f) ? a :
  90                     ( (a < 0.0f) ? -0.0f : 1.0f) );
  91         }
  92         if (CHECK_OVERFLOW && (exponent >= 23)) { // 52 for double
  93             /*
  94              * Infinity, NaN, or a value so large it must be integral.
  95              */
  96             return a;
  97         }
  98         // Else the argument is either an integral value already XOR it
  99         // has to be rounded to one.
 100         assert exponent >= 0 && exponent <= 22; // 51 for double
 101 
 102         final int intpart = doppel
 103                 & (~(FLOAT_SIGNIF_BIT_MASK >> exponent));
 104 
 105         if (intpart == doppel) {
 106             return a; // integral value (including 0)
 107         }
 108 
 109         // 0 handled above as an integer
 110         // sign: 1 for negative, 0 for positive numbers
 111         // add : 0 for negative and 1 for positive numbers
 112         return Float.intBitsToFloat(intpart) + ((~intpart) >>> 31);
 113     }
 114 
 115     /**
 116      * Returns the largest (closest to positive infinity) {@code float} value
 117      * that is less than or equal to the argument and is equal to a mathematical
 118      * integer. Special cases:
 119      * <ul><li>If the argument value is already equal to a mathematical integer,
 120      * then the result is the same as the argument.  <li>If the argument is NaN
 121      * or an infinity or positive zero or negative zero, then the result is the
 122      * same as the argument.</ul>
 123      *
 124      * @param a a value.
 125      * @return the largest (closest to positive infinity) floating-point value
 126      * that less than or equal to the argument and is equal to a mathematical
 127      * integer.
 128      */
 129     public static float floor_f(final float a) {
 130         // Derived from StrictMath.floor(double):
 131 
 132         // Inline call to Math.getExponent(a) to
 133         // compute only once Float.floatToRawIntBits(a)
 134         final int doppel = Float.floatToRawIntBits(a);
 135 
 136         final int exponent = ((doppel & FLOAT_EXP_BIT_MASK)
 137                 >> (FLOAT_SIGNIFICAND_WIDTH - 1))
 138                 - FLOAT_EXP_BIAS;
 139 
 140         if (exponent < 0) {
 141             /*
 142              * Absolute value of argument is less than 1.
 143              * floorOrceil(-0.0) => -0.0
 144              * floorOrceil(+0.0) => +0.0
 145              */
 146             return ((a == 0.0f) ? a :
 147                     ( (a < 0.0f) ? -1.0f : 0.0f) );
 148         }
 149         if (CHECK_OVERFLOW && (exponent >= 23)) { // 52 for double
 150             /*
 151              * Infinity, NaN, or a value so large it must be integral.
 152              */
 153             return a;
 154         }
 155         // Else the argument is either an integral value already XOR it
 156         // has to be rounded to one.
 157         assert exponent >= 0 && exponent <= 22; // 51 for double
 158 
 159         final int intpart = doppel
 160                 & (~(FLOAT_SIGNIF_BIT_MASK >> exponent));
 161 
 162         if (intpart == doppel) {
 163             return a; // integral value (including 0)
 164         }
 165 
 166         // 0 handled above as an integer
 167         // sign: 1 for negative, 0 for positive numbers
 168         // add : -1 for negative and 0 for positive numbers
 169         return Float.intBitsToFloat(intpart) + (intpart >> 31);
 170     }
 171 
 172     /**
 173      * Faster alternative to ceil(float) optimized for the integer domain
 174      * and supporting NaN and +/-Infinity.
 175      *
 176      * @param a a value.
 177      * @return the largest (closest to positive infinity) integer value
 178      * that less than or equal to the argument and is equal to a mathematical
 179      * integer.
 180      */
 181     public static int ceil_int(final float a) {
 182         final int intpart = (int) a;
 183 
 184         if (a <= intpart
 185                 || (CHECK_OVERFLOW && intpart == Integer.MAX_VALUE)
 186                 || CHECK_NAN && Float.isNaN(a)) {
 187             return intpart;
 188         }
 189         return intpart + 1;
 190     }
 191 
 192     /**
 193      * Faster alternative to ceil(double) optimized for the integer domain
 194      * and supporting NaN and +/-Infinity.
 195      *
 196      * @param a a value.
 197      * @return the largest (closest to positive infinity) integer value
 198      * that less than or equal to the argument and is equal to a mathematical
 199      * integer.
 200      */
 201     public static int ceil_int(final double a) {
 202         final int intpart = (int) a;
 203 
 204         if (a <= intpart
 205                 || (CHECK_OVERFLOW && intpart == Integer.MAX_VALUE)
 206                 || CHECK_NAN && Double.isNaN(a)) {
 207             return intpart;
 208         }
 209         return intpart + 1;
 210     }
 211 
 212     /**
 213      * Faster alternative to floor(float) optimized for the integer domain
 214      * and supporting NaN and +/-Infinity.
 215      *
 216      * @param a a value.
 217      * @return the largest (closest to positive infinity) floating-point value
 218      * that less than or equal to the argument and is equal to a mathematical
 219      * integer.
 220      */
 221     public static int floor_int(final float a) {
 222         final int intpart = (int) a;
 223 
 224         if (a >= intpart
 225                 || (CHECK_OVERFLOW && intpart == Integer.MIN_VALUE)
 226                 || CHECK_NAN && Float.isNaN(a)) {
 227             return intpart;
 228         }
 229         return intpart - 1;
 230     }
 231 
 232     /**
 233      * Faster alternative to floor(double) optimized for the integer domain
 234      * and supporting NaN and +/-Infinity.
 235      *
 236      * @param a a value.
 237      * @return the largest (closest to positive infinity) floating-point value
 238      * that less than or equal to the argument and is equal to a mathematical
 239      * integer.
 240      */
 241     public static int floor_int(final double a) {
 242         final int intpart = (int) a;
 243 
 244         if (a >= intpart
 245                 || (CHECK_OVERFLOW && intpart == Integer.MIN_VALUE)
 246                 || CHECK_NAN && Double.isNaN(a)) {
 247             return intpart;
 248         }
 249         return intpart - 1;
 250     }
 251 }