mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
634 lines
17 KiB
634 lines
17 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// d3dflt.h
|
|
//
|
|
// Floating-point constants and operations on FP values.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef _D3DFLT_H_
|
|
#define _D3DFLT_H_
|
|
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef union tagFLOATINT32
|
|
{
|
|
FLOAT f;
|
|
INT32 i;
|
|
UINT32 u;
|
|
} FLOATINT32, *PFLOATINT32;
|
|
|
|
//
|
|
// Type-forcing macros to access FP as integer and vice-versa.
|
|
// ATTENTION - VC5's optimizer turns these macros into ftol sometimes,
|
|
// completely breaking them.
|
|
// Using FLOATINT32 works around the problem but is not as flexible,
|
|
// so the old code is kept around for the time when the compiler is fixed.
|
|
// Note that pointer casting with FLOATINT32 fails just as the direct
|
|
// pointer casting does, so it's not a remedy.
|
|
//
|
|
// Use these macros with extreme care.
|
|
//
|
|
|
|
#define ASFLOAT(i) (*(FLOAT *)&(i))
|
|
#define ASINT32(f) (*(INT32 *)&(f))
|
|
#define ASUINT32(f) (*(UINT32 *)&(f))
|
|
|
|
//
|
|
// FP constants.
|
|
//
|
|
|
|
// Powers of two for snap values. These should not be used in code.
|
|
#define CONST_TWOPOW0 1
|
|
#define CONST_TWOPOW1 2
|
|
#define CONST_TWOPOW2 4
|
|
#define CONST_TWOPOW3 8
|
|
#define CONST_TWOPOW4 16
|
|
#define CONST_TWOPOW5 32
|
|
#define CONST_TWOPOW6 64
|
|
#define CONST_TWOPOW7 128
|
|
#define CONST_TWOPOW8 256
|
|
#define CONST_TWOPOW9 512
|
|
#define CONST_TWOPOW10 1024
|
|
#define CONST_TWOPOW11 2048
|
|
#define CONST_TWOPOW12 4096
|
|
#define CONST_TWOPOW13 8192
|
|
#define CONST_TWOPOW14 16384
|
|
#define CONST_TWOPOW15 32768
|
|
#define CONST_TWOPOW16 65536
|
|
#define CONST_TWOPOW17 131072
|
|
#define CONST_TWOPOW18 262144
|
|
#define CONST_TWOPOW19 524288
|
|
#define CONST_TWOPOW20 1048576
|
|
#define CONST_TWOPOW21 2097152
|
|
#define CONST_TWOPOW22 4194304
|
|
#define CONST_TWOPOW23 8388608
|
|
#define CONST_TWOPOW24 16777216
|
|
#define CONST_TWOPOW25 33554432
|
|
#define CONST_TWOPOW26 67108864
|
|
#define CONST_TWOPOW27 134217728
|
|
#define CONST_TWOPOW28 268435456
|
|
#define CONST_TWOPOW29 536870912
|
|
#define CONST_TWOPOW30 1073741824
|
|
#define CONST_TWOPOW31 2147483648
|
|
#define CONST_TWOPOW32 4294967296
|
|
#define CONST_TWOPOW33 8589934592
|
|
#define CONST_TWOPOW34 17179869184
|
|
#define CONST_TWOPOW35 34359738368
|
|
#define CONST_TWOPOW36 68719476736
|
|
#define CONST_TWOPOW37 137438953472
|
|
#define CONST_TWOPOW38 274877906944
|
|
#define CONST_TWOPOW39 549755813888
|
|
#define CONST_TWOPOW40 1099511627776
|
|
#define CONST_TWOPOW41 2199023255552
|
|
#define CONST_TWOPOW42 4398046511104
|
|
#define CONST_TWOPOW43 8796093022208
|
|
#define CONST_TWOPOW44 17592186044416
|
|
#define CONST_TWOPOW45 35184372088832
|
|
#define CONST_TWOPOW46 70368744177664
|
|
#define CONST_TWOPOW47 140737488355328
|
|
#define CONST_TWOPOW48 281474976710656
|
|
#define CONST_TWOPOW49 562949953421312
|
|
#define CONST_TWOPOW50 1125899906842624
|
|
#define CONST_TWOPOW51 2251799813685248
|
|
#define CONST_TWOPOW52 4503599627370496
|
|
|
|
#define FLOAT_TWOPOW0 ((FLOAT)(CONST_TWOPOW0))
|
|
#define FLOAT_TWOPOW1 ((FLOAT)(CONST_TWOPOW1))
|
|
#define FLOAT_TWOPOW2 ((FLOAT)(CONST_TWOPOW2))
|
|
#define FLOAT_TWOPOW3 ((FLOAT)(CONST_TWOPOW3))
|
|
#define FLOAT_TWOPOW4 ((FLOAT)(CONST_TWOPOW4))
|
|
#define FLOAT_TWOPOW5 ((FLOAT)(CONST_TWOPOW5))
|
|
#define FLOAT_TWOPOW6 ((FLOAT)(CONST_TWOPOW6))
|
|
#define FLOAT_TWOPOW7 ((FLOAT)(CONST_TWOPOW7))
|
|
#define FLOAT_TWOPOW8 ((FLOAT)(CONST_TWOPOW8))
|
|
#define FLOAT_TWOPOW9 ((FLOAT)(CONST_TWOPOW9))
|
|
#define FLOAT_TWOPOW10 ((FLOAT)(CONST_TWOPOW10))
|
|
#define FLOAT_TWOPOW11 ((FLOAT)(CONST_TWOPOW11))
|
|
#define FLOAT_TWOPOW12 ((FLOAT)(CONST_TWOPOW12))
|
|
#define FLOAT_TWOPOW13 ((FLOAT)(CONST_TWOPOW13))
|
|
#define FLOAT_TWOPOW14 ((FLOAT)(CONST_TWOPOW14))
|
|
#define FLOAT_TWOPOW15 ((FLOAT)(CONST_TWOPOW15))
|
|
#define FLOAT_TWOPOW16 ((FLOAT)(CONST_TWOPOW16))
|
|
#define FLOAT_TWOPOW17 ((FLOAT)(CONST_TWOPOW17))
|
|
#define FLOAT_TWOPOW18 ((FLOAT)(CONST_TWOPOW18))
|
|
#define FLOAT_TWOPOW19 ((FLOAT)(CONST_TWOPOW19))
|
|
#define FLOAT_TWOPOW20 ((FLOAT)(CONST_TWOPOW20))
|
|
#define FLOAT_TWOPOW21 ((FLOAT)(CONST_TWOPOW21))
|
|
#define FLOAT_TWOPOW22 ((FLOAT)(CONST_TWOPOW22))
|
|
#define FLOAT_TWOPOW23 ((FLOAT)(CONST_TWOPOW23))
|
|
#define FLOAT_TWOPOW24 ((FLOAT)(CONST_TWOPOW24))
|
|
#define FLOAT_TWOPOW25 ((FLOAT)(CONST_TWOPOW25))
|
|
#define FLOAT_TWOPOW26 ((FLOAT)(CONST_TWOPOW26))
|
|
#define FLOAT_TWOPOW27 ((FLOAT)(CONST_TWOPOW27))
|
|
#define FLOAT_TWOPOW28 ((FLOAT)(CONST_TWOPOW28))
|
|
#define FLOAT_TWOPOW29 ((FLOAT)(CONST_TWOPOW29))
|
|
#define FLOAT_TWOPOW30 ((FLOAT)(CONST_TWOPOW30))
|
|
#define FLOAT_TWOPOW31 ((FLOAT)(CONST_TWOPOW31))
|
|
#define FLOAT_TWOPOW32 ((FLOAT)(CONST_TWOPOW32))
|
|
#define FLOAT_TWOPOW33 ((FLOAT)(CONST_TWOPOW33))
|
|
#define FLOAT_TWOPOW34 ((FLOAT)(CONST_TWOPOW34))
|
|
#define FLOAT_TWOPOW35 ((FLOAT)(CONST_TWOPOW35))
|
|
#define FLOAT_TWOPOW36 ((FLOAT)(CONST_TWOPOW36))
|
|
#define FLOAT_TWOPOW37 ((FLOAT)(CONST_TWOPOW37))
|
|
#define FLOAT_TWOPOW38 ((FLOAT)(CONST_TWOPOW38))
|
|
#define FLOAT_TWOPOW39 ((FLOAT)(CONST_TWOPOW39))
|
|
#define FLOAT_TWOPOW40 ((FLOAT)(CONST_TWOPOW40))
|
|
#define FLOAT_TWOPOW41 ((FLOAT)(CONST_TWOPOW41))
|
|
#define FLOAT_TWOPOW42 ((FLOAT)(CONST_TWOPOW42))
|
|
#define FLOAT_TWOPOW43 ((FLOAT)(CONST_TWOPOW43))
|
|
#define FLOAT_TWOPOW44 ((FLOAT)(CONST_TWOPOW44))
|
|
#define FLOAT_TWOPOW45 ((FLOAT)(CONST_TWOPOW45))
|
|
#define FLOAT_TWOPOW46 ((FLOAT)(CONST_TWOPOW46))
|
|
#define FLOAT_TWOPOW47 ((FLOAT)(CONST_TWOPOW47))
|
|
#define FLOAT_TWOPOW48 ((FLOAT)(CONST_TWOPOW48))
|
|
#define FLOAT_TWOPOW49 ((FLOAT)(CONST_TWOPOW49))
|
|
#define FLOAT_TWOPOW50 ((FLOAT)(CONST_TWOPOW50))
|
|
#define FLOAT_TWOPOW51 ((FLOAT)(CONST_TWOPOW51))
|
|
#define FLOAT_TWOPOW52 ((FLOAT)(CONST_TWOPOW52))
|
|
|
|
// Values that are smaller than the named value by the smallest
|
|
// representable amount. Since this depends on the type used
|
|
// there is no CONST form.
|
|
#define FLOAT_NEARTWOPOW31 ((FLOAT)2147483583)
|
|
#define FLOAT_NEARTWOPOW32 ((FLOAT)4294967167)
|
|
|
|
// Value close enough to zero to consider zero. This can't be too small
|
|
// but it can't be too large. In other words, it's picked by guessing.
|
|
#define FLOAT_NEARZERO (1e-5f)
|
|
|
|
// General FP constants.
|
|
#define FLOAT_E ((FLOAT)2.7182818284590452354)
|
|
|
|
// Integer value of first exponent bit in a float. Provides a scaling factor
|
|
// for exponent values extracted directly from float representation.
|
|
#define FLOAT_EXPSCALE ((FLOAT)0x00800000)
|
|
|
|
// Integer representation of 1.0f.
|
|
#define INT32_FLOAT_ONE 0x3f800000
|
|
|
|
#ifdef _X86_
|
|
|
|
// All FP values are loaded from memory so declare them all as global
|
|
// variables.
|
|
|
|
extern FLOAT g_fE;
|
|
extern FLOAT g_fZero;
|
|
extern FLOAT g_fNearZero;
|
|
extern FLOAT g_fHalf;
|
|
extern FLOAT g_fp95;
|
|
extern FLOAT g_fOne;
|
|
extern FLOAT g_fOneMinusEps;
|
|
extern FLOAT g_fExpScale;
|
|
extern FLOAT g_fOoExpScale;
|
|
extern FLOAT g_f255oTwoPow15;
|
|
extern FLOAT g_fOo255;
|
|
extern FLOAT g_fOo256;
|
|
extern FLOAT g_fTwoPow7;
|
|
extern FLOAT g_fTwoPow8;
|
|
extern FLOAT g_fTwoPow11;
|
|
extern FLOAT g_fTwoPow15;
|
|
extern FLOAT g_fOoTwoPow15;
|
|
extern FLOAT g_fTwoPow16;
|
|
extern FLOAT g_fOoTwoPow16;
|
|
extern FLOAT g_fTwoPow20;
|
|
extern FLOAT g_fOoTwoPow20;
|
|
extern FLOAT g_fTwoPow27;
|
|
extern FLOAT g_fOoTwoPow27;
|
|
extern FLOAT g_fTwoPow30;
|
|
extern FLOAT g_fTwoPow31;
|
|
extern FLOAT g_fNearTwoPow31;
|
|
extern FLOAT g_fOoTwoPow31;
|
|
extern FLOAT g_fOoNearTwoPow31;
|
|
extern FLOAT g_fTwoPow32;
|
|
extern FLOAT g_fNearTwoPow32;
|
|
extern FLOAT g_fTwoPow39;
|
|
extern FLOAT g_fTwoPow47;
|
|
|
|
#else
|
|
|
|
// Leave FP values as constants.
|
|
|
|
#define g_fE FLOAT_E
|
|
#define g_fNearZero FLOAT_NEARZERO
|
|
#define g_fZero (0.0f)
|
|
#define g_fHalf (0.5f)
|
|
#define g_fp95 (0.95f)
|
|
#define g_fOne (1.0f)
|
|
#define g_fOneMinusEps (1.0f - FLT_EPSILON)
|
|
#define g_fExpScale FLOAT_EXPSCALE
|
|
#define g_fOoExpScale ((FLOAT)(1.0 / (double)FLOAT_EXPSCALE))
|
|
#define g_f255oTwoPow15 ((FLOAT)(255.0 / (double)CONST_TWOPOW15))
|
|
#define g_fOo255 ((FLOAT)(1.0 / 255.0))
|
|
#define g_fOo256 ((FLOAT)(1.0 / 256.0))
|
|
#define g_fTwoPow7 FLOAT_TWOPOW7
|
|
#define g_fTwoPow8 FLOAT_TWOPOW8
|
|
#define g_fTwoPow11 FLOAT_TWOPOW11
|
|
#define g_fTwoPow15 FLOAT_TWOPOW15
|
|
#define g_fOoTwoPow15 ((FLOAT)(1.0 / (double)CONST_TWOPOW15))
|
|
#define g_fTwoPow16 FLOAT_TWOPOW16
|
|
#define g_fOoTwoPow16 ((FLOAT)(1.0 / (double)CONST_TWOPOW16))
|
|
#define g_fTwoPow20 FLOAT_TWOPOW20
|
|
#define g_fOoTwoPow20 ((FLOAT)(1.0 / (double)CONST_TWOPOW20))
|
|
#define g_fTwoPow27 FLOAT_TWOPOW27
|
|
#define g_fOoTwoPow27 ((FLOAT)(1.0 / (double)CONST_TWOPOW27))
|
|
#define g_fTwoPow30 FLOAT_TWOPOW30
|
|
#define g_fTwoPow31 FLOAT_TWOPOW31
|
|
#define g_fNearTwoPow31 FLOAT_NEARTWOPOW31
|
|
#define g_fOoTwoPow31 ((FLOAT)(1.0 / (double)CONST_TWOPOW31))
|
|
#define g_fOoNearTwoPow31 ((FLOAT)(1.0 / ((double)FLOAT_NEARTWOPOW31)))
|
|
#define g_fTwoPow32 FLOAT_TWOPOW32
|
|
#define g_fNearTwoPow32 FLOAT_NEARTWOPOW32
|
|
#define g_fTwoPow39 FLOAT_TWOPOW39
|
|
#define g_fTwoPow47 FLOAT_TWOPOW47
|
|
|
|
#endif // _X86_
|
|
|
|
//
|
|
// Conversion tables.
|
|
//
|
|
|
|
// Takes an unsigned byte to a float in [0.0, 1.0]. 257'th entry is
|
|
// also one to allow overflow.
|
|
extern FLOAT g_fUInt8ToFloat[257];
|
|
|
|
// Floating-point pinning values for float-int conversion.
|
|
extern double g_dSnap[33];
|
|
|
|
//
|
|
// x86 FP control for optimized FTOI and single-precision divides.
|
|
//
|
|
|
|
#ifdef _X86_
|
|
|
|
#define FPU_GET_MODE(uMode) \
|
|
__asm fnstcw WORD PTR uMode
|
|
#define FPU_SET_MODE(uMode) \
|
|
__asm fldcw WORD PTR uMode
|
|
#define FPU_SAFE_SET_MODE(uMode) \
|
|
__asm fnclex \
|
|
__asm fldcw WORD PTR uMode
|
|
|
|
#define FPU_MODE_CHOP_ROUND(uMode) \
|
|
((uMode) | 0xc00)
|
|
#define FPU_MODE_LOW_PRECISION(uMode) \
|
|
((uMode) & 0xfcff)
|
|
#define FPU_MODE_MASK_EXCEPTIONS(uMode) \
|
|
((uMode) | 0x3f)
|
|
|
|
#if DBG
|
|
|
|
#define ASSERT_CHOP_ROUND() \
|
|
{ \
|
|
WORD cw; \
|
|
__asm fnstcw cw \
|
|
DDASSERT((cw & 0xc00) == 0xc00); \
|
|
}
|
|
|
|
#else
|
|
|
|
#define ASSERT_CHOP_ROUND()
|
|
|
|
#endif // DBG
|
|
|
|
#else
|
|
|
|
// Initialize with zero to avoid use-before-set errors.
|
|
#define FPU_GET_MODE(uMode) \
|
|
((uMode) = 0)
|
|
#define FPU_SET_MODE(uMode)
|
|
#define FPU_SAFE_SET_MODE(uMode)
|
|
|
|
#define FPU_MODE_CHOP_ROUND(uMode) 0
|
|
#define FPU_MODE_LOW_PRECISION(uMode) 0
|
|
#define FPU_MODE_MASK_EXCEPTIONS(uMode) 0
|
|
|
|
#define ASSERT_CHOP_ROUND()
|
|
|
|
#endif // _X86_
|
|
|
|
//
|
|
// Single-precision FP functions.
|
|
// May produce invalid results for exceptional or denormal values.
|
|
// ATTENTION - Alpha exposes float math routines and they may be a small win.
|
|
//
|
|
|
|
#define COSF(fV) ((FLOAT)cos((double)(fV)))
|
|
#define SINF(fV) ((FLOAT)sin((double)(fV)))
|
|
#define SQRTF(fV) ((FLOAT)sqrt((double)(fV)))
|
|
#define POWF(fV, fE) ((FLOAT)pow((double)(fV), (double)(fE)))
|
|
|
|
// Approximate log and power functions using Jim Blinn's CG&A technique.
|
|
// Only work for positive values.
|
|
|
|
#ifdef POINTER_CASTING
|
|
|
|
__inline FLOAT
|
|
APPXLG2F(FLOAT f)
|
|
{
|
|
return (FLOAT)(ASINT32(f) - INT32_FLOAT_ONE) * g_fOoExpScale;
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXPOW2F(FLOAT f)
|
|
{
|
|
INT32 i = (INT32)(f * g_fExpScale) + INT32_FLOAT_ONE;
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXINVF(FLOAT f)
|
|
{
|
|
INT32 i = (INT32_FLOAT_ONE << 1) - ASINT32(f);
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXSQRTF(FLOAT f)
|
|
{
|
|
INT32 i = (ASINT32(f) >> 1) + (INT32_FLOAT_ONE >> 1);
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXISQRTF(FLOAT f)
|
|
{
|
|
INT32 i = INT32_FLOAT_ONE + (INT32_FLOAT_ONE >> 1) - (ASINT32(f) >> 1);
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXPOWF(FLOAT f, FLOAT exp)
|
|
{
|
|
INT32 i = (INT32)(exp * (ASINT32(f) - INT32_FLOAT_ONE)) + INT32_FLOAT_ONE;
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
#else
|
|
|
|
__inline FLOAT
|
|
APPXLG2F(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return (FLOAT)(fi.i - INT32_FLOAT_ONE) * g_fOoExpScale;
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXPOW2F(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.i = (INT32)(f * g_fExpScale) + INT32_FLOAT_ONE;
|
|
return fi.f;
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXINVF(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
fi.i = (INT32_FLOAT_ONE << 1) - fi.i;
|
|
return fi.f;
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXSQRTF(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
fi.i = (fi.i >> 1) + (INT32_FLOAT_ONE >> 1);
|
|
return fi.f;
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXISQRTF(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
fi.i = INT32_FLOAT_ONE + (INT32_FLOAT_ONE >> 1) - (fi.i >> 1);
|
|
return fi.f;
|
|
}
|
|
|
|
__inline FLOAT
|
|
APPXPOWF(FLOAT f, FLOAT exp)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
fi.i = (INT32)(exp * (fi.i - INT32_FLOAT_ONE)) + INT32_FLOAT_ONE;
|
|
return fi.f;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef _X86_
|
|
|
|
// Uses a table
|
|
float __fastcall TableInvSqrt(float value);
|
|
// Uses Jim Blinn's floating point trick
|
|
float __fastcall JBInvSqrt(float value);
|
|
|
|
#define ISQRTF(fV) TableInvSqrt(fV);
|
|
|
|
#ifdef POINTER_CASTING
|
|
|
|
// Strip sign bit in integer.
|
|
__inline FLOAT
|
|
ABSF(FLOAT f)
|
|
{
|
|
UINT32 i = ASUINT32(f) & 0x7fffffff;
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
// Toggle sign bit in integer.
|
|
__inline FLOAT
|
|
NEGF(FLOAT f)
|
|
{
|
|
UINT32 i = ASUINT32(f) ^ 0x80000000;
|
|
return ASFLOAT(i);
|
|
}
|
|
|
|
#else
|
|
|
|
// Strip sign bit in integer.
|
|
__inline FLOAT
|
|
ABSF(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
fi.u &= 0x7fffffff;
|
|
return fi.f;
|
|
}
|
|
|
|
// Toggle sign bit in integer.
|
|
__inline FLOAT
|
|
NEGF(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
fi.u ^= 0x80000000;
|
|
return fi.f;
|
|
}
|
|
|
|
#endif // POINTER_CASTING
|
|
|
|
// Requires chop rounding.
|
|
__inline INT32
|
|
SCALED_FRACTION(FLOAT f)
|
|
{
|
|
LARGE_INTEGER i;
|
|
|
|
__asm
|
|
{
|
|
fld f
|
|
fmul g_fTwoPow31
|
|
fistp i
|
|
}
|
|
|
|
return i.LowPart;
|
|
}
|
|
|
|
// Requires chop rounding.
|
|
__inline INT
|
|
FTOI(FLOAT f)
|
|
{
|
|
LARGE_INTEGER i;
|
|
|
|
__asm
|
|
{
|
|
fld f
|
|
fistp i
|
|
}
|
|
|
|
return i.LowPart;
|
|
}
|
|
|
|
// Requires chop rounding.
|
|
#define ICEILF(f) (FLOAT_LEZ(f) ? FTOI(f) : FTOI((f) + g_fOneMinusEps))
|
|
#define CEILF(f) ((FLOAT)ICEILF(f))
|
|
#define IFLOORF(f) (FLOAT_LTZ(f) ? FTOI((f) - g_fOneMinusEps) : FTOI(f))
|
|
#define FLOORF(f) ((FLOAT)IFLOORF(f))
|
|
|
|
#else // _X86_
|
|
|
|
#define ISQRTF(fV) (1.0f / (FLOAT)sqrt((double)(fV)))
|
|
#define ABSF(f) ((FLOAT)fabs((double)(f)))
|
|
#define NEGF(f) (-(f))
|
|
#define SCALED_FRACTION(f) ((INT32)((f) * g_fTwoPow31))
|
|
#define FTOI(f) ((INT)(f))
|
|
#define CEILF(f) ((FLOAT)ceil((double)(f)))
|
|
#define ICEILF(f) ((INT)CEILF(f))
|
|
#define FLOORF(f) ((FLOAT)floor((double)(f)))
|
|
#define IFLOORF(f) ((INT)FLOORF(f))
|
|
|
|
#endif // _X86_
|
|
|
|
//
|
|
// Overlapped divide support.
|
|
//
|
|
|
|
#ifdef _X86_
|
|
|
|
// Starts a divide directly from memory. Result field is provided for
|
|
// compatibility with non-x86 code that does the divide immediately.
|
|
#define FLD_BEGIN_DIVIDE(Num, Den, Res) { __asm fld Num __asm fdiv Den }
|
|
#define FLD_BEGIN_IDIVIDE(Num, Den, Res) { __asm fld Num __asm fidiv Den }
|
|
// Store a divide result directly to memory.
|
|
#define FSTP_END_DIVIDE(Res) { __asm fstp Res }
|
|
|
|
#else // _X86_
|
|
|
|
#define FLD_BEGIN_DIVIDE(Num, Den, Res) ((Res) = (Num) / (Den))
|
|
#define FLD_BEGIN_IDIVIDE(Num, Den, Res) ((Res) = (Num) / (FLOAT)(Den))
|
|
#define FSTP_END_DIVIDE(Res)
|
|
|
|
#endif // _X86_
|
|
|
|
//
|
|
// Specialized FP comparison functions.
|
|
//
|
|
// On the x86, it's faster to do compares with an integer cast
|
|
// than it is to do the fcom.
|
|
//
|
|
// The zero operations work for all normalized FP numbers, -0 included.
|
|
//
|
|
|
|
#ifdef _X86_
|
|
|
|
#define FLOAT_CMP_POS(fa, op, fb) (ASINT32(fa) op ASINT32(fb))
|
|
#define FLOAT_CMP_PONE(flt, op) (ASINT32(flt) op INT32_FLOAT_ONE)
|
|
|
|
#ifdef POINTER_CASTING
|
|
|
|
#define FLOAT_GTZ(flt) (ASINT32(flt) > 0)
|
|
#define FLOAT_LTZ(flt) (ASUINT32(flt) > 0x80000000)
|
|
#define FLOAT_GEZ(flt) (ASUINT32(flt) <= 0x80000000)
|
|
#define FLOAT_LEZ(flt) (ASINT32(flt) <= 0)
|
|
#define FLOAT_EQZ(flt) ((ASUINT32(flt) & 0x7fffffff) == 0)
|
|
#define FLOAT_NEZ(flt) ((ASUINT32(flt) & 0x7fffffff) != 0)
|
|
|
|
#else
|
|
|
|
__inline int FLOAT_GTZ(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return fi.i > 0;
|
|
}
|
|
__inline int FLOAT_LTZ(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return fi.u > 0x80000000;
|
|
}
|
|
__inline int FLOAT_GEZ(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return fi.u <= 0x80000000;
|
|
}
|
|
__inline int FLOAT_LEZ(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return fi.i <= 0;
|
|
}
|
|
__inline int FLOAT_EQZ(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return (fi.u & 0x7fffffff) == 0;
|
|
}
|
|
__inline int FLOAT_NEZ(FLOAT f)
|
|
{
|
|
FLOATINT32 fi;
|
|
fi.f = f;
|
|
return (fi.u & 0x7fffffff) != 0;
|
|
}
|
|
|
|
#endif // POINTER_CASTING
|
|
|
|
#else
|
|
|
|
#define FLOAT_GTZ(flt) ((flt) > g_fZero)
|
|
#define FLOAT_LTZ(flt) ((flt) < g_fZero)
|
|
#define FLOAT_GEZ(flt) ((flt) >= g_fZero)
|
|
#define FLOAT_LEZ(flt) ((flt) <= g_fZero)
|
|
#define FLOAT_EQZ(flt) ((flt) == g_fZero)
|
|
#define FLOAT_NEZ(flt) ((flt) != g_fZero)
|
|
#define FLOAT_CMP_POS(fa, op, fb) ((fa) op (fb))
|
|
#define FLOAT_CMP_PONE(flt, op) ((flt) op g_fOne)
|
|
|
|
#endif // _X86_
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // #ifndef _D3DFLT_H_
|