#ifndef MMATH_H
#define MMATH_H
#include "glheader.h"
#include "imports.h"
#if defined(__GNUC__) && defined(__i386__)
#define DEFAULT_X86_FPU 0x037f
#define FAST_X86_FPU 0x003f
#if defined(NO_FAST_MATH)
#define START_FAST_MATH(x) \
do { \
static GLuint mask = DEFAULT_X86_FPU; \
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
__asm__ ( "fldcw %0" : : "m" (mask) ); \
} while (0)
#else
#define START_FAST_MATH(x) \
do { \
static GLuint mask = FAST_X86_FPU; \
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
__asm__ ( "fldcw %0" : : "m" (mask) ); \
} while (0)
#endif
#define END_FAST_MATH(x) \
do { \
__asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
} while (0)
#define HAVE_FAST_MATH
#elif defined(__WATCOMC__) && !defined(NO_FAST_MATH)
void START_FAST_MATH2(unsigned short *x);
#pragma aux START_FAST_MATH2 = \
"fstcw word ptr [esi]" \
"or word ptr [esi], 0x3f" \
"fldcw word ptr [esi]" \
parm [esi] \
modify exact [];
void END_FAST_MATH2(unsigned short *x);
#pragma aux END_FAST_MATH2 = \
"fldcw word ptr [esi]" \
parm [esi] \
modify exact [];
#define START_FAST_MATH(x) START_FAST_MATH2(& x)
#define END_FAST_MATH(x) END_FAST_MATH2(& x)
#define HAVE_FAST_MATH
#else
#define START_FAST_MATH(x) x = 0
#define END_FAST_MATH(x) (void)(x)
#if defined(macintosh) || defined(__powerpc__)
#define HAVE_FAST_MATH
#endif
#endif
extern float gl_sqrt(float x);
#ifdef FAST_MATH
#if defined(__WATCOMC__) && defined(USE_X86_ASM)
# define GL_SQRT(X) asm_sqrt(X)
#else
# define GL_SQRT(X) gl_sqrt(X)
#endif
#else
# define GL_SQRT(X) sqrt(X)
#endif
#define NORMALIZE_3FV( V ) \
do { \
GLfloat len = (GLfloat) LEN_SQUARED_3FV(V); \
if (len) { \
len = (GLfloat) (1.0 / GL_SQRT(len)); \
(V)[0] = (GLfloat) ((V)[0] * len); \
(V)[1] = (GLfloat) ((V)[1] * len); \
(V)[2] = (GLfloat) ((V)[2] * len); \
} \
} while(0)
#define LEN_3FV( V ) (GL_SQRT((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2]))
#define LEN_2FV( V ) (GL_SQRT((V)[0]*(V)[0]+(V)[1]*(V)[1]))
#define LEN_SQUARED_3FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2])
#define LEN_SQUARED_2FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1])
#if defined(XFree86LOADER) && defined(IN_MODULE)
#define CEILF(x) ((GLfloat) xf86ceil(x))
#define FLOORF(x) ((GLfloat) xf86floor(x))
#define FABSF(x) ((GLfloat) xf86fabs(x))
#elif defined(__gnu_linux__)
#define CEILF(x) ceilf(x)
#define FLOORF(x) floorf(x)
#define FABSF(x) fabsf(x)
#else
#define CEILF(x) ((GLfloat) ceil(x))
#define FLOORF(x) ((GLfloat) floor(x))
#define FABSF(x) ((GLfloat) fabs(x))
#endif
#if defined(__i386__) || defined(__sparc__) || defined(__s390x__) || \
defined(__powerpc__) || defined(__AMD64__) || \
( defined(__alpha__) && ( defined(__IEEE_FLOAT) || !defined(VMS) ) )
#define USE_IEEE
#endif
#define GET_FLOAT_BITS(x) ((fi_type *) &(x))->i
#if defined(USE_SPARC_ASM) && defined(__GNUC__) && defined(__sparc__)
static INLINE int iround(float f)
{
int r;
__asm__ ("fstoi %1, %0" : "=f" (r) : "f" (f));
return r;
}
#define IROUND(x) iround(x)
#elif defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
static INLINE int iround(float f)
{
int r;
__asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
return r;
}
#define IROUND(x) iround(x)
static INLINE int ifloor(float f)
{
int ai, bi;
double af, bf;
af = (3 << 22) + 0.5 + (double)f;
bf = (3 << 22) + 0.5 - (double)f;
__asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
__asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
return (ai - bi) >> 1;
}
#define IFLOOR(x) ifloor(x)
static INLINE int iceil(float f)
{
int ai, bi;
double af, bf;
af = (3 << 22) + 0.5 + (double)f;
bf = (3 << 22) + 0.5 - (double)f;
__asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
__asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
return (ai - bi + 1) >> 1;
}
#define ICEIL(x) iceil(x)
#elif defined(USE_X86_ASM) && defined(__MSC__) && defined(__WIN32__)
static INLINE int iround(float f)
{
int r;
_asm {
fld f
fistp r
}
return r;
}
#define IROUND(x) iround(x)
#elif defined(USE_X86_ASM) && defined(__WATCOMC__)
long iround(float f);
#pragma aux iround = \
"push eax" \
"fistp dword ptr [esp]" \
"pop eax" \
parm [8087] \
value [eax] \
modify exact [eax];
#define IROUND(x) iround(x)
float asm_sqrt (float x);
#pragma aux asm_sqrt = \
"fsqrt" \
parm [8087] \
value [8087] \
modify exact [];
#endif
#ifndef IROUND
#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
#endif
#ifndef IROUND_POS
#ifdef DEBUG
#define IROUND_POS(f) (ASSERT((f) >= 0.0F), IROUND(f))
#else
#define IROUND_POS(f) (IROUND(f))
#endif
#endif
#ifndef IFLOOR
static INLINE int ifloor(float f)
{
#ifdef USE_IEEE
int ai, bi;
double af, bf;
union { int i; float f; } u;
af = (3 << 22) + 0.5 + (double)f;
bf = (3 << 22) + 0.5 - (double)f;
u.f = af; ai = u.i;
u.f = bf; bi = u.i;
return (ai - bi) >> 1;
#else
int i = IROUND(f);
return (i > f) ? i - 1 : i;
#endif
}
#define IFLOOR(x) ifloor(x)
#endif
#ifndef ICEIL
static INLINE int iceil(float f)
{
#ifdef USE_IEEE
int ai, bi;
double af, bf;
union { int i; float f; } u;
af = (3 << 22) + 0.5 + (double)f;
bf = (3 << 22) + 0.5 - (double)f;
u.f = af; ai = u.i;
u.f = bf; bi = u.i;
return (ai - bi + 1) >> 1;
#else
int i = IROUND(f);
return (i < f) ? i + 1 : i;
#endif
}
#define ICEIL(x) iceil(x)
#endif
#define IEEE_ONE 0x3f800000
#define IEEE_0996 0x3f7f0000
#if defined(USE_IEEE) && !defined(DEBUG)
#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
do { \
union { GLfloat r; GLuint i; } __tmp; \
__tmp.r = (f); \
ub = ((__tmp.i >= IEEE_0996) \
? ((GLint)__tmp.i < 0) ? (GLubyte)0 : (GLubyte)255 \
: (__tmp.r = __tmp.r*(255.0F/256.0F) + 32768.0F, \
(GLubyte)__tmp.i)); \
} while (0)
#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
UNCLAMPED_FLOAT_TO_UBYTE(ub, f)
#define COPY_FLOAT( dst, src ) \
((fi_type *) &(dst))->i = ((fi_type *) &(src))->i
#else
#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
ub = ((GLubyte) IROUND(CLAMP((f), 0.0F, 1.0F) * 255.0F))
#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
ub = ((GLubyte) IROUND((f) * 255.0F))
#define COPY_FLOAT( dst, src ) (dst) = (src)
#endif
extern float _mesa_ubyte_to_float_color_tab[256];
#define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)]
#define FLOAT_TO_UBYTE(X) ((GLubyte) (GLint) ((X) * 255.0F))
#define BYTE_TO_FLOAT(B) ((2.0F * (B) + 1.0F) * (1.0F/255.0F))
#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 )
#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F))
#define FLOAT_TO_USHORT(X) ((GLushort) (GLint) ((X) * 65535.0F))
#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 )
#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0F))
#define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0))
#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F))
#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) )
#define BYTE_TO_UBYTE(b) ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b)))
#define SHORT_TO_UBYTE(s) ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7)))
#define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8))
#define INT_TO_UBYTE(i) ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23)))
#define UINT_TO_UBYTE(i) ((GLubyte) ((i) >> 24))
#define BYTE_TO_USHORT(b) ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255)))
#define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b))
#define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767))))
#define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
#define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
#define UNCLAMPED_FLOAT_TO_USHORT(us, f) \
us = ( (GLushort) IROUND( CLAMP((f), 0.0, 1.0) * 65535.0F) )
#define CLAMPED_FLOAT_TO_USHORT(us, f) \
us = ( (GLushort) IROUND( (f) * 65535.0F) )
#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT)))
#define INTERP_UB( t, dstub, outub, inub ) \
do { \
GLfloat inf = UBYTE_TO_FLOAT( inub ); \
GLfloat outf = UBYTE_TO_FLOAT( outub ); \
GLfloat dstf = LINTERP( t, outf, inf ); \
UNCLAMPED_FLOAT_TO_UBYTE( dstub, dstf ); \
} while (0)
#define INTERP_CHAN( t, dstc, outc, inc ) \
do { \
GLfloat inf = CHAN_TO_FLOAT( inc ); \
GLfloat outf = CHAN_TO_FLOAT( outc ); \
GLfloat dstf = LINTERP( t, outf, inf ); \
UNCLAMPED_FLOAT_TO_CHAN( dstc, dstf ); \
} while (0)
#define INTERP_UI( t, dstui, outui, inui ) \
dstui = (GLuint) (GLint) LINTERP( (t), (GLfloat) (outui), (GLfloat) (inui) )
#define INTERP_F( t, dstf, outf, inf ) \
dstf = LINTERP( t, outf, inf )
#define INTERP_4F( t, dst, out, in ) \
do { \
dst[0] = LINTERP( (t), (out)[0], (in)[0] ); \
dst[1] = LINTERP( (t), (out)[1], (in)[1] ); \
dst[2] = LINTERP( (t), (out)[2], (in)[2] ); \
dst[3] = LINTERP( (t), (out)[3], (in)[3] ); \
} while (0)
#define INTERP_3F( t, dst, out, in ) \
do { \
dst[0] = LINTERP( (t), (out)[0], (in)[0] ); \
dst[1] = LINTERP( (t), (out)[1], (in)[1] ); \
dst[2] = LINTERP( (t), (out)[2], (in)[2] ); \
} while (0)
#define INTERP_4CHAN( t, dst, out, in ) \
do { \
INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] ); \
INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] ); \
INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] ); \
INTERP_CHAN( (t), (dst)[3], (out)[3], (in)[3] ); \
} while (0)
#define INTERP_3CHAN( t, dst, out, in ) \
do { \
INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] ); \
INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] ); \
INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] ); \
} while (0)
#define INTERP_SZ( t, vec, to, out, in, sz ) \
do { \
switch (sz) { \
case 4: vec[to][3] = LINTERP( (t), (vec)[out][3], (vec)[in][3] ); \
case 3: vec[to][2] = LINTERP( (t), (vec)[out][2], (vec)[in][2] ); \
case 2: vec[to][1] = LINTERP( (t), (vec)[out][1], (vec)[in][1] ); \
case 1: vec[to][0] = LINTERP( (t), (vec)[out][0], (vec)[in][0] ); \
} \
} while(0)
#ifdef FIXED_14
#define FIXED_ONE 0x00004000
#define FIXED_HALF 0x00002000
#define FIXED_FRAC_MASK 0x00003FFF
#define FIXED_SCALE 16384.0f
#define FIXED_SHIFT 14
#else
#define FIXED_ONE 0x00000800
#define FIXED_HALF 0x00000400
#define FIXED_FRAC_MASK 0x000007FF
#define FIXED_SCALE 2048.0f
#define FIXED_SHIFT 11
#endif
#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
#define FIXED_EPSILON 1
#define FloatToFixed(X) (IROUND((X) * FIXED_SCALE))
#define IntToFixed(I) ((I) << FIXED_SHIFT)
#define FixedToInt(X) ((X) >> FIXED_SHIFT)
#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT)
#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
#define FixedFloor(X) ((X) & FIXED_INT_MASK)
#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
#define PosFloatToFixed(X) FloatToFixed(X)
#define SignedFloatToFixed(X) FloatToFixed(X)
#ifdef USE_IEEE
static INLINE int IS_INF_OR_NAN( float x )
{
union {float f; int i;} tmp;
tmp.f = x;
return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
}
#elif defined(isfinite)
#define IS_INF_OR_NAN(x) (!isfinite(x))
#elif defined(finite)
#define IS_INF_OR_NAN(x) (!finite(x))
#elif __VMS
#define IS_INF_OR_NAN(x) (!finite(x))
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define IS_INF_OR_NAN(x) (!isfinite(x))
#else
#define IS_INF_OR_NAN(x) (!finite(x))
#endif
#ifdef USE_IEEE
#if 0
static INLINE GLfloat LOG2(GLfloat x)
{
const GLfloat y = x * x * x * x;
const GLuint ix = *((GLuint *) &y);
const GLuint exp = (ix >> 23) & 0xFF;
const GLint log2 = ((GLint) exp) - 127;
return (GLfloat) log2 * (1.0 / 4.0);
}
#endif
static INLINE GLfloat LOG2(GLfloat val)
{
GLint *exp_ptr = (GLint *) &val;
GLint x = *exp_ptr;
const GLint log_2 = ((x >> 23) & 255) - 128;
x &= ~(255 << 23);
x += 127 << 23;
*exp_ptr = x;
val = ((-1.0f/3) * val + 2) * val - 2.0f/3;
return val + log_2;
}
#else
#define LOG2(x) ((GLfloat) (log(x) * 1.442695F))
#endif
extern void
_mesa_init_math(void);
extern GLuint
_mesa_bitcount(GLuint n);
#endif