• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2008 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkFloat.h"
11 #include "SkMathPriv.h"
12 
13 #define EXP_BIAS    (127+23)
14 
get_unsigned_exp(uint32_t packed)15 static int get_unsigned_exp(uint32_t packed)
16 {
17     return (packed << 1 >> 24);
18 }
19 
get_unsigned_value(uint32_t packed)20 static unsigned get_unsigned_value(uint32_t packed)
21 {
22     return (packed << 9 >> 9) | (1 << 23);
23 }
24 
get_signed_value(int32_t packed)25 static int get_signed_value(int32_t packed)
26 {
27     return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed));
28 }
29 
30 /////////////////////////////////////////////////////////////////////////
31 
GetShift(int32_t packed,int shift)32 int SkFloat::GetShift(int32_t packed, int shift)
33 {
34     if (packed == 0)
35         return 0;
36 
37     int exp = get_unsigned_exp(packed) - EXP_BIAS - shift;
38     int value = get_unsigned_value(packed);
39 
40     if (exp >= 0)
41     {
42         if (exp > 8)    // overflow
43             value = SK_MaxS32;
44         else
45             value <<= exp;
46     }
47     else
48     {
49         exp = -exp;
50         if (exp > 23)   // underflow
51             value = 0;
52         else
53             value >>= exp;
54     }
55     return SkApplySign(value, SkExtractSign(packed));
56 }
57 
58 /////////////////////////////////////////////////////////////////////////////////////
59 
SetShift(int value,int shift)60 int32_t SkFloat::SetShift(int value, int shift)
61 {
62     if (value == 0)
63         return 0;
64 
65     // record the sign and make value positive
66     int sign = SkExtractSign(value);
67     value = SkApplySign(value, sign);
68 
69     if (value >> 24)    // value is too big (has more than 24 bits set)
70     {
71         int bias = 8 - SkCLZ(value);
72         SkASSERT(bias > 0 && bias < 8);
73         value >>= bias;
74         shift += bias;
75     }
76     else
77     {
78         int zeros = SkCLZ(value << 8);
79         SkASSERT(zeros >= 0 && zeros <= 23);
80         value <<= zeros;
81         shift -= zeros;
82     }
83     // now value is left-aligned to 24 bits
84     SkASSERT((value >> 23) == 1);
85 
86     shift += EXP_BIAS;
87     if (shift < 0)  // underflow
88         return 0;
89     else
90     {
91         if (shift > 255)    // overflow
92         {
93             shift = 255;
94             value = 0x00FFFFFF;
95         }
96         int32_t packed = sign << 31;        // set the sign-bit
97         packed |= shift << 23;          // store the packed exponent
98         packed |= ((unsigned)(value << 9) >> 9);    // clear 24th bit of value (its implied)
99 
100 #ifdef SK_DEBUG
101         {
102             int n;
103 
104             n = SkExtractSign(packed);
105             SkASSERT(n == sign);
106             n = get_unsigned_exp(packed);
107             SkASSERT(n == shift);
108             n = get_unsigned_value(packed);
109             SkASSERT(n == value);
110         }
111 #endif
112         return packed;
113     }
114 }
115 
Neg(int32_t packed)116 int32_t SkFloat::Neg(int32_t packed)
117 {
118     if (packed)
119         packed = packed ^ (1 << 31);
120     return packed;
121 }
122 
Add(int32_t packed_a,int32_t packed_b)123 int32_t SkFloat::Add(int32_t packed_a, int32_t packed_b)
124 {
125     if (packed_a == 0)
126         return packed_b;
127     if (packed_b == 0)
128         return packed_a;
129 
130     int exp_a = get_unsigned_exp(packed_a);
131     int exp_b = get_unsigned_exp(packed_b);
132     int exp_diff = exp_a - exp_b;
133 
134     int shift_a = 0, shift_b = 0;
135     int exp;
136 
137     if (exp_diff >= 0)
138     {
139         if (exp_diff > 24)  // B is too small to contribute
140             return packed_a;
141         shift_b = exp_diff;
142         exp = exp_a;
143     }
144     else
145     {
146         exp_diff = -exp_diff;
147         if (exp_diff > 24)  // A is too small to contribute
148             return packed_b;
149         shift_a = exp_diff;
150         exp = exp_b;
151     }
152 
153     int value_a = get_signed_value(packed_a) >> shift_a;
154     int value_b = get_signed_value(packed_b) >> shift_b;
155 
156     return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS);
157 }
158 
159 #include "Sk64.h"
160 
mul24(int32_t a,int32_t b)161 static inline int32_t mul24(int32_t a, int32_t b)
162 {
163     Sk64 tmp;
164 
165     tmp.setMul(a, b);
166     tmp.roundRight(24);
167     return tmp.get32();
168 }
169 
Mul(int32_t packed_a,int32_t packed_b)170 int32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
171 {
172     if (packed_a == 0 || packed_b == 0)
173         return 0;
174 
175     int exp_a = get_unsigned_exp(packed_a);
176     int exp_b = get_unsigned_exp(packed_b);
177 
178     int value_a = get_signed_value(packed_a);
179     int value_b = get_signed_value(packed_b);
180 
181     return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24);
182 }
183 
MulInt(int32_t packed,int n)184 int32_t SkFloat::MulInt(int32_t packed, int n)
185 {
186     return Mul(packed, SetShift(n, 0));
187 }
188 
Div(int32_t packed_n,int32_t packed_d)189 int32_t SkFloat::Div(int32_t packed_n, int32_t packed_d)
190 {
191     SkASSERT(packed_d != 0);
192 
193     if (packed_n == 0)
194         return 0;
195 
196     int exp_n = get_unsigned_exp(packed_n);
197     int exp_d = get_unsigned_exp(packed_d);
198 
199     int value_n = get_signed_value(packed_n);
200     int value_d = get_signed_value(packed_d);
201 
202     return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24);
203 }
204 
DivInt(int32_t packed,int n)205 int32_t SkFloat::DivInt(int32_t packed, int n)
206 {
207     return Div(packed, SetShift(n, 0));
208 }
209 
Invert(int32_t packed)210 int32_t SkFloat::Invert(int32_t packed)
211 {
212     return Div(packed, SetShift(1, 0));
213 }
214 
Sqrt(int32_t packed)215 int32_t SkFloat::Sqrt(int32_t packed)
216 {
217     if (packed < 0)
218     {
219         SkDEBUGFAIL("can't sqrt a negative number");
220         return 0;
221     }
222 
223     int exp = get_unsigned_exp(packed);
224     int value = get_unsigned_value(packed);
225 
226     int nexp = exp - EXP_BIAS;
227     int root = SkSqrtBits(value << (nexp & 1), 26);
228     nexp >>= 1;
229     return SkFloat::SetShift(root, nexp - 11);
230 }
231 
232 #if defined _WIN32 && _MSC_VER >= 1300  // disable warning : unreachable code
233 #pragma warning ( push )
234 #pragma warning ( disable : 4702 )
235 #endif
236 
CubeRoot(int32_t packed)237 int32_t SkFloat::CubeRoot(int32_t packed)
238 {
239     sk_throw();
240     return 0;
241 }
242 
243 #if defined _WIN32 && _MSC_VER >= 1300
244 #pragma warning ( pop )
245 #endif
246 
clear_high_bit(int32_t n)247 static inline int32_t clear_high_bit(int32_t n)
248 {
249     return ((uint32_t)(n << 1)) >> 1;
250 }
251 
int_sign(int32_t a,int32_t b)252 static inline int int_sign(int32_t a, int32_t b)
253 {
254     return a > b ? 1 : (a < b ? -1 : 0);
255 }
256 
Cmp(int32_t packed_a,int32_t packed_b)257 int SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
258 {
259     packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a));
260     packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b));
261 
262     return int_sign(packed_a, packed_b);
263 }
264 
265 /////////////////////////////////////////////////////////////////////////////////////
266 /////////////////////////////////////////////////////////////////////////////////////
267 
268 #ifdef SK_DEBUG
269 
270 #include "SkRandom.h"
271 #include "SkFloatingPoint.h"
272 
UnitTest()273 void SkFloat::UnitTest()
274 {
275 #ifdef SK_SUPPORT_UNITTEST
276     SkFloat a, b, c, d;
277     int     n;
278 
279     a.setZero();
280     n = a.getInt();
281     SkASSERT(n == 0);
282 
283     b.setInt(5);
284     n = b.getInt();
285     SkASSERT(n == 5);
286 
287     c.setInt(-3);
288     n = c.getInt();
289     SkASSERT(n == -3);
290 
291     d.setAdd(c, b);
292     SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt());
293 
294     SkRandom    rand;
295 
296     int i;
297     for (i = 0; i < 1000; i++)
298     {
299         float fa, fb;
300         int aa = rand.nextS() >> 14;
301         int bb = rand.nextS() >> 14;
302         a.setInt(aa);
303         b.setInt(bb);
304         SkASSERT(a.getInt() == aa);
305         SkASSERT(b.getInt() == bb);
306 
307         c.setAdd(a, b);
308         int cc = c.getInt();
309         SkASSERT(cc == aa + bb);
310 
311         c.setSub(a, b);
312         cc = c.getInt();
313         SkASSERT(cc == aa - bb);
314 
315         aa >>= 5;
316         bb >>= 5;
317         a.setInt(aa);
318         b.setInt(bb);
319         c.setMul(a, b);
320         cc = c.getInt();
321         SkASSERT(cc == aa * bb);
322         /////////////////////////////////////
323 
324         aa = rand.nextS() >> 11;
325         a.setFixed(aa);
326         cc = a.getFixed();
327         SkASSERT(aa == cc);
328 
329         bb = rand.nextS() >> 11;
330         b.setFixed(bb);
331         cc = b.getFixed();
332         SkASSERT(bb == cc);
333 
334         cc = SkFixedMul(aa, bb);
335         c.setMul(a, b);
336         SkFixed dd = c.getFixed();
337         int diff = cc - dd;
338         SkASSERT(SkAbs32(diff) <= 1);
339 
340         fa = (float)aa / 65536.0f;
341         fb = (float)bb / 65536.0f;
342         a.assertEquals(fa);
343         b.assertEquals(fb);
344         fa = a.getFloat();
345         fb = b.getFloat();
346 
347         c.assertEquals(fa * fb, 1);
348 
349         c.setDiv(a, b);
350         cc = SkFixedDiv(aa, bb);
351         dd = c.getFixed();
352         diff = cc - dd;
353         SkASSERT(SkAbs32(diff) <= 3);
354 
355         c.assertEquals(fa / fb, 1);
356 
357         SkASSERT((aa == bb) == (a == b));
358         SkASSERT((aa != bb) == (a != b));
359         SkASSERT((aa < bb) == (a < b));
360         SkASSERT((aa <= bb) == (a <= b));
361         SkASSERT((aa > bb) == (a > b));
362         SkASSERT((aa >= bb) == (a >= b));
363 
364         if (aa < 0)
365         {
366             aa = -aa;
367             fa = -fa;
368         }
369         a.setFixed(aa);
370         c.setSqrt(a);
371         cc = SkFixedSqrt(aa);
372         dd = c.getFixed();
373         SkASSERT(dd == cc);
374 
375         c.assertEquals(sk_float_sqrt(fa), 2);
376 
377         // cuberoot
378 #if 0
379         a.setInt(1);
380         a.cubeRoot();
381         a.assertEquals(1.0f, 0);
382         a.setInt(8);
383         a.cubeRoot();
384         a.assertEquals(2.0f, 0);
385         a.setInt(27);
386         a.cubeRoot();
387         a.assertEquals(3.0f, 0);
388 #endif
389     }
390 #endif
391 }
392 
393 #endif
394