Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. |
||
4 | * All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the |
||
8 | * "Software"), to deal in the Software without restriction, including |
||
9 | * without limitation the rights to use, copy, modify, merge, publish, |
||
10 | * distribute, sub license, and/or sell copies of the Software, and to |
||
11 | * permit persons to whom the Software is furnished to do so, subject to |
||
12 | * the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice (including the |
||
15 | * next paragraph) shall be included in all copies or substantial portions |
||
16 | * of the Software. |
||
17 | * |
||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
||
21 | * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR |
||
22 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||
23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||
24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | * |
||
26 | **************************************************************************/ |
||
27 | |||
28 | |||
29 | /** |
||
30 | * Math utilities and approximations for common math functions. |
||
31 | * Reduced precision is usually acceptable in shaders... |
||
32 | * |
||
33 | * "fast" is used in the names of functions which are low-precision, |
||
34 | * or at least lower-precision than the normal C lib functions. |
||
35 | */ |
||
36 | |||
37 | |||
38 | #ifndef U_MATH_H |
||
39 | #define U_MATH_H |
||
40 | |||
41 | |||
42 | #include "pipe/p_compiler.h" |
||
43 | |||
44 | |||
45 | #ifdef __cplusplus |
||
46 | extern "C" { |
||
47 | #endif |
||
48 | |||
49 | |||
50 | #include |
||
51 | #include |
||
52 | |||
53 | #ifdef PIPE_OS_UNIX |
||
54 | #include |
||
55 | #endif |
||
56 | |||
57 | |||
58 | #ifndef M_SQRT2 |
||
59 | #define M_SQRT2 1.41421356237309504880 |
||
60 | #endif |
||
61 | |||
62 | |||
63 | #if defined(_MSC_VER) |
||
64 | |||
65 | #if _MSC_VER < 1400 && !defined(__cplusplus) |
||
66 | |||
67 | static INLINE float cosf( float f ) |
||
68 | { |
||
69 | return (float) cos( (double) f ); |
||
70 | } |
||
71 | |||
72 | static INLINE float sinf( float f ) |
||
73 | { |
||
74 | return (float) sin( (double) f ); |
||
75 | } |
||
76 | |||
77 | static INLINE float ceilf( float f ) |
||
78 | { |
||
79 | return (float) ceil( (double) f ); |
||
80 | } |
||
81 | |||
82 | static INLINE float floorf( float f ) |
||
83 | { |
||
84 | return (float) floor( (double) f ); |
||
85 | } |
||
86 | |||
87 | static INLINE float powf( float f, float g ) |
||
88 | { |
||
89 | return (float) pow( (double) f, (double) g ); |
||
90 | } |
||
91 | |||
92 | static INLINE float sqrtf( float f ) |
||
93 | { |
||
94 | return (float) sqrt( (double) f ); |
||
95 | } |
||
96 | |||
97 | static INLINE float fabsf( float f ) |
||
98 | { |
||
99 | return (float) fabs( (double) f ); |
||
100 | } |
||
101 | |||
102 | static INLINE float logf( float f ) |
||
103 | { |
||
104 | return (float) log( (double) f ); |
||
105 | } |
||
106 | |||
107 | #else |
||
108 | /* Work-around an extra semi-colon in VS 2005 logf definition */ |
||
109 | #ifdef logf |
||
110 | #undef logf |
||
111 | #define logf(x) ((float)log((double)(x))) |
||
112 | #endif /* logf */ |
||
113 | |||
114 | #define isfinite(x) _finite((double)(x)) |
||
115 | #define isnan(x) _isnan((double)(x)) |
||
116 | #endif /* _MSC_VER < 1400 && !defined(__cplusplus) */ |
||
117 | |||
118 | static INLINE double log2( double x ) |
||
119 | { |
||
120 | const double invln2 = 1.442695041; |
||
121 | return log( x ) * invln2; |
||
122 | } |
||
123 | |||
124 | static INLINE double |
||
125 | round(double x) |
||
126 | { |
||
127 | return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5); |
||
128 | } |
||
129 | |||
130 | static INLINE float |
||
131 | roundf(float x) |
||
132 | { |
||
133 | return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); |
||
134 | } |
||
135 | |||
136 | #endif /* _MSC_VER */ |
||
137 | |||
138 | |||
139 | #ifdef PIPE_OS_ANDROID |
||
140 | |||
141 | static INLINE |
||
142 | double log2(double d) |
||
143 | { |
||
144 | return log(d) * (1.0 / M_LN2); |
||
145 | } |
||
146 | |||
147 | /* workaround a conflict with main/imports.h */ |
||
148 | #ifdef log2f |
||
149 | #undef log2f |
||
150 | #endif |
||
151 | |||
152 | static INLINE |
||
153 | float log2f(float f) |
||
154 | { |
||
155 | return logf(f) * (float) (1.0 / M_LN2); |
||
156 | } |
||
157 | |||
158 | #endif |
||
159 | |||
160 | |||
161 | |||
162 | |||
163 | #define POW2_TABLE_SIZE_LOG2 9 |
||
164 | #define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2) |
||
165 | #define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2) |
||
166 | #define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2)) |
||
167 | extern float pow2_table[POW2_TABLE_SIZE]; |
||
168 | |||
169 | |||
170 | /** |
||
171 | * Initialize math module. This should be called before using any |
||
172 | * other functions in this module. |
||
173 | */ |
||
174 | extern void |
||
175 | util_init_math(void); |
||
176 | |||
177 | |||
178 | union fi { |
||
179 | float f; |
||
180 | int32_t i; |
||
181 | uint32_t ui; |
||
182 | }; |
||
183 | |||
184 | |||
185 | union di { |
||
186 | double d; |
||
187 | int64_t i; |
||
188 | uint64_t ui; |
||
189 | }; |
||
190 | |||
191 | |||
192 | /** |
||
193 | * Fast version of 2^x |
||
194 | * Identity: exp2(a + b) = exp2(a) * exp2(b) |
||
195 | * Let ipart = int(x) |
||
196 | * Let fpart = x - ipart; |
||
197 | * So, exp2(x) = exp2(ipart) * exp2(fpart) |
||
198 | * Compute exp2(ipart) with i << ipart |
||
199 | * Compute exp2(fpart) with lookup table. |
||
200 | */ |
||
201 | static INLINE float |
||
202 | util_fast_exp2(float x) |
||
203 | { |
||
204 | int32_t ipart; |
||
205 | float fpart, mpart; |
||
206 | union fi epart; |
||
207 | |||
208 | if(x > 129.00000f) |
||
209 | return 3.402823466e+38f; |
||
210 | |||
211 | if (x < -126.99999f) |
||
212 | return 0.0f; |
||
213 | |||
214 | ipart = (int32_t) x; |
||
215 | fpart = x - (float) ipart; |
||
216 | |||
217 | /* same as |
||
218 | * epart.f = (float) (1 << ipart) |
||
219 | * but faster and without integer overflow for ipart > 31 |
||
220 | */ |
||
221 | epart.i = (ipart + 127 ) << 23; |
||
222 | |||
223 | mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)]; |
||
224 | |||
225 | return epart.f * mpart; |
||
226 | } |
||
227 | |||
228 | |||
229 | /** |
||
230 | * Fast approximation to exp(x). |
||
231 | */ |
||
232 | static INLINE float |
||
233 | util_fast_exp(float x) |
||
234 | { |
||
235 | const float k = 1.44269f; /* = log2(e) */ |
||
236 | return util_fast_exp2(k * x); |
||
237 | } |
||
238 | |||
239 | |||
240 | #define LOG2_TABLE_SIZE_LOG2 16 |
||
241 | #define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2) |
||
242 | #define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1) |
||
243 | extern float log2_table[LOG2_TABLE_SIZE]; |
||
244 | |||
245 | |||
246 | /** |
||
247 | * Fast approximation to log2(x). |
||
248 | */ |
||
249 | static INLINE float |
||
250 | util_fast_log2(float x) |
||
251 | { |
||
252 | union fi num; |
||
253 | float epart, mpart; |
||
254 | num.f = x; |
||
255 | epart = (float)(((num.i & 0x7f800000) >> 23) - 127); |
||
256 | /* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */ |
||
257 | mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)]; |
||
258 | return epart + mpart; |
||
259 | } |
||
260 | |||
261 | |||
262 | /** |
||
263 | * Fast approximation to x^y. |
||
264 | */ |
||
265 | static INLINE float |
||
266 | util_fast_pow(float x, float y) |
||
267 | { |
||
268 | return util_fast_exp2(util_fast_log2(x) * y); |
||
269 | } |
||
270 | |||
271 | /* Note that this counts zero as a power of two. |
||
272 | */ |
||
273 | static INLINE boolean |
||
274 | util_is_power_of_two( unsigned v ) |
||
275 | { |
||
276 | return (v & (v-1)) == 0; |
||
277 | } |
||
278 | |||
279 | |||
280 | /** |
||
281 | * Floor(x), returned as int. |
||
282 | */ |
||
283 | static INLINE int |
||
284 | util_ifloor(float f) |
||
285 | { |
||
286 | int ai, bi; |
||
287 | double af, bf; |
||
288 | union fi u; |
||
289 | af = (3 << 22) + 0.5 + (double) f; |
||
290 | bf = (3 << 22) + 0.5 - (double) f; |
||
291 | u.f = (float) af; ai = u.i; |
||
292 | u.f = (float) bf; bi = u.i; |
||
293 | return (ai - bi) >> 1; |
||
294 | } |
||
295 | |||
296 | |||
297 | /** |
||
298 | * Round float to nearest int. |
||
299 | */ |
||
300 | static INLINE int |
||
301 | util_iround(float f) |
||
302 | { |
||
303 | #if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) |
||
304 | int r; |
||
305 | __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); |
||
306 | return r; |
||
307 | #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) |
||
308 | int r; |
||
309 | _asm { |
||
310 | fld f |
||
311 | fistp r |
||
312 | } |
||
313 | return r; |
||
314 | #else |
||
315 | if (f >= 0.0f) |
||
316 | return (int) (f + 0.5f); |
||
317 | else |
||
318 | return (int) (f - 0.5f); |
||
319 | #endif |
||
320 | } |
||
321 | |||
322 | |||
323 | /** |
||
324 | * Approximate floating point comparison |
||
325 | */ |
||
326 | static INLINE boolean |
||
327 | util_is_approx(float a, float b, float tol) |
||
328 | { |
||
329 | return fabs(b - a) <= tol; |
||
330 | } |
||
331 | |||
332 | |||
333 | /** |
||
334 | * util_is_X_inf_or_nan = test if x is NaN or +/- Inf |
||
335 | * util_is_X_nan = test if x is NaN |
||
336 | * util_X_inf_sign = return +1 for +Inf, -1 for -Inf, or 0 for not Inf |
||
337 | * |
||
338 | * NaN can be checked with x != x, however this fails with the fast math flag |
||
339 | **/ |
||
340 | |||
341 | |||
342 | /** |
||
343 | * Single-float |
||
344 | */ |
||
345 | static INLINE boolean |
||
346 | util_is_inf_or_nan(float x) |
||
347 | { |
||
348 | union fi tmp; |
||
349 | tmp.f = x; |
||
350 | return (tmp.ui & 0x7f800000) == 0x7f800000; |
||
351 | } |
||
352 | |||
353 | |||
354 | static INLINE boolean |
||
355 | util_is_nan(float x) |
||
356 | { |
||
357 | union fi tmp; |
||
358 | tmp.f = x; |
||
359 | return (tmp.ui & 0x7fffffff) > 0x7f800000; |
||
360 | } |
||
361 | |||
362 | |||
363 | static INLINE int |
||
364 | util_inf_sign(float x) |
||
365 | { |
||
366 | union fi tmp; |
||
367 | tmp.f = x; |
||
368 | if ((tmp.ui & 0x7fffffff) != 0x7f800000) { |
||
369 | return 0; |
||
370 | } |
||
371 | |||
372 | return (x < 0) ? -1 : 1; |
||
373 | } |
||
374 | |||
375 | |||
376 | /** |
||
377 | * Double-float |
||
378 | */ |
||
379 | static INLINE boolean |
||
380 | util_is_double_inf_or_nan(double x) |
||
381 | { |
||
382 | union di tmp; |
||
383 | tmp.d = x; |
||
384 | return (tmp.ui & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL; |
||
385 | } |
||
386 | |||
387 | |||
388 | static INLINE boolean |
||
389 | util_is_double_nan(double x) |
||
390 | { |
||
391 | union di tmp; |
||
392 | tmp.d = x; |
||
393 | return (tmp.ui & 0x7fffffffffffffffULL) > 0x7ff0000000000000ULL; |
||
394 | } |
||
395 | |||
396 | |||
397 | static INLINE int |
||
398 | util_double_inf_sign(double x) |
||
399 | { |
||
400 | union di tmp; |
||
401 | tmp.d = x; |
||
402 | if ((tmp.ui & 0x7fffffffffffffffULL) != 0x7ff0000000000000ULL) { |
||
403 | return 0; |
||
404 | } |
||
405 | |||
406 | return (x < 0) ? -1 : 1; |
||
407 | } |
||
408 | |||
409 | |||
410 | /** |
||
411 | * Half-float |
||
412 | */ |
||
413 | static INLINE boolean |
||
414 | util_is_half_inf_or_nan(int16_t x) |
||
415 | { |
||
416 | return (x & 0x7c00) == 0x7c00; |
||
417 | } |
||
418 | |||
419 | |||
420 | static INLINE boolean |
||
421 | util_is_half_nan(int16_t x) |
||
422 | { |
||
423 | return (x & 0x7fff) > 0x7c00; |
||
424 | } |
||
425 | |||
426 | |||
427 | static INLINE int |
||
428 | util_half_inf_sign(int16_t x) |
||
429 | { |
||
430 | if ((x & 0x7fff) != 0x7c00) { |
||
431 | return 0; |
||
432 | } |
||
433 | |||
434 | return (x < 0) ? -1 : 1; |
||
435 | } |
||
436 | |||
437 | |||
438 | /** |
||
439 | * Find first bit set in word. Least significant bit is 1. |
||
440 | * Return 0 if no bits set. |
||
441 | */ |
||
442 | #ifndef FFS_DEFINED |
||
443 | #define FFS_DEFINED 1 |
||
444 | |||
445 | #if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) |
||
446 | unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); |
||
447 | #pragma intrinsic(_BitScanForward) |
||
448 | static INLINE |
||
449 | unsigned long ffs( unsigned long u ) |
||
450 | { |
||
451 | unsigned long i; |
||
452 | if (_BitScanForward(&i, u)) |
||
453 | return i + 1; |
||
454 | else |
||
455 | return 0; |
||
456 | } |
||
457 | #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) |
||
458 | static INLINE |
||
459 | unsigned ffs( unsigned u ) |
||
460 | { |
||
461 | unsigned i; |
||
462 | |||
463 | if (u == 0) { |
||
464 | return 0; |
||
465 | } |
||
466 | |||
467 | __asm bsf eax, [u] |
||
468 | __asm inc eax |
||
469 | __asm mov [i], eax |
||
470 | |||
471 | return i; |
||
472 | } |
||
473 | #elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID) |
||
474 | #define ffs __builtin_ffs |
||
475 | #endif |
||
476 | |||
477 | #endif /* FFS_DEFINED */ |
||
478 | |||
479 | /** |
||
480 | * Find last bit set in a word. The least significant bit is 1. |
||
481 | * Return 0 if no bits are set. |
||
482 | */ |
||
483 | static INLINE unsigned util_last_bit(unsigned u) |
||
484 | { |
||
485 | #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) |
||
486 | return u == 0 ? 0 : 32 - __builtin_clz(u); |
||
487 | #else |
||
488 | unsigned r = 0; |
||
489 | while (u) { |
||
490 | r++; |
||
491 | u >>= 1; |
||
492 | } |
||
493 | return r; |
||
494 | #endif |
||
495 | } |
||
496 | |||
497 | |||
498 | /* Destructively loop over all of the bits in a mask as in: |
||
499 | * |
||
500 | * while (mymask) { |
||
501 | * int i = u_bit_scan(&mymask); |
||
502 | * ... process element i |
||
503 | * } |
||
504 | * |
||
505 | */ |
||
506 | static INLINE int u_bit_scan(unsigned *mask) |
||
507 | { |
||
508 | int i = ffs(*mask) - 1; |
||
509 | *mask &= ~(1 << i); |
||
510 | return i; |
||
511 | } |
||
512 | |||
513 | |||
514 | /** |
||
515 | * Return float bits. |
||
516 | */ |
||
517 | static INLINE unsigned |
||
518 | fui( float f ) |
||
519 | { |
||
520 | union fi fi; |
||
521 | fi.f = f; |
||
522 | return fi.ui; |
||
523 | } |
||
524 | |||
525 | |||
526 | /** |
||
527 | * Convert ubyte to float in [0, 1]. |
||
528 | * XXX a 256-entry lookup table would be slightly faster. |
||
529 | */ |
||
530 | static INLINE float |
||
531 | ubyte_to_float(ubyte ub) |
||
532 | { |
||
533 | return (float) ub * (1.0f / 255.0f); |
||
534 | } |
||
535 | |||
536 | |||
537 | /** |
||
538 | * Convert float in [0,1] to ubyte in [0,255] with clamping. |
||
539 | */ |
||
540 | static INLINE ubyte |
||
541 | float_to_ubyte(float f) |
||
542 | { |
||
543 | union fi tmp; |
||
544 | |||
545 | tmp.f = f; |
||
546 | if (tmp.i < 0) { |
||
547 | return (ubyte) 0; |
||
548 | } |
||
549 | else if (tmp.i >= 0x3f800000 /* 1.0f */) { |
||
550 | return (ubyte) 255; |
||
551 | } |
||
552 | else { |
||
553 | tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f; |
||
554 | return (ubyte) tmp.i; |
||
555 | } |
||
556 | } |
||
557 | |||
558 | static INLINE float |
||
559 | byte_to_float_tex(int8_t b) |
||
560 | { |
||
561 | return (b == -128) ? -1.0F : b * 1.0F / 127.0F; |
||
562 | } |
||
563 | |||
564 | static INLINE int8_t |
||
565 | float_to_byte_tex(float f) |
||
566 | { |
||
567 | return (int8_t) (127.0F * f); |
||
568 | } |
||
569 | |||
570 | /** |
||
571 | * Calc log base 2 |
||
572 | */ |
||
573 | static INLINE unsigned |
||
574 | util_logbase2(unsigned n) |
||
575 | { |
||
576 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||
577 | return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1)); |
||
578 | #else |
||
579 | unsigned pos = 0; |
||
580 | if (n >= 1<<16) { n >>= 16; pos += 16; } |
||
581 | if (n >= 1<< 8) { n >>= 8; pos += 8; } |
||
582 | if (n >= 1<< 4) { n >>= 4; pos += 4; } |
||
583 | if (n >= 1<< 2) { n >>= 2; pos += 2; } |
||
584 | if (n >= 1<< 1) { pos += 1; } |
||
585 | return pos; |
||
586 | #endif |
||
587 | } |
||
588 | |||
589 | |||
590 | /** |
||
591 | * Returns the smallest power of two >= x |
||
592 | */ |
||
593 | static INLINE unsigned |
||
594 | util_next_power_of_two(unsigned x) |
||
595 | { |
||
596 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||
597 | if (x <= 1) |
||
598 | return 1; |
||
599 | |||
600 | return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1))); |
||
601 | #else |
||
602 | unsigned val = x; |
||
603 | |||
604 | if (x <= 1) |
||
605 | return 1; |
||
606 | |||
607 | if (util_is_power_of_two(x)) |
||
608 | return x; |
||
609 | |||
610 | val--; |
||
611 | val = (val >> 1) | val; |
||
612 | val = (val >> 2) | val; |
||
613 | val = (val >> 4) | val; |
||
614 | val = (val >> 8) | val; |
||
615 | val = (val >> 16) | val; |
||
616 | val++; |
||
617 | return val; |
||
618 | #endif |
||
619 | } |
||
620 | |||
621 | |||
622 | /** |
||
623 | * Return number of bits set in n. |
||
624 | */ |
||
625 | static INLINE unsigned |
||
626 | util_bitcount(unsigned n) |
||
627 | { |
||
628 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||
629 | return __builtin_popcount(n); |
||
630 | #else |
||
631 | /* K&R classic bitcount. |
||
632 | * |
||
633 | * For each iteration, clear the LSB from the bitfield. |
||
634 | * Requires only one iteration per set bit, instead of |
||
635 | * one iteration per bit less than highest set bit. |
||
636 | */ |
||
637 | unsigned bits = 0; |
||
638 | for (bits; n; bits++) { |
||
639 | n &= n - 1; |
||
640 | } |
||
641 | return bits; |
||
642 | #endif |
||
643 | } |
||
644 | |||
645 | |||
646 | /** |
||
647 | * Convert from little endian to CPU byte order. |
||
648 | */ |
||
649 | |||
650 | #ifdef PIPE_ARCH_BIG_ENDIAN |
||
651 | #define util_le32_to_cpu(x) util_bswap32(x) |
||
652 | #define util_le16_to_cpu(x) util_bswap16(x) |
||
653 | #else |
||
654 | #define util_le32_to_cpu(x) (x) |
||
655 | #define util_le16_to_cpu(x) (x) |
||
656 | #endif |
||
657 | |||
658 | |||
659 | /** |
||
660 | * Reverse byte order of a 32 bit word. |
||
661 | */ |
||
662 | static INLINE uint32_t |
||
663 | util_bswap32(uint32_t n) |
||
664 | { |
||
665 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403) |
||
666 | return __builtin_bswap32(n); |
||
667 | #else |
||
668 | return (n >> 24) | |
||
669 | ((n >> 8) & 0x0000ff00) | |
||
670 | ((n << 8) & 0x00ff0000) | |
||
671 | (n << 24); |
||
672 | #endif |
||
673 | } |
||
674 | |||
675 | |||
676 | /** |
||
677 | * Reverse byte order of a 16 bit word. |
||
678 | */ |
||
679 | static INLINE uint16_t |
||
680 | util_bswap16(uint16_t n) |
||
681 | { |
||
682 | return (n >> 8) | |
||
683 | (n << 8); |
||
684 | } |
||
685 | |||
686 | |||
687 | /** |
||
688 | * Clamp X to [MIN, MAX]. |
||
689 | * This is a macro to allow float, int, uint, etc. types. |
||
690 | */ |
||
691 | #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) |
||
692 | |||
693 | #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) |
||
694 | #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) |
||
695 | |||
696 | #define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C)) |
||
697 | #define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) |
||
698 | |||
699 | #define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D)) |
||
700 | #define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D)) |
||
701 | |||
702 | |||
703 | /** |
||
704 | * Align a value, only works pot alignemnts. |
||
705 | */ |
||
706 | static INLINE int |
||
707 | align(int value, int alignment) |
||
708 | { |
||
709 | return (value + alignment - 1) & ~(alignment - 1); |
||
710 | } |
||
711 | |||
712 | /** |
||
713 | * Works like align but on npot alignments. |
||
714 | */ |
||
715 | static INLINE size_t |
||
716 | util_align_npot(size_t value, size_t alignment) |
||
717 | { |
||
718 | if (value % alignment) |
||
719 | return value + (alignment - (value % alignment)); |
||
720 | return value; |
||
721 | } |
||
722 | |||
723 | static INLINE unsigned |
||
724 | u_minify(unsigned value, unsigned levels) |
||
725 | { |
||
726 | return MAX2(1, value >> levels); |
||
727 | } |
||
728 | |||
729 | #ifndef COPY_4V |
||
730 | #define COPY_4V( DST, SRC ) \ |
||
731 | do { \ |
||
732 | (DST)[0] = (SRC)[0]; \ |
||
733 | (DST)[1] = (SRC)[1]; \ |
||
734 | (DST)[2] = (SRC)[2]; \ |
||
735 | (DST)[3] = (SRC)[3]; \ |
||
736 | } while (0) |
||
737 | #endif |
||
738 | |||
739 | |||
740 | #ifndef COPY_4FV |
||
741 | #define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC) |
||
742 | #endif |
||
743 | |||
744 | |||
745 | #ifndef ASSIGN_4V |
||
746 | #define ASSIGN_4V( DST, V0, V1, V2, V3 ) \ |
||
747 | do { \ |
||
748 | (DST)[0] = (V0); \ |
||
749 | (DST)[1] = (V1); \ |
||
750 | (DST)[2] = (V2); \ |
||
751 | (DST)[3] = (V3); \ |
||
752 | } while (0) |
||
753 | #endif |
||
754 | |||
755 | |||
756 | static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits) |
||
757 | { |
||
758 | return value < 0 ? 0 : (uint32_t)(value * (1< |
||
759 | } |
||
760 | |||
761 | static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits) |
||
762 | { |
||
763 | return (int32_t)(value * (1< |
||
764 | } |
||
765 | |||
766 | unsigned |
||
767 | util_fpstate_get(void); |
||
768 | unsigned |
||
769 | util_fpstate_set_denorms_to_zero(unsigned current_fpstate); |
||
770 | void |
||
771 | util_fpstate_set(unsigned fpstate); |
||
772 | |||
773 | |||
774 | |||
775 | #ifdef __cplusplus |
||
776 | } |
||
777 | #endif |
||
778 | |||
779 | #endif /* U_MATH_H */ |