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 package sun.java2d.marlin;
  26 
  27 import jdk.internal.math.FloatConsts;
  28 
  29 /**
  30  * Faster Math ceil / floor routines derived from StrictMath
  31  */
  32 public final class FloatMath implements MarlinConst {
  33 
  34     // overflow / NaN handling enabled:
  35     static final boolean CHECK_OVERFLOW = true;
  36     static final boolean CHECK_NAN = true;
  37 
  38     private FloatMath() {
  39         // utility class
  40     }
  41 
  42     // faster inlined min/max functions in the branch prediction is high
  43     static float max(final float a, final float b) {
  44         // no NaN handling
  45         return (a >= b) ? a : b;
  46     }
  47 
  48     static int max(final int a, final int b) {
  49         return (a >= b) ? a : b;
  50     }
  51 
  52     static int min(final int a, final int b) {
  53         return (a <= b) ? a : b;
  54     }
  55 
  56     /**
  57      * Returns the smallest (closest to negative infinity) {@code float} value
  58      * that is greater than or equal to the argument and is equal to a
  59      * mathematical integer. Special cases:
  60      * <ul><li>If the argument value is already equal to a mathematical integer,
  61      * then the result is the same as the argument.  <li>If the argument is NaN
  62      * or an infinity or positive zero or negative zero, then the result is the
  63      * same as the argument.  <li>If the argument value is less than zero but
  64      * greater than -1.0, then the result is negative zero.</ul> Note that the
  65      * value of {@code StrictMath.ceil(x)} is exactly the value of
  66      * {@code -StrictMath.floor(-x)}.
  67      *
  68      * @param a a value.
  69      * @return the smallest (closest to negative infinity) floating-point value
  70      * that is greater than or equal to the argument and is equal to a
  71      * mathematical integer.
  72      */
  73     public static float ceil_f(final float a) {
  74         // Derived from StrictMath.ceil(double):
  75 
  76         // Inline call to Math.getExponent(a) to
  77         // compute only once Float.floatToRawIntBits(a)
  78         final int doppel = Float.floatToRawIntBits(a);
  79 
  80         final int exponent = ((doppel & FloatConsts.EXP_BIT_MASK)
  81                 >> (FloatConsts.SIGNIFICAND_WIDTH - 1))
  82                 - FloatConsts.EXP_BIAS;
  83 
  84         if (exponent < 0) {
  85             /*
  86              * Absolute value of argument is less than 1.
  87              * floorOrceil(-0.0) => -0.0
  88              * floorOrceil(+0.0) => +0.0
  89              */
  90             return ((a == 0) ? a :
  91                     ( (a < 0f) ? -0f : 1f) );
  92         }
  93         if (CHECK_OVERFLOW && (exponent >= 23)) { // 52 for double
  94             /*
  95              * Infinity, NaN, or a value so large it must be integral.
  96              */
  97             return a;
  98         }
  99         // Else the argument is either an integral value already XOR it
 100         // has to be rounded to one.
 101         assert exponent >= 0 && exponent <= 22; // 51 for double
 102 
 103         final int intpart = doppel
 104                 & (~(FloatConsts.SIGNIF_BIT_MASK >> exponent));
 105 
 106         if (intpart == doppel) {
 107             return a; // integral value (including 0)
 108         }
 109 
 110         // 0 handled above as an integer
 111         // sign: 1 for negative, 0 for positive numbers
 112         // add : 0 for negative and 1 for positive numbers
 113         return Float.intBitsToFloat(intpart) + ((~intpart) >>> 31);
 114     }
 115 
 116     /**
 117      * Returns the largest (closest to positive infinity) {@code float} value
 118      * that is less than or equal to the argument and is equal to a mathematical
 119      * integer. Special cases:
 120      * <ul><li>If the argument value is already equal to a mathematical integer,
 121      * then the result is the same as the argument.  <li>If the argument is NaN
 122      * or an infinity or positive zero or negative zero, then the result is the
 123      * same as the argument.</ul>
 124      *
 125      * @param a a value.
 126      * @return the largest (closest to positive infinity) floating-point value
 127      * that less than or equal to the argument and is equal to a mathematical
 128      * integer.
 129      */
 130     public static float floor_f(final float a) {
 131         // Derived from StrictMath.floor(double):
 132 
 133         // Inline call to Math.getExponent(a) to
 134         // compute only once Float.floatToRawIntBits(a)
 135         final int doppel = Float.floatToRawIntBits(a);
 136 
 137         final int exponent = ((doppel & FloatConsts.EXP_BIT_MASK)
 138                 >> (FloatConsts.SIGNIFICAND_WIDTH - 1))
 139                 - FloatConsts.EXP_BIAS;
 140 
 141         if (exponent < 0) {
 142             /*
 143              * Absolute value of argument is less than 1.
 144              * floorOrceil(-0.0) => -0.0
 145              * floorOrceil(+0.0) => +0.0
 146              */
 147             return ((a == 0) ? a :
 148                     ( (a < 0f) ? -1f : 0f) );
 149         }
 150         if (CHECK_OVERFLOW && (exponent >= 23)) { // 52 for double
 151             /*
 152              * Infinity, NaN, or a value so large it must be integral.
 153              */
 154             return a;
 155         }
 156         // Else the argument is either an integral value already XOR it
 157         // has to be rounded to one.
 158         assert exponent >= 0 && exponent <= 22; // 51 for double
 159 
 160         final int intpart = doppel
 161                 & (~(FloatConsts.SIGNIF_BIT_MASK >> exponent));
 162 
 163         if (intpart == doppel) {
 164             return a; // integral value (including 0)
 165         }
 166 
 167         // 0 handled above as an integer
 168         // sign: 1 for negative, 0 for positive numbers
 169         // add : -1 for negative and 0 for positive numbers
 170         return Float.intBitsToFloat(intpart) + (intpart >> 31);
 171     }
 172 
 173     /**
 174      * Faster alternative to ceil(float) optimized for the integer domain
 175      * and supporting NaN and +/-Infinity.
 176      *
 177      * @param a a value.
 178      * @return the largest (closest to positive infinity) integer value
 179      * that less than or equal to the argument and is equal to a mathematical
 180      * integer.
 181      */
 182     public static int ceil_int(final float a) {
 183         final int intpart = (int) a;
 184 
 185         if (a <= intpart
 186                 || (CHECK_OVERFLOW && intpart == Integer.MAX_VALUE)
 187                 || CHECK_NAN && Float.isNaN(a)) {
 188             return intpart;
 189         }
 190         return intpart + 1;
 191     }
 192 
 193     /**
 194      * Faster alternative to floor(float) optimized for the integer domain
 195      * and supporting NaN and +/-Infinity.
 196      *
 197      * @param a a value.
 198      * @return the largest (closest to positive infinity) floating-point value
 199      * that less than or equal to the argument and is equal to a mathematical
 200      * integer.
 201      */
 202     public static int floor_int(final float a) {
 203         final int intpart = (int) a;
 204 
 205         if (a >= intpart
 206                 || (CHECK_OVERFLOW && intpart == Integer.MIN_VALUE)
 207                 || CHECK_NAN && Float.isNaN(a)) {
 208             return intpart;
 209         }
 210         return intpart - 1;
 211     }
 212 }