• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkFloatBits.h"
2 #include "SkMath.h"
3 
4 /******************************************************************************
5     SkFloatBits_toInt[Floor, Round, Ceil] are identical except for what they
6     do right before they return ... >> exp;
7     Floor - adds nothing
8     Round - adds 1 << (exp - 1)
9     Ceil - adds (1 << exp) - 1
10 
11     Floor and Cast are very similar, but Cast applies its sign after all other
12     computations on value. Also, Cast does not need to check for negative zero,
13     as that value (0x80000000) "does the right thing" for Ceil. Note that it
14     doesn't for Floor/Round/Ceil, hence the explicit check.
15 ******************************************************************************/
16 
17 #define EXP_BIAS            (127+23)
18 #define MATISSA_MAGIC_BIG   (1 << 23)
19 
unpack_exp(uint32_t packed)20 static inline int unpack_exp(uint32_t packed) {
21     return (packed << 1 >> 24);
22 }
23 
24 #if 0
25 // the ARM compiler generates an extra BIC, so I use the dirty version instead
26 static inline int unpack_matissa(uint32_t packed) {
27     // we could mask with 0x7FFFFF, but that is harder for ARM to encode
28     return (packed & ~0xFF000000) | MATISSA_MAGIC_BIG;
29 }
30 #endif
31 
32 // returns the low 24-bits, so we need to OR in the magic_bit afterwards
unpack_matissa_dirty(uint32_t packed)33 static inline int unpack_matissa_dirty(uint32_t packed) {
34     return packed & ~0xFF000000;
35 }
36 
37 // same as (int)float
SkFloatBits_toIntCast(int32_t packed)38 int32_t SkFloatBits_toIntCast(int32_t packed) {
39     int exp = unpack_exp(packed) - EXP_BIAS;
40     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
41 
42     if (exp >= 0) {
43         if (exp > 7) {    // overflow
44             value = SK_MaxS32;
45         } else {
46             value <<= exp;
47         }
48     } else {
49         exp = -exp;
50         if (exp > 25) {   // underflow
51             exp = 25;
52         }
53         value >>= exp;
54     }
55     return SkApplySign(value, SkExtractSign(packed));
56 }
57 
58 // same as (int)floor(float)
SkFloatBits_toIntFloor(int32_t packed)59 int32_t SkFloatBits_toIntFloor(int32_t packed) {
60     // curse you negative 0
61     if ((packed << 1) == 0) {
62         return 0;
63     }
64 
65     int exp = unpack_exp(packed) - EXP_BIAS;
66     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
67 
68     if (exp >= 0) {
69         if (exp > 7) {    // overflow
70             value = SK_MaxS32;
71         } else {
72             value <<= exp;
73         }
74         // apply the sign after we check for overflow
75         return SkApplySign(value, SkExtractSign(packed));
76     } else {
77         // apply the sign before we right-shift
78         value = SkApplySign(value, SkExtractSign(packed));
79         exp = -exp;
80         if (exp > 25) {   // underflow
81             exp = 25;
82         }
83         // int add = 0;
84         return value >> exp;
85     }
86 }
87 
88 // same as (int)floor(float + 0.5)
SkFloatBits_toIntRound(int32_t packed)89 int32_t SkFloatBits_toIntRound(int32_t packed) {
90     // curse you negative 0
91     if ((packed << 1) == 0) {
92         return 0;
93     }
94 
95     int exp = unpack_exp(packed) - EXP_BIAS;
96     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
97 
98     if (exp >= 0) {
99         if (exp > 7) {    // overflow
100             value = SK_MaxS32;
101         } else {
102             value <<= exp;
103         }
104         // apply the sign after we check for overflow
105         return SkApplySign(value, SkExtractSign(packed));
106     } else {
107         // apply the sign before we right-shift
108         value = SkApplySign(value, SkExtractSign(packed));
109         exp = -exp;
110         if (exp > 25) {   // underflow
111             exp = 25;
112         }
113         int add = 1 << (exp - 1);
114         return (value + add) >> exp;
115     }
116 }
117 
118 // same as (int)ceil(float)
SkFloatBits_toIntCeil(int32_t packed)119 int32_t SkFloatBits_toIntCeil(int32_t packed) {
120     // curse you negative 0
121     if ((packed << 1) == 0) {
122         return 0;
123     }
124 
125     int exp = unpack_exp(packed) - EXP_BIAS;
126     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
127 
128     if (exp >= 0) {
129         if (exp > 7) {    // overflow
130             value = SK_MaxS32;
131         } else {
132             value <<= exp;
133         }
134         // apply the sign after we check for overflow
135         return SkApplySign(value, SkExtractSign(packed));
136     } else {
137         // apply the sign before we right-shift
138         value = SkApplySign(value, SkExtractSign(packed));
139         exp = -exp;
140         if (exp > 25) {   // underflow
141             exp = 25;
142         }
143         int add = (1 << exp) - 1;
144         return (value + add) >> exp;
145     }
146 }
147 
148 #ifdef SK_CAN_USE_FLOAT
149 
150 float SkFloatBits_intToFloatNative(int x);
SkFloatBits_intToFloatNative(int x)151 float SkFloatBits_intToFloatNative(int x) {
152     return x;
153 }
154 
SkIntToFloatCast(int32_t value)155 float SkIntToFloatCast(int32_t value) {
156     if (0 == value) {
157         return 0;
158     }
159 
160     int shift = EXP_BIAS;
161 
162     // record the sign and make value positive
163     int sign = SkExtractSign(value);
164     value = SkApplySign(value, sign);
165 
166     if (value >> 24) {    // value is too big (has more than 24 bits set)
167         int bias = 8 - SkCLZ(value);
168         SkDebugf("value = %d, bias = %d\n", value, bias);
169         SkASSERT(bias > 0 && bias < 8);
170         value >>= bias; // need to round?
171         shift += bias;
172     } else {
173         int zeros = SkCLZ(value << 8);
174         SkASSERT(zeros >= 0 && zeros <= 23);
175         value <<= zeros;
176         shift -= zeros;
177     }
178 
179     // now value is left-aligned to 24 bits
180     SkASSERT((value >> 23) == 1);
181     SkASSERT(shift >= 0 && shift <= 255);
182 
183     SkFloatIntUnion data;
184     data.fSignBitInt = (sign << 31) | (shift << 23) | (value & ~MATISSA_MAGIC_BIG);
185     return data.fFloat;
186 }
187 
SkIntToFloatCast_NoOverflowCheck(int32_t value)188 float SkIntToFloatCast_NoOverflowCheck(int32_t value) {
189     if (0 == value) {
190         return 0;
191     }
192 
193     int shift = EXP_BIAS;
194 
195     // record the sign and make value positive
196     int sign = SkExtractSign(value);
197     value = SkApplySign(value, sign);
198 
199     int zeros = SkCLZ(value << 8);
200     value <<= zeros;
201     shift -= zeros;
202 
203     SkFloatIntUnion data;
204     data.fSignBitInt = (sign << 31) | (shift << 23) | (value & ~MATISSA_MAGIC_BIG);
205     return data.fFloat;
206 }
207 
208 #endif
209