Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: src/core/SkFloat.cpp

Issue 619563003: Archive SkFloat (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkFloat.h ('k') | src/core/SkGraphics.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
15 static int get_unsigned_exp(uint32_t packed)
16 {
17 return (packed << 1 >> 24);
18 }
19
20 static unsigned get_unsigned_value(uint32_t packed)
21 {
22 return (packed << 9 >> 9) | (1 << 23);
23 }
24
25 static int get_signed_value(int32_t packed)
26 {
27 return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed));
28 }
29
30 /////////////////////////////////////////////////////////////////////////
31
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
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
116 int32_t SkFloat::Neg(int32_t packed)
117 {
118 if (packed)
119 packed = packed ^ (1 << 31);
120 return packed;
121 }
122
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 static inline int32_t mul24(int32_t a, int32_t b) {
160 int64_t tmp = (sk_64_mul(a, b) + (1 << 23)) >> 24;
161 return sk_64_asS32(tmp);
162 }
163
164 int32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
165 {
166 if (packed_a == 0 || packed_b == 0)
167 return 0;
168
169 int exp_a = get_unsigned_exp(packed_a);
170 int exp_b = get_unsigned_exp(packed_b);
171
172 int value_a = get_signed_value(packed_a);
173 int value_b = get_signed_value(packed_b);
174
175 return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24);
176 }
177
178 int32_t SkFloat::MulInt(int32_t packed, int n)
179 {
180 return Mul(packed, SetShift(n, 0));
181 }
182
183 int32_t SkFloat::Div(int32_t packed_n, int32_t packed_d)
184 {
185 SkASSERT(packed_d != 0);
186
187 if (packed_n == 0)
188 return 0;
189
190 int exp_n = get_unsigned_exp(packed_n);
191 int exp_d = get_unsigned_exp(packed_d);
192
193 int value_n = get_signed_value(packed_n);
194 int value_d = get_signed_value(packed_d);
195
196 return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24 );
197 }
198
199 int32_t SkFloat::DivInt(int32_t packed, int n)
200 {
201 return Div(packed, SetShift(n, 0));
202 }
203
204 int32_t SkFloat::Invert(int32_t packed)
205 {
206 return Div(packed, SetShift(1, 0));
207 }
208
209 int32_t SkFloat::Sqrt(int32_t packed)
210 {
211 if (packed < 0)
212 {
213 SkDEBUGFAIL("can't sqrt a negative number");
214 return 0;
215 }
216
217 int exp = get_unsigned_exp(packed);
218 int value = get_unsigned_value(packed);
219
220 int nexp = exp - EXP_BIAS;
221 int root = SkSqrtBits(value << (nexp & 1), 26);
222 nexp >>= 1;
223 return SkFloat::SetShift(root, nexp - 11);
224 }
225
226 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : unreachable code
227 #pragma warning ( push )
228 #pragma warning ( disable : 4702 )
229 #endif
230
231 int32_t SkFloat::CubeRoot(int32_t packed)
232 {
233 sk_throw();
234 return 0;
235 }
236
237 #if defined _WIN32 && _MSC_VER >= 1300
238 #pragma warning ( pop )
239 #endif
240
241 static inline int32_t clear_high_bit(int32_t n)
242 {
243 return ((uint32_t)(n << 1)) >> 1;
244 }
245
246 static inline int int_sign(int32_t a, int32_t b)
247 {
248 return a > b ? 1 : (a < b ? -1 : 0);
249 }
250
251 int SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
252 {
253 packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a));
254 packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b));
255
256 return int_sign(packed_a, packed_b);
257 }
258
259 //////////////////////////////////////////////////////////////////////////////// /////
260 //////////////////////////////////////////////////////////////////////////////// /////
261
262 #ifdef SK_DEBUG
263
264 #include "SkRandom.h"
265 #include "SkFloatingPoint.h"
266
267 void SkFloat::UnitTest()
268 {
269 #if 0 // def SK_SUPPORT_UNITTEST
270 SkFloat a, b, c, d;
271 int n;
272
273 a.setZero();
274 n = a.getInt();
275 SkASSERT(n == 0);
276
277 b.setInt(5);
278 n = b.getInt();
279 SkASSERT(n == 5);
280
281 c.setInt(-3);
282 n = c.getInt();
283 SkASSERT(n == -3);
284
285 d.setAdd(c, b);
286 SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt());
287
288 SkRandom rand;
289
290 int i;
291 for (i = 0; i < 1000; i++)
292 {
293 float fa, fb;
294 int aa = rand.nextS() >> 14;
295 int bb = rand.nextS() >> 14;
296 a.setInt(aa);
297 b.setInt(bb);
298 SkASSERT(a.getInt() == aa);
299 SkASSERT(b.getInt() == bb);
300
301 c.setAdd(a, b);
302 int cc = c.getInt();
303 SkASSERT(cc == aa + bb);
304
305 c.setSub(a, b);
306 cc = c.getInt();
307 SkASSERT(cc == aa - bb);
308
309 aa >>= 5;
310 bb >>= 5;
311 a.setInt(aa);
312 b.setInt(bb);
313 c.setMul(a, b);
314 cc = c.getInt();
315 SkASSERT(cc == aa * bb);
316 /////////////////////////////////////
317
318 aa = rand.nextS() >> 11;
319 a.setFixed(aa);
320 cc = a.getFixed();
321 SkASSERT(aa == cc);
322
323 bb = rand.nextS() >> 11;
324 b.setFixed(bb);
325 cc = b.getFixed();
326 SkASSERT(bb == cc);
327
328 cc = SkFixedMul(aa, bb);
329 c.setMul(a, b);
330 SkFixed dd = c.getFixed();
331 int diff = cc - dd;
332 SkASSERT(SkAbs32(diff) <= 1);
333
334 fa = (float)aa / 65536.0f;
335 fb = (float)bb / 65536.0f;
336 a.assertEquals(fa);
337 b.assertEquals(fb);
338 fa = a.getFloat();
339 fb = b.getFloat();
340
341 c.assertEquals(fa * fb, 1);
342
343 c.setDiv(a, b);
344 cc = SkFixedDiv(aa, bb);
345 dd = c.getFixed();
346 diff = cc - dd;
347 SkASSERT(SkAbs32(diff) <= 3);
348
349 c.assertEquals(fa / fb, 1);
350
351 SkASSERT((aa == bb) == (a == b));
352 SkASSERT((aa != bb) == (a != b));
353 SkASSERT((aa < bb) == (a < b));
354 SkASSERT((aa <= bb) == (a <= b));
355 SkASSERT((aa > bb) == (a > b));
356 SkASSERT((aa >= bb) == (a >= b));
357
358 if (aa < 0)
359 {
360 aa = -aa;
361 fa = -fa;
362 }
363 a.setFixed(aa);
364 c.setSqrt(a);
365 cc = SkFixedSqrt(aa);
366 dd = c.getFixed();
367 SkASSERT(dd == cc);
368
369 c.assertEquals(sk_float_sqrt(fa), 2);
370
371 // cuberoot
372 #if 0
373 a.setInt(1);
374 a.cubeRoot();
375 a.assertEquals(1.0f, 0);
376 a.setInt(8);
377 a.cubeRoot();
378 a.assertEquals(2.0f, 0);
379 a.setInt(27);
380 a.cubeRoot();
381 a.assertEquals(3.0f, 0);
382 #endif
383 }
384 #endif
385 }
386
387 #endif
OLDNEW
« no previous file with comments | « src/core/SkFloat.h ('k') | src/core/SkGraphics.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698