michael@0: michael@0: /* michael@0: * Copyright 2008 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #ifndef SkFloatBits_DEFINED michael@0: #define SkFloatBits_DEFINED michael@0: michael@0: #include "SkTypes.h" michael@0: michael@0: /** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement michael@0: int. This also converts -0 (0x80000000) to 0. Doing this to a float allows michael@0: it to be compared using normal C operators (<, <=, etc.) michael@0: */ michael@0: static inline int32_t SkSignBitTo2sCompliment(int32_t x) { michael@0: if (x < 0) { michael@0: x &= 0x7FFFFFFF; michael@0: x = -x; michael@0: } michael@0: return x; michael@0: } michael@0: michael@0: /** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float). michael@0: This undoes the result of SkSignBitTo2sCompliment(). michael@0: */ michael@0: static inline int32_t Sk2sComplimentToSignBit(int32_t x) { michael@0: int sign = x >> 31; michael@0: // make x positive michael@0: x = (x ^ sign) - sign; michael@0: // set the sign bit as needed michael@0: x |= sign << 31; michael@0: return x; michael@0: } michael@0: michael@0: /** Given the bit representation of a float, return its value cast to an int. michael@0: If the value is out of range, or NaN, return return +/- SK_MaxS32 michael@0: */ michael@0: int32_t SkFloatBits_toIntCast(int32_t floatBits); michael@0: michael@0: /** Given the bit representation of a float, return its floor as an int. michael@0: If the value is out of range, or NaN, return return +/- SK_MaxS32 michael@0: */ michael@0: SK_API int32_t SkFloatBits_toIntFloor(int32_t floatBits); michael@0: michael@0: /** Given the bit representation of a float, return it rounded to an int. michael@0: If the value is out of range, or NaN, return return +/- SK_MaxS32 michael@0: */ michael@0: SK_API int32_t SkFloatBits_toIntRound(int32_t floatBits); michael@0: michael@0: /** Given the bit representation of a float, return its ceiling as an int. michael@0: If the value is out of range, or NaN, return return +/- SK_MaxS32 michael@0: */ michael@0: SK_API int32_t SkFloatBits_toIntCeil(int32_t floatBits); michael@0: michael@0: michael@0: union SkFloatIntUnion { michael@0: float fFloat; michael@0: int32_t fSignBitInt; michael@0: }; michael@0: michael@0: // Helper to see a float as its bit pattern (w/o aliasing warnings) michael@0: static inline int32_t SkFloat2Bits(float x) { michael@0: SkFloatIntUnion data; michael@0: data.fFloat = x; michael@0: return data.fSignBitInt; michael@0: } michael@0: michael@0: // Helper to see a bit pattern as a float (w/o aliasing warnings) michael@0: static inline float SkBits2Float(int32_t floatAsBits) { michael@0: SkFloatIntUnion data; michael@0: data.fSignBitInt = floatAsBits; michael@0: return data.fFloat; michael@0: } michael@0: michael@0: /** Return the float as a 2s compliment int. Just to be used to compare floats michael@0: to each other or against positive float-bit-constants (like 0). This does michael@0: not return the int equivalent of the float, just something cheaper for michael@0: compares-only. michael@0: */ michael@0: static inline int32_t SkFloatAs2sCompliment(float x) { michael@0: return SkSignBitTo2sCompliment(SkFloat2Bits(x)); michael@0: } michael@0: michael@0: /** Return the 2s compliment int as a float. This undos the result of michael@0: SkFloatAs2sCompliment michael@0: */ michael@0: static inline float Sk2sComplimentAsFloat(int32_t x) { michael@0: return SkBits2Float(Sk2sComplimentToSignBit(x)); michael@0: } michael@0: michael@0: /** Return x cast to a float (i.e. (float)x) michael@0: */ michael@0: float SkIntToFloatCast(int x); michael@0: float SkIntToFloatCast_NoOverflowCheck(int x); michael@0: michael@0: /** Return the float cast to an int. michael@0: If the value is out of range, or NaN, return +/- SK_MaxS32 michael@0: */ michael@0: static inline int32_t SkFloatToIntCast(float x) { michael@0: return SkFloatBits_toIntCast(SkFloat2Bits(x)); michael@0: } michael@0: michael@0: /** Return the floor of the float as an int. michael@0: If the value is out of range, or NaN, return +/- SK_MaxS32 michael@0: */ michael@0: static inline int32_t SkFloatToIntFloor(float x) { michael@0: return SkFloatBits_toIntFloor(SkFloat2Bits(x)); michael@0: } michael@0: michael@0: /** Return the float rounded to an int. michael@0: If the value is out of range, or NaN, return +/- SK_MaxS32 michael@0: */ michael@0: static inline int32_t SkFloatToIntRound(float x) { michael@0: return SkFloatBits_toIntRound(SkFloat2Bits(x)); michael@0: } michael@0: michael@0: /** Return the ceiling of the float as an int. michael@0: If the value is out of range, or NaN, return +/- SK_MaxS32 michael@0: */ michael@0: static inline int32_t SkFloatToIntCeil(float x) { michael@0: return SkFloatBits_toIntCeil(SkFloat2Bits(x)); michael@0: } michael@0: michael@0: // Scalar wrappers for float-bit routines michael@0: michael@0: #define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x) michael@0: #define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x) michael@0: michael@0: #endif