util: Don't destroy shaders null shaders
[mesa.git] / src / gallium / auxiliary / util / u_math.h
index aa4fa17b5968fbd1f31b40911b9aeb37a96cf9c4..30555f92a6d021d9eede41b7e4204aacda1625a4 100644 (file)
@@ -40,7 +40,7 @@
 
 
 #include "pipe/p_compiler.h"
-#include "pipe/p_debug.h"
+#include "util/u_debug.h"
 
 
 #ifdef __cplusplus
@@ -53,11 +53,11 @@ __inline double ceil(double val)
 {
    double ceil_val;
 
-   if((val - (long) val) == 0) {
+   if ((val - (long) val) == 0) {
       ceil_val = val;
    }
    else {
-      if(val > 0) {
+      if (val > 0) {
          ceil_val = (long) val + 1;
       }
       else {
@@ -73,11 +73,11 @@ __inline double floor(double val)
 {
    double floor_val;
 
-   if((val - (long) val) == 0) {
+   if ((val - (long) val) == 0) {
       floor_val = val;
    }
    else {
-      if(val > 0) {
+      if (val > 0) {
          floor_val = (long) val;
       }
       else {
@@ -118,6 +118,11 @@ __inline double __cdecl atan2(double val)
 #endif
 
 
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+
+
 #if defined(_MSC_VER) 
 
 #if _MSC_VER < 1400 && !defined(__cplusplus) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
@@ -168,7 +173,10 @@ static INLINE float logf( float f )
 #undef logf
 #define logf(x) ((float)log((double)(x)))
 #endif /* logf */
-#endif
+
+#define isfinite(x) _finite((double)(x))
+#define isnan(x) _isnan((double)(x))
+#endif /* _MSC_VER < 1400 && !defined(__cplusplus) */
 
 static INLINE double log2( double x )
 {
@@ -176,6 +184,18 @@ static INLINE double log2( double x )
    return log( x ) * invln2;
 }
 
+static INLINE double
+round(double x)
+{
+   return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5);
+}
+
+static INLINE float
+roundf(float x)
+{
+   return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f);
+}
+
 #endif /* _MSC_VER */
 
 
@@ -189,7 +209,10 @@ static INLINE double log2( double x )
 extern float pow2_table[POW2_TABLE_SIZE];
 
 
-
+/**
+ * Initialize math module.  This should be called before using any
+ * other functions in this module.
+ */
 extern void
 util_init_math(void);
 
@@ -216,23 +239,24 @@ util_fast_exp2(float x)
    int32_t ipart;
    float fpart, mpart;
    union fi epart;
-   
+
    if(x > 129.00000f)
       return 3.402823466e+38f;
-   
-   if(x < -126.99999f)
+
+   if (x < -126.99999f)
       return 0.0f;
 
    ipart = (int32_t) x;
    fpart = x - (float) ipart;
-   
+
    /* same as
     *   epart.f = (float) (1 << ipart)
-    * but faster and without integer overflow for ipart > 31 */
+    * but faster and without integer overflow for ipart > 31
+    */
    epart.i = (ipart + 127 ) << 23;
-   
+
    mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)];
-   
+
    return epart.f * mpart;
 }
 
@@ -254,6 +278,9 @@ util_fast_exp(float x)
 extern float log2_table[LOG2_TABLE_SIZE];
 
 
+/**
+ * Fast approximation to log2(x).
+ */
 static INLINE float
 util_fast_log2(float x)
 {
@@ -267,12 +294,22 @@ util_fast_log2(float x)
 }
 
 
+/**
+ * Fast approximation to x^y.
+ */
 static INLINE float
 util_fast_pow(float x, float y)
 {
    return util_fast_exp2(util_fast_log2(x) * y);
 }
 
+/* Note that this counts zero as a power of two.
+ */
+static INLINE boolean
+util_is_power_of_two( unsigned v )
+{
+   return (v & (v-1)) == 0;
+}
 
 
 /**
@@ -284,8 +321,8 @@ util_ifloor(float f)
    int ai, bi;
    double af, bf;
    union fi u;
-   af = (3 << 22) + 0.5 + (double)f;
-   bf = (3 << 22) + 0.5 - (double)f;
+   af = (3 << 22) + 0.5 + (double) f;
+   bf = (3 << 22) + 0.5 - (double) f;
    u.f = (float) af;  ai = u.i;
    u.f = (float) bf;  bi = u.i;
    return (ai - bi) >> 1;
@@ -305,9 +342,9 @@ util_iround(float f)
 #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
    int r;
    _asm {
-        fld f
-        fistp r
-       }
+      fld f
+      fistp r
+   }
    return r;
 #else
    if (f >= 0.0f)
@@ -318,18 +355,51 @@ util_iround(float f)
 }
 
 
+/**
+ * Approximate floating point comparison
+ */
+static INLINE boolean
+util_is_approx(float a, float b, float tol)
+{
+   return fabs(b - a) <= tol;
+}
+
+
+/**
+ * Test if x is NaN or +/- infinity.
+ */
+static INLINE boolean
+util_is_inf_or_nan(float x)
+{
+   union fi tmp;
+   tmp.f = x;
+   return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
+}
+
 
-#if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
 /**
  * Find first bit set in word.  Least significant bit is 1.
  * Return 0 if no bits set.
  */
+#if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64)
+unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask);
+#pragma intrinsic(_BitScanForward)
+static INLINE
+unsigned long ffs( unsigned long u )
+{
+   unsigned long i;
+   if (_BitScanForward(&i, u))
+      return i + 1;
+   else
+      return 0;
+}
+#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
 static INLINE
 unsigned ffs( unsigned u )
 {
    unsigned i;
 
-   if( u == 0 ) {
+   if (u == 0) {
       return 0;
    }
 
@@ -339,8 +409,26 @@ unsigned ffs( unsigned u )
 
    return i;
 }
+#elif defined(__MINGW32__)
+#define ffs __builtin_ffs
 #endif
 
+#ifdef __MINGW32__
+#define ffs __builtin_ffs
+#endif
+
+
+/* Could also binary search for the highest bit.
+ */
+static INLINE unsigned
+util_unsigned_logbase2(unsigned n)
+{
+   unsigned log2 = 0;
+   while (n >>= 1)
+      ++log2;
+   return log2;
+}
+
 
 /**
  * Return float bits.
@@ -354,7 +442,10 @@ fui( float f )
 }
 
 
-
+/**
+ * Convert ubyte to float in [0, 1].
+ * XXX a 256-entry lookup table would be slightly faster.
+ */
 static INLINE float
 ubyte_to_float(ubyte ub)
 {
@@ -385,19 +476,132 @@ float_to_ubyte(float f)
 }
 
 
+/**
+ * Calc log base 2
+ */
+static INLINE unsigned
+util_logbase2(unsigned n)
+{
+   unsigned log2 = 0;
+   while (n >>= 1)
+      ++log2;
+   return log2;
+}
+
+
+/**
+ * Returns the smallest power of two >= x
+ */
+static INLINE unsigned
+util_next_power_of_two(unsigned x)
+{
+   unsigned i;
+
+   if (x == 0)
+      return 1;
+
+   --x;
+
+   for (i = 1; i < sizeof(unsigned) * 8; i <<= 1)
+      x |= x >> i;
+
+   return x + 1;
+}
+
+
+/**
+ * Return number of bits set in n.
+ */
+static INLINE unsigned
+util_bitcount(unsigned n)
+{
+#if defined(PIPE_CC_GCC)
+   return __builtin_popcount(n);
+#else
+   /* K&R classic bitcount.
+    *
+    * For each iteration, clear the LSB from the bitfield.
+    * Requires only one iteration per set bit, instead of
+    * one iteration per bit less than highest set bit.
+    */
+   unsigned bits = 0;
+   for (bits; n; bits++) {
+      n &= n - 1;
+   }
+   return bits;
+#endif
+}
+
+
+/**
+ * Reverse byte order of a 32 bit word.
+ */
+static INLINE uint32_t
+util_bswap32(uint32_t n)
+{
+#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403)
+   return __builtin_bswap32(n);
+#else
+   return (n >> 24) |
+          ((n >> 8) & 0x0000ff00) |
+          ((n << 8) & 0x00ff0000) |
+          (n << 24);
+#endif
+}
+
+
+/**
+ * Reverse byte order of a 16 bit word.
+ */
+static INLINE uint16_t
+util_bswap16(uint16_t n)
+{
+   return (n >> 8) |
+          (n << 8);
+}
+
 
+/**
+ * Clamp X to [MIN, MAX].
+ * This is a macro to allow float, int, uint, etc. types.
+ */
 #define CLAMP( X, MIN, MAX )  ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
 
 #define MIN2( A, B )   ( (A)<(B) ? (A) : (B) )
 #define MAX2( A, B )   ( (A)>(B) ? (A) : (B) )
 
+#define MIN3( A, B, C ) MIN2( MIN2( A, B ), C )
+#define MAX3( A, B, C ) MAX2( MAX2( A, B ), C )
+
+#define MIN4( A, B, C, D ) MIN2( MIN2( A, B ), MIN2(C, D) )
+#define MAX4( A, B, C, D ) MAX2( MAX2( A, B ), MAX2(C, D) )
+
 
+/**
+ * Align a value, only works pot alignemnts.
+ */
 static INLINE int
 align(int value, int alignment)
 {
    return (value + alignment - 1) & ~(alignment - 1);
 }
 
+/**
+ * Works like align but on npot alignments.
+ */
+static INLINE size_t
+util_align_npot(size_t value, size_t alignment)
+{
+   if (value % alignment)
+      return value + (alignment - (value % alignment));
+   return value;
+}
+
+static INLINE unsigned
+u_minify(unsigned value, unsigned levels)
+{
+    return MAX2(1, value >> levels);
+}
 
 #ifndef COPY_4V
 #define COPY_4V( DST, SRC )         \
@@ -426,6 +630,18 @@ do {                                     \
 #endif
 
 
+static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits)
+{
+   return value < 0 ? 0 : (uint32_t)(value * (1<<frac_bits));
+}
+
+static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits)
+{
+   return (int32_t)(value * (1<<frac_bits));
+}
+
+
+
 #ifdef __cplusplus
 }
 #endif