1 | /* |
2 | * Copyright 2008 The Android Open Source Project |
3 | * |
4 | * Use of this source code is governed by a BSD-style license that can be |
5 | * found in the LICENSE file. |
6 | */ |
7 | |
8 | #ifndef SkFloatBits_DEFINED |
9 | #define SkFloatBits_DEFINED |
10 | |
11 | #include "include/core/SkTypes.h" |
12 | #include "include/private/SkSafe_math.h" |
13 | |
14 | #include <float.h> |
15 | |
16 | /** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement |
17 | int. This also converts -0 (0x80000000) to 0. Doing this to a float allows |
18 | it to be compared using normal C operators (<, <=, etc.) |
19 | */ |
20 | static inline int32_t SkSignBitTo2sCompliment(int32_t x) { |
21 | if (x < 0) { |
22 | x &= 0x7FFFFFFF; |
23 | x = -x; |
24 | } |
25 | return x; |
26 | } |
27 | |
28 | /** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float). |
29 | This undoes the result of SkSignBitTo2sCompliment(). |
30 | */ |
31 | static inline int32_t Sk2sComplimentToSignBit(int32_t x) { |
32 | int sign = x >> 31; |
33 | // make x positive |
34 | x = (x ^ sign) - sign; |
35 | // set the sign bit as needed |
36 | x |= SkLeftShift(sign, 31); |
37 | return x; |
38 | } |
39 | |
40 | union SkFloatIntUnion { |
41 | float fFloat; |
42 | int32_t fSignBitInt; |
43 | }; |
44 | |
45 | // Helper to see a float as its bit pattern (w/o aliasing warnings) |
46 | static inline int32_t SkFloat2Bits(float x) { |
47 | SkFloatIntUnion data; |
48 | data.fFloat = x; |
49 | return data.fSignBitInt; |
50 | } |
51 | |
52 | // Helper to see a bit pattern as a float (w/o aliasing warnings) |
53 | static inline float SkBits2Float(int32_t floatAsBits) { |
54 | SkFloatIntUnion data; |
55 | data.fSignBitInt = floatAsBits; |
56 | return data.fFloat; |
57 | } |
58 | |
59 | constexpr int32_t gFloatBits_exponent_mask = 0x7F800000; |
60 | constexpr int32_t gFloatBits_matissa_mask = 0x007FFFFF; |
61 | |
62 | static inline bool SkFloatBits_IsFinite(int32_t bits) { |
63 | return (bits & gFloatBits_exponent_mask) != gFloatBits_exponent_mask; |
64 | } |
65 | |
66 | static inline bool SkFloatBits_IsInf(int32_t bits) { |
67 | return ((bits & gFloatBits_exponent_mask) == gFloatBits_exponent_mask) && |
68 | (bits & gFloatBits_matissa_mask) == 0; |
69 | } |
70 | |
71 | /** Return the float as a 2s compliment int. Just to be used to compare floats |
72 | to each other or against positive float-bit-constants (like 0). This does |
73 | not return the int equivalent of the float, just something cheaper for |
74 | compares-only. |
75 | */ |
76 | static inline int32_t SkFloatAs2sCompliment(float x) { |
77 | return SkSignBitTo2sCompliment(SkFloat2Bits(x)); |
78 | } |
79 | |
80 | /** Return the 2s compliment int as a float. This undos the result of |
81 | SkFloatAs2sCompliment |
82 | */ |
83 | static inline float Sk2sComplimentAsFloat(int32_t x) { |
84 | return SkBits2Float(Sk2sComplimentToSignBit(x)); |
85 | } |
86 | |
87 | // Scalar wrappers for float-bit routines |
88 | |
89 | #define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x) |
90 | |
91 | #endif |
92 | |