Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
5063 | serge | 2 | * |
4358 | Serge | 3 | * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. |
4 | * All Rights Reserved. |
||
5063 | serge | 5 | * |
4358 | Serge | 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: |
||
5063 | serge | 13 | * |
4358 | Serge | 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. |
||
5063 | serge | 17 | * |
4358 | Serge | 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. |
||
5063 | serge | 25 | * |
4358 | Serge | 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 | |||
5063 | serge | 63 | #if defined(_MSC_VER) |
4358 | Serge | 64 | |
65 | #if _MSC_VER < 1400 && !defined(__cplusplus) |
||
5063 | serge | 66 | |
67 | static INLINE float cosf( float f ) |
||
4358 | Serge | 68 | { |
69 | return (float) cos( (double) f ); |
||
70 | } |
||
71 | |||
5063 | serge | 72 | static INLINE float sinf( float f ) |
4358 | Serge | 73 | { |
74 | return (float) sin( (double) f ); |
||
75 | } |
||
76 | |||
5063 | serge | 77 | static INLINE float ceilf( float f ) |
4358 | Serge | 78 | { |
79 | return (float) ceil( (double) f ); |
||
80 | } |
||
81 | |||
5063 | serge | 82 | static INLINE float floorf( float f ) |
4358 | Serge | 83 | { |
84 | return (float) floor( (double) f ); |
||
85 | } |
||
86 | |||
5063 | serge | 87 | static INLINE float powf( float f, float g ) |
4358 | Serge | 88 | { |
89 | return (float) pow( (double) f, (double) g ); |
||
90 | } |
||
91 | |||
5063 | serge | 92 | static INLINE float sqrtf( float f ) |
4358 | Serge | 93 | { |
94 | return (float) sqrt( (double) f ); |
||
95 | } |
||
96 | |||
5063 | serge | 97 | static INLINE float fabsf( float f ) |
4358 | Serge | 98 | { |
99 | return (float) fabs( (double) f ); |
||
100 | } |
||
101 | |||
5063 | serge | 102 | static INLINE float logf( float f ) |
4358 | Serge | 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 | { |
||
5063 | serge | 303 | #if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) |
4358 | Serge | 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 | #define ffs __builtin_ffs |
||
446 | |||
447 | #endif /* FFS_DEFINED */ |
||
448 | |||
449 | /** |
||
450 | * Find last bit set in a word. The least significant bit is 1. |
||
451 | * Return 0 if no bits are set. |
||
452 | */ |
||
453 | static INLINE unsigned util_last_bit(unsigned u) |
||
454 | { |
||
455 | #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) |
||
456 | return u == 0 ? 0 : 32 - __builtin_clz(u); |
||
457 | #else |
||
458 | unsigned r = 0; |
||
459 | while (u) { |
||
460 | r++; |
||
461 | u >>= 1; |
||
462 | } |
||
463 | return r; |
||
464 | #endif |
||
465 | } |
||
466 | |||
467 | |||
468 | /* Destructively loop over all of the bits in a mask as in: |
||
469 | * |
||
470 | * while (mymask) { |
||
471 | * int i = u_bit_scan(&mymask); |
||
472 | * ... process element i |
||
473 | * } |
||
5063 | serge | 474 | * |
4358 | Serge | 475 | */ |
476 | static INLINE int u_bit_scan(unsigned *mask) |
||
477 | { |
||
478 | int i = ffs(*mask) - 1; |
||
479 | *mask &= ~(1 << i); |
||
480 | return i; |
||
481 | } |
||
482 | |||
483 | |||
484 | /** |
||
485 | * Return float bits. |
||
486 | */ |
||
487 | static INLINE unsigned |
||
488 | fui( float f ) |
||
489 | { |
||
490 | union fi fi; |
||
491 | fi.f = f; |
||
492 | return fi.ui; |
||
493 | } |
||
494 | |||
495 | |||
496 | /** |
||
497 | * Convert ubyte to float in [0, 1]. |
||
498 | * XXX a 256-entry lookup table would be slightly faster. |
||
499 | */ |
||
500 | static INLINE float |
||
501 | ubyte_to_float(ubyte ub) |
||
502 | { |
||
503 | return (float) ub * (1.0f / 255.0f); |
||
504 | } |
||
505 | |||
506 | |||
507 | /** |
||
508 | * Convert float in [0,1] to ubyte in [0,255] with clamping. |
||
509 | */ |
||
510 | static INLINE ubyte |
||
511 | float_to_ubyte(float f) |
||
512 | { |
||
513 | union fi tmp; |
||
514 | |||
515 | tmp.f = f; |
||
516 | if (tmp.i < 0) { |
||
517 | return (ubyte) 0; |
||
518 | } |
||
519 | else if (tmp.i >= 0x3f800000 /* 1.0f */) { |
||
520 | return (ubyte) 255; |
||
521 | } |
||
522 | else { |
||
523 | tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f; |
||
524 | return (ubyte) tmp.i; |
||
525 | } |
||
526 | } |
||
527 | |||
528 | static INLINE float |
||
529 | byte_to_float_tex(int8_t b) |
||
530 | { |
||
531 | return (b == -128) ? -1.0F : b * 1.0F / 127.0F; |
||
532 | } |
||
533 | |||
534 | static INLINE int8_t |
||
535 | float_to_byte_tex(float f) |
||
536 | { |
||
537 | return (int8_t) (127.0F * f); |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Calc log base 2 |
||
542 | */ |
||
543 | static INLINE unsigned |
||
544 | util_logbase2(unsigned n) |
||
545 | { |
||
546 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||
547 | return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1)); |
||
548 | #else |
||
549 | unsigned pos = 0; |
||
550 | if (n >= 1<<16) { n >>= 16; pos += 16; } |
||
551 | if (n >= 1<< 8) { n >>= 8; pos += 8; } |
||
552 | if (n >= 1<< 4) { n >>= 4; pos += 4; } |
||
553 | if (n >= 1<< 2) { n >>= 2; pos += 2; } |
||
554 | if (n >= 1<< 1) { pos += 1; } |
||
555 | return pos; |
||
556 | #endif |
||
557 | } |
||
558 | |||
559 | |||
560 | /** |
||
561 | * Returns the smallest power of two >= x |
||
562 | */ |
||
563 | static INLINE unsigned |
||
564 | util_next_power_of_two(unsigned x) |
||
565 | { |
||
566 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||
567 | if (x <= 1) |
||
568 | return 1; |
||
569 | |||
570 | return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1))); |
||
571 | #else |
||
572 | unsigned val = x; |
||
573 | |||
574 | if (x <= 1) |
||
575 | return 1; |
||
576 | |||
577 | if (util_is_power_of_two(x)) |
||
578 | return x; |
||
579 | |||
580 | val--; |
||
581 | val = (val >> 1) | val; |
||
582 | val = (val >> 2) | val; |
||
583 | val = (val >> 4) | val; |
||
584 | val = (val >> 8) | val; |
||
585 | val = (val >> 16) | val; |
||
586 | val++; |
||
587 | return val; |
||
588 | #endif |
||
589 | } |
||
590 | |||
591 | |||
592 | /** |
||
593 | * Return number of bits set in n. |
||
594 | */ |
||
595 | static INLINE unsigned |
||
596 | util_bitcount(unsigned n) |
||
597 | { |
||
598 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||
599 | return __builtin_popcount(n); |
||
600 | #else |
||
601 | /* K&R classic bitcount. |
||
602 | * |
||
603 | * For each iteration, clear the LSB from the bitfield. |
||
604 | * Requires only one iteration per set bit, instead of |
||
605 | * one iteration per bit less than highest set bit. |
||
606 | */ |
||
607 | unsigned bits = 0; |
||
608 | for (bits; n; bits++) { |
||
609 | n &= n - 1; |
||
610 | } |
||
611 | return bits; |
||
612 | #endif |
||
613 | } |
||
614 | |||
615 | |||
616 | /** |
||
617 | * Convert from little endian to CPU byte order. |
||
618 | */ |
||
619 | |||
620 | #ifdef PIPE_ARCH_BIG_ENDIAN |
||
621 | #define util_le32_to_cpu(x) util_bswap32(x) |
||
622 | #define util_le16_to_cpu(x) util_bswap16(x) |
||
623 | #else |
||
624 | #define util_le32_to_cpu(x) (x) |
||
625 | #define util_le16_to_cpu(x) (x) |
||
626 | #endif |
||
627 | |||
628 | |||
629 | /** |
||
630 | * Reverse byte order of a 32 bit word. |
||
631 | */ |
||
632 | static INLINE uint32_t |
||
633 | util_bswap32(uint32_t n) |
||
634 | { |
||
635 | #if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403) |
||
636 | return __builtin_bswap32(n); |
||
637 | #else |
||
638 | return (n >> 24) | |
||
639 | ((n >> 8) & 0x0000ff00) | |
||
640 | ((n << 8) & 0x00ff0000) | |
||
641 | (n << 24); |
||
642 | #endif |
||
643 | } |
||
644 | |||
645 | |||
646 | /** |
||
647 | * Reverse byte order of a 16 bit word. |
||
648 | */ |
||
649 | static INLINE uint16_t |
||
650 | util_bswap16(uint16_t n) |
||
651 | { |
||
652 | return (n >> 8) | |
||
653 | (n << 8); |
||
654 | } |
||
655 | |||
656 | |||
657 | /** |
||
658 | * Clamp X to [MIN, MAX]. |
||
659 | * This is a macro to allow float, int, uint, etc. types. |
||
660 | */ |
||
661 | #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) |
||
662 | |||
663 | #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) |
||
664 | #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) |
||
665 | |||
666 | #define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C)) |
||
667 | #define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) |
||
668 | |||
669 | #define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D)) |
||
670 | #define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D)) |
||
671 | |||
672 | |||
673 | /** |
||
674 | * Align a value, only works pot alignemnts. |
||
675 | */ |
||
676 | static INLINE int |
||
677 | align(int value, int alignment) |
||
678 | { |
||
679 | return (value + alignment - 1) & ~(alignment - 1); |
||
680 | } |
||
681 | |||
682 | /** |
||
683 | * Works like align but on npot alignments. |
||
684 | */ |
||
685 | static INLINE size_t |
||
686 | util_align_npot(size_t value, size_t alignment) |
||
687 | { |
||
688 | if (value % alignment) |
||
689 | return value + (alignment - (value % alignment)); |
||
690 | return value; |
||
691 | } |
||
692 | |||
693 | static INLINE unsigned |
||
694 | u_minify(unsigned value, unsigned levels) |
||
695 | { |
||
696 | return MAX2(1, value >> levels); |
||
697 | } |
||
698 | |||
699 | #ifndef COPY_4V |
||
700 | #define COPY_4V( DST, SRC ) \ |
||
701 | do { \ |
||
702 | (DST)[0] = (SRC)[0]; \ |
||
703 | (DST)[1] = (SRC)[1]; \ |
||
704 | (DST)[2] = (SRC)[2]; \ |
||
705 | (DST)[3] = (SRC)[3]; \ |
||
706 | } while (0) |
||
707 | #endif |
||
708 | |||
709 | |||
710 | #ifndef COPY_4FV |
||
711 | #define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC) |
||
712 | #endif |
||
713 | |||
714 | |||
715 | #ifndef ASSIGN_4V |
||
716 | #define ASSIGN_4V( DST, V0, V1, V2, V3 ) \ |
||
717 | do { \ |
||
718 | (DST)[0] = (V0); \ |
||
719 | (DST)[1] = (V1); \ |
||
720 | (DST)[2] = (V2); \ |
||
721 | (DST)[3] = (V3); \ |
||
722 | } while (0) |
||
723 | #endif |
||
724 | |||
725 | |||
726 | static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits) |
||
727 | { |
||
728 | return value < 0 ? 0 : (uint32_t)(value * (1< |
||
729 | } |
||
730 | |||
731 | static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits) |
||
732 | { |
||
733 | return (int32_t)(value * (1< |
||
734 | } |
||
735 | |||
736 | unsigned |
||
737 | util_fpstate_get(void); |
||
738 | unsigned |
||
739 | util_fpstate_set_denorms_to_zero(unsigned current_fpstate); |
||
740 | void |
||
741 | util_fpstate_set(unsigned fpstate); |
||
742 | |||
743 | |||
744 | |||
745 | #ifdef __cplusplus |
||
746 | } |
||
747 | #endif |
||
748 | |||
749 | #endif /* U_MATH_H */ |