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