Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / gallium / auxiliary / util / u_math.h
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 #include "pipe/p_debug.h"
44
45
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49
50
51 #if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
52 __inline double ceil(double val)
53 {
54 double ceil_val;
55
56 if((val - (long) val) == 0) {
57 ceil_val = val;
58 }
59 else {
60 if(val > 0) {
61 ceil_val = (long) val + 1;
62 }
63 else {
64 ceil_val = (long) val;
65 }
66 }
67
68 return ceil_val;
69 }
70
71 #ifndef PIPE_SUBSYSTEM_WINDOWS_CE_OGL
72 __inline double floor(double val)
73 {
74 double floor_val;
75
76 if((val - (long) val) == 0) {
77 floor_val = val;
78 }
79 else {
80 if(val > 0) {
81 floor_val = (long) val;
82 }
83 else {
84 floor_val = (long) val - 1;
85 }
86 }
87
88 return floor_val;
89 }
90 #endif
91
92 #pragma function(pow)
93 __inline double __cdecl pow(double val, double exponent)
94 {
95 /* XXX */
96 assert(0);
97 return 0;
98 }
99
100 #pragma function(log)
101 __inline double __cdecl log(double val)
102 {
103 /* XXX */
104 assert(0);
105 return 0;
106 }
107
108 #pragma function(atan2)
109 __inline double __cdecl atan2(double val)
110 {
111 /* XXX */
112 assert(0);
113 return 0;
114 }
115 #else
116 #include <math.h>
117 #include <stdarg.h>
118 #endif
119
120
121 #if defined(_MSC_VER)
122 #if _MSC_VER < 1400 && !defined(__cplusplus) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
123
124 static INLINE float cosf( float f )
125 {
126 return (float) cos( (double) f );
127 }
128
129 static INLINE float sinf( float f )
130 {
131 return (float) sin( (double) f );
132 }
133
134 static INLINE float ceilf( float f )
135 {
136 return (float) ceil( (double) f );
137 }
138
139 static INLINE float floorf( float f )
140 {
141 return (float) floor( (double) f );
142 }
143
144 static INLINE float powf( float f, float g )
145 {
146 return (float) pow( (double) f, (double) g );
147 }
148
149 static INLINE float sqrtf( float f )
150 {
151 return (float) sqrt( (double) f );
152 }
153
154 static INLINE float fabsf( float f )
155 {
156 return (float) fabs( (double) f );
157 }
158
159 static INLINE float logf( float f )
160 {
161 return (float) log( (double) f );
162 }
163
164 #else
165 /* Work-around an extra semi-colon in VS 2005 logf definition */
166 #ifdef logf
167 #undef logf
168 #define logf(x) ((float)log((double)(x)))
169 #endif /* logf */
170 #endif
171 #endif /* _MSC_VER */
172
173
174
175
176
177 #define POW2_TABLE_SIZE_LOG2 9
178 #define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2)
179 #define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2)
180 #define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2))
181 extern float pow2_table[POW2_TABLE_SIZE];
182
183
184
185 extern void
186 util_init_math(void);
187
188
189 union fi {
190 float f;
191 int32_t i;
192 uint32_t ui;
193 };
194
195
196 /**
197 * Fast version of 2^x
198 * Identity: exp2(a + b) = exp2(a) * exp2(b)
199 * Let ipart = int(x)
200 * Let fpart = x - ipart;
201 * So, exp2(x) = exp2(ipart) * exp2(fpart)
202 * Compute exp2(ipart) with i << ipart
203 * Compute exp2(fpart) with lookup table.
204 */
205 static INLINE float
206 util_fast_exp2(float x)
207 {
208 int32_t ipart;
209 float fpart, mpart;
210 union fi epart;
211
212 if(x > 129.00000f)
213 return 3.402823466e+38f;
214
215 if(x < -126.99999f)
216 return 0.0f;
217
218 ipart = (int32_t) x;
219 fpart = x - (float) ipart;
220
221 /* same as
222 * epart.f = (float) (1 << ipart)
223 * but faster and without integer overflow for ipart > 31 */
224 epart.i = (ipart + 127 ) << 23;
225
226 mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)];
227
228 return epart.f * mpart;
229 }
230
231
232 /**
233 * Fast approximation to exp(x).
234 */
235 static INLINE float
236 util_fast_exp(float x)
237 {
238 const float k = 1.44269f; /* = log2(e) */
239 return util_fast_exp2(k * x);
240 }
241
242
243 #define LOG2_TABLE_SIZE_LOG2 8
244 #define LOG2_TABLE_SIZE (1 << LOG2_TABLE_SIZE_LOG2)
245 extern float log2_table[LOG2_TABLE_SIZE];
246
247
248 static INLINE float
249 util_fast_log2(float x)
250 {
251 union fi num;
252 float epart, mpart;
253 num.f = x;
254 epart = (float)(((num.i & 0x7f800000) >> 23) - 127);
255 mpart = log2_table[(num.i & 0x007fffff) >> (23 - LOG2_TABLE_SIZE_LOG2)];
256 return epart + mpart;
257 }
258
259
260 static INLINE float
261 util_fast_pow(float x, float y)
262 {
263 return util_fast_exp2(util_fast_log2(x) * y);
264 }
265
266
267
268 /**
269 * Floor(x), returned as int.
270 */
271 static INLINE int
272 util_ifloor(float f)
273 {
274 int ai, bi;
275 double af, bf;
276 union fi u;
277 af = (3 << 22) + 0.5 + (double)f;
278 bf = (3 << 22) + 0.5 - (double)f;
279 u.f = (float) af; ai = u.i;
280 u.f = (float) bf; bi = u.i;
281 return (ai - bi) >> 1;
282 }
283
284
285 /**
286 * Round float to nearest int.
287 */
288 static INLINE int
289 util_iround(float f)
290 {
291 #if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)
292 int r;
293 __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
294 return r;
295 #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
296 int r;
297 _asm {
298 fld f
299 fistp r
300 }
301 return r;
302 #else
303 if (f >= 0.0f)
304 return (int) (f + 0.5f);
305 else
306 return (int) (f - 0.5f);
307 #endif
308 }
309
310
311
312 #if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
313 /**
314 * Find first bit set in word. Least significant bit is 1.
315 * Return 0 if no bits set.
316 */
317 static INLINE
318 unsigned ffs( unsigned u )
319 {
320 unsigned i;
321
322 if( u == 0 ) {
323 return 0;
324 }
325
326 __asm bsf eax, [u]
327 __asm inc eax
328 __asm mov [i], eax
329
330 return i;
331 }
332 #endif
333
334
335 /**
336 * Return float bits.
337 */
338 static INLINE unsigned
339 fui( float f )
340 {
341 union fi fi;
342 fi.f = f;
343 return fi.ui;
344 }
345
346
347
348 static INLINE float
349 ubyte_to_float(ubyte ub)
350 {
351 return (float) ub * (1.0f / 255.0f);
352 }
353
354
355 /**
356 * Convert float in [0,1] to ubyte in [0,255] with clamping.
357 */
358 static INLINE ubyte
359 float_to_ubyte(float f)
360 {
361 const int ieee_0996 = 0x3f7f0000; /* 0.996 or so */
362 union fi tmp;
363
364 tmp.f = f;
365 if (tmp.i < 0) {
366 return (ubyte) 0;
367 }
368 else if (tmp.i >= ieee_0996) {
369 return (ubyte) 255;
370 }
371 else {
372 tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f;
373 return (ubyte) tmp.i;
374 }
375 }
376
377
378
379 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
380
381 #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
382 #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
383
384
385 static INLINE int
386 align(int value, int alignment)
387 {
388 return (value + alignment - 1) & ~(alignment - 1);
389 }
390
391
392 #ifndef COPY_4V
393 #define COPY_4V( DST, SRC ) \
394 do { \
395 (DST)[0] = (SRC)[0]; \
396 (DST)[1] = (SRC)[1]; \
397 (DST)[2] = (SRC)[2]; \
398 (DST)[3] = (SRC)[3]; \
399 } while (0)
400 #endif
401
402
403 #ifndef COPY_4FV
404 #define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC)
405 #endif
406
407
408 #ifndef ASSIGN_4V
409 #define ASSIGN_4V( DST, V0, V1, V2, V3 ) \
410 do { \
411 (DST)[0] = (V0); \
412 (DST)[1] = (V1); \
413 (DST)[2] = (V2); \
414 (DST)[3] = (V3); \
415 } while (0)
416 #endif
417
418
419 #ifdef __cplusplus
420 }
421 #endif
422
423 #endif /* U_MATH_H */