1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkFloatBits_DEFINED 18 #define SkFloatBits_DEFINED 19 20 #include "SkTypes.h" 21 22 /** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement 23 int. This also converts -0 (0x80000000) to 0. Doing this to a float allows 24 it to be compared using normal C operators (<, <=, etc.) 25 */ 26 static inline int32_t SkSignBitTo2sCompliment(int32_t x) { 27 if (x < 0) { 28 x &= 0x7FFFFFFF; 29 x = -x; 30 } 31 return x; 32 } 33 34 /** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float). 35 This undoes the result of SkSignBitTo2sCompliment(). 36 */ 37 static inline int32_t Sk2sComplimentToSignBit(int32_t x) { 38 int sign = x >> 31; 39 // make x positive 40 x = (x ^ sign) - sign; 41 // set the sign bit as needed 42 x |= sign << 31; 43 return x; 44 } 45 46 /** Given the bit representation of a float, return its value cast to an int. 47 If the value is out of range, or NaN, return return +/- SK_MaxS32 48 */ 49 int32_t SkFloatBits_toIntCast(int32_t floatBits); 50 51 /** Given the bit representation of a float, return its floor as an int. 52 If the value is out of range, or NaN, return return +/- SK_MaxS32 53 */ 54 SK_API int32_t SkFloatBits_toIntFloor(int32_t floatBits); 55 56 /** Given the bit representation of a float, return it rounded to an int. 57 If the value is out of range, or NaN, return return +/- SK_MaxS32 58 */ 59 SK_API int32_t SkFloatBits_toIntRound(int32_t floatBits); 60 61 /** Given the bit representation of a float, return its ceiling as an int. 62 If the value is out of range, or NaN, return return +/- SK_MaxS32 63 */ 64 SK_API int32_t SkFloatBits_toIntCeil(int32_t floatBits); 65 66 67 #ifdef SK_CAN_USE_FLOAT 68 69 union SkFloatIntUnion { 70 float fFloat; 71 int32_t fSignBitInt; 72 }; 73 74 // Helper to see a float as its bit pattern (w/o aliasing warnings) 75 static inline int32_t SkFloat2Bits(float x) { 76 SkFloatIntUnion data; 77 data.fFloat = x; 78 return data.fSignBitInt; 79 } 80 81 // Helper to see a bit pattern as a float (w/o aliasing warnings) 82 static inline float SkBits2Float(int32_t floatAsBits) { 83 SkFloatIntUnion data; 84 data.fSignBitInt = floatAsBits; 85 return data.fFloat; 86 } 87 88 /** Return the float as a 2s compliment int. Just to be used to compare floats 89 to each other or against positive float-bit-constants (like 0). This does 90 not return the int equivalent of the float, just something cheaper for 91 compares-only. 92 */ 93 static inline int32_t SkFloatAs2sCompliment(float x) { 94 return SkSignBitTo2sCompliment(SkFloat2Bits(x)); 95 } 96 97 /** Return the 2s compliment int as a float. This undos the result of 98 SkFloatAs2sCompliment 99 */ 100 static inline float Sk2sComplimentAsFloat(int32_t x) { 101 return SkBits2Float(Sk2sComplimentToSignBit(x)); 102 } 103 104 /** Return x cast to a float (i.e. (float)x) 105 */ 106 float SkIntToFloatCast(int x); 107 float SkIntToFloatCast_NoOverflowCheck(int x); 108 109 /** Return the float cast to an int. 110 If the value is out of range, or NaN, return +/- SK_MaxS32 111 */ 112 static inline int32_t SkFloatToIntCast(float x) { 113 return SkFloatBits_toIntCast(SkFloat2Bits(x)); 114 } 115 116 /** Return the floor of the float as an int. 117 If the value is out of range, or NaN, return +/- SK_MaxS32 118 */ 119 static inline int32_t SkFloatToIntFloor(float x) { 120 return SkFloatBits_toIntFloor(SkFloat2Bits(x)); 121 } 122 123 /** Return the float rounded to an int. 124 If the value is out of range, or NaN, return +/- SK_MaxS32 125 */ 126 static inline int32_t SkFloatToIntRound(float x) { 127 return SkFloatBits_toIntRound(SkFloat2Bits(x)); 128 } 129 130 /** Return the ceiling of the float as an int. 131 If the value is out of range, or NaN, return +/- SK_MaxS32 132 */ 133 static inline int32_t SkFloatToIntCeil(float x) { 134 return SkFloatBits_toIntCeil(SkFloat2Bits(x)); 135 } 136 137 #endif 138 139 // Scalar wrappers for float-bit routines 140 141 #ifdef SK_SCALAR_IS_FLOAT 142 #define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x) 143 #define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x) 144 #else 145 #define SkScalarAs2sCompliment(x) (x) 146 #define Sk2sComplimentAsScalar(x) (x) 147 #endif 148 149 #endif 150 151