u_math.h

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 
00038 #ifndef U_MATH_H
00039 #define U_MATH_H
00040 
00041 
00042 #include "pipe/p_compiler.h"
00043 #include "pipe/p_debug.h"
00044 
00045 
00046 #ifdef __cplusplus
00047 extern "C" {
00048 #endif
00049 
00050 
00051 #if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00052 __inline double ceil(double val)
00053 {
00054    double ceil_val;
00055 
00056    if((val - (long) val) == 0) {
00057       ceil_val = val;
00058    }
00059    else {
00060       if(val > 0) {
00061          ceil_val = (long) val + 1;
00062       }
00063       else {
00064          ceil_val = (long) val;
00065       }
00066    }
00067 
00068    return ceil_val;
00069 }
00070 
00071 #ifndef PIPE_SUBSYSTEM_WINDOWS_CE
00072 __inline double floor(double val)
00073 {
00074    double floor_val;
00075 
00076    if((val - (long) val) == 0) {
00077       floor_val = val;
00078    }
00079    else {
00080       if(val > 0) {
00081          floor_val = (long) val;
00082       }
00083       else {
00084          floor_val = (long) val - 1;
00085       }
00086    }
00087 
00088    return floor_val;
00089 }
00090 #endif
00091 
00092 #pragma function(pow)
00093 __inline double __cdecl pow(double val, double exponent)
00094 {
00095    /* XXX */
00096    assert(0);
00097    return 0;
00098 }
00099 
00100 #pragma function(log)
00101 __inline double __cdecl log(double val)
00102 {
00103    /* XXX */
00104    assert(0);
00105    return 0;
00106 }
00107 
00108 #pragma function(atan2)
00109 __inline double __cdecl atan2(double val)
00110 {
00111    /* XXX */
00112    assert(0);
00113    return 0;
00114 }
00115 #else
00116 #include <math.h>
00117 #include <stdarg.h>
00118 #endif
00119 
00120 
00121 #if defined(_MSC_VER) 
00122 
00123 #if _MSC_VER < 1400 && !defined(__cplusplus) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
00124  
00125 static INLINE float cosf( float f ) 
00126 {
00127    return (float) cos( (double) f );
00128 }
00129 
00130 static INLINE float sinf( float f ) 
00131 {
00132    return (float) sin( (double) f );
00133 }
00134 
00135 static INLINE float ceilf( float f ) 
00136 {
00137    return (float) ceil( (double) f );
00138 }
00139 
00140 static INLINE float floorf( float f ) 
00141 {
00142    return (float) floor( (double) f );
00143 }
00144 
00145 static INLINE float powf( float f, float g ) 
00146 {
00147    return (float) pow( (double) f, (double) g );
00148 }
00149 
00150 static INLINE float sqrtf( float f ) 
00151 {
00152    return (float) sqrt( (double) f );
00153 }
00154 
00155 static INLINE float fabsf( float f ) 
00156 {
00157    return (float) fabs( (double) f );
00158 }
00159 
00160 static INLINE float logf( float f ) 
00161 {
00162    return (float) log( (double) f );
00163 }
00164 
00165 #else
00166 /* Work-around an extra semi-colon in VS 2005 logf definition */
00167 #ifdef logf
00168 #undef logf
00169 #define logf(x) ((float)log((double)(x)))
00170 #endif /* logf */
00171 #endif
00172 
00173 static INLINE double log2( double x )
00174 {
00175    const double invln2 = 1.442695041;
00176    return log( x ) * invln2;
00177 }
00178 
00179 #endif /* _MSC_VER */
00180 
00181 
00182 
00183 
00184 
00185 #define POW2_TABLE_SIZE_LOG2 9
00186 #define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2)
00187 #define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2)
00188 #define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2))
00189 extern float pow2_table[POW2_TABLE_SIZE];
00190 
00191 
00192 
00193 extern void
00194 util_init_math(void);
00195 
00196 
00197 union fi {
00198    float f;
00199    int32_t i;
00200    uint32_t ui;
00201 };
00202 
00203 
00213 static INLINE float
00214 util_fast_exp2(float x)
00215 {
00216    int32_t ipart;
00217    float fpart, mpart;
00218    union fi epart;
00219    
00220    if(x > 129.00000f)
00221       return 3.402823466e+38f;
00222    
00223    if(x < -126.99999f)
00224       return 0.0f;
00225 
00226    ipart = (int32_t) x;
00227    fpart = x - (float) ipart;
00228    
00229    /* same as
00230     *   epart.f = (float) (1 << ipart)
00231     * but faster and without integer overflow for ipart > 31 */
00232    epart.i = (ipart + 127 ) << 23;
00233    
00234    mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)];
00235    
00236    return epart.f * mpart;
00237 }
00238 
00239 
00243 static INLINE float
00244 util_fast_exp(float x)
00245 {
00246    const float k = 1.44269f; /* = log2(e) */
00247    return util_fast_exp2(k * x);
00248 }
00249 
00250 
00251 #define LOG2_TABLE_SIZE_LOG2 16
00252 #define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2)
00253 #define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1)
00254 extern float log2_table[LOG2_TABLE_SIZE];
00255 
00256 
00257 static INLINE float
00258 util_fast_log2(float x)
00259 {
00260    union fi num;
00261    float epart, mpart;
00262    num.f = x;
00263    epart = (float)(((num.i & 0x7f800000) >> 23) - 127);
00264    /* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */
00265    mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)];
00266    return epart + mpart;
00267 }
00268 
00269 
00270 static INLINE float
00271 util_fast_pow(float x, float y)
00272 {
00273    return util_fast_exp2(util_fast_log2(x) * y);
00274 }
00275 
00276 
00277 
00281 static INLINE int
00282 util_ifloor(float f)
00283 {
00284    int ai, bi;
00285    double af, bf;
00286    union fi u;
00287    af = (3 << 22) + 0.5 + (double)f;
00288    bf = (3 << 22) + 0.5 - (double)f;
00289    u.f = (float) af;  ai = u.i;
00290    u.f = (float) bf;  bi = u.i;
00291    return (ai - bi) >> 1;
00292 }
00293 
00294 
00298 static INLINE int
00299 util_iround(float f)
00300 {
00301 #if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) 
00302    int r;
00303    __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
00304    return r;
00305 #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
00306    int r;
00307    _asm {
00308          fld f
00309          fistp r
00310         }
00311    return r;
00312 #else
00313    if (f >= 0.0f)
00314       return (int) (f + 0.5f);
00315    else
00316       return (int) (f - 0.5f);
00317 #endif
00318 }
00319 
00320 
00321 
00322 #if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
00323 
00327 static INLINE
00328 unsigned ffs( unsigned u )
00329 {
00330    unsigned i;
00331 
00332    if( u == 0 ) {
00333       return 0;
00334    }
00335 
00336    __asm bsf eax, [u]
00337    __asm inc eax
00338    __asm mov [i], eax
00339 
00340    return i;
00341 }
00342 #endif
00343 
00344 #ifdef __MINGW32__
00345 #define ffs __builtin_ffs
00346 #endif
00347 
00348 
00352 static INLINE unsigned
00353 fui( float f )
00354 {
00355    union fi fi;
00356    fi.f = f;
00357    return fi.ui;
00358 }
00359 
00360 
00361 
00362 static INLINE float
00363 ubyte_to_float(ubyte ub)
00364 {
00365    return (float) ub * (1.0f / 255.0f);
00366 }
00367 
00368 
00372 static INLINE ubyte
00373 float_to_ubyte(float f)
00374 {
00375    const int ieee_0996 = 0x3f7f0000;   /* 0.996 or so */
00376    union fi tmp;
00377 
00378    tmp.f = f;
00379    if (tmp.i < 0) {
00380       return (ubyte) 0;
00381    }
00382    else if (tmp.i >= ieee_0996) {
00383       return (ubyte) 255;
00384    }
00385    else {
00386       tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f;
00387       return (ubyte) tmp.i;
00388    }
00389 }
00390 
00391 
00392 
00393 #define CLAMP( X, MIN, MAX )  ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
00394 
00395 #define MIN2( A, B )   ( (A)<(B) ? (A) : (B) )
00396 #define MAX2( A, B )   ( (A)>(B) ? (A) : (B) )
00397 
00398 
00399 static INLINE int
00400 align(int value, int alignment)
00401 {
00402    return (value + alignment - 1) & ~(alignment - 1);
00403 }
00404 
00405 
00406 #ifndef COPY_4V
00407 #define COPY_4V( DST, SRC )         \
00408 do {                                \
00409    (DST)[0] = (SRC)[0];             \
00410    (DST)[1] = (SRC)[1];             \
00411    (DST)[2] = (SRC)[2];             \
00412    (DST)[3] = (SRC)[3];             \
00413 } while (0)
00414 #endif
00415 
00416 
00417 #ifndef COPY_4FV
00418 #define COPY_4FV( DST, SRC )  COPY_4V(DST, SRC)
00419 #endif
00420 
00421 
00422 #ifndef ASSIGN_4V
00423 #define ASSIGN_4V( DST, V0, V1, V2, V3 ) \
00424 do {                                     \
00425    (DST)[0] = (V0);                      \
00426    (DST)[1] = (V1);                      \
00427    (DST)[2] = (V2);                      \
00428    (DST)[3] = (V3);                      \
00429 } while (0)
00430 #endif
00431 
00432 
00433 #ifdef __cplusplus
00434 }
00435 #endif
00436 
00437 #endif /* U_MATH_H */

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4