Go to the documentation of this file.00001
00002
00008
00009
00011
00012 #ifndef __ICEFPU_H__
00013 #define __ICEFPU_H__
00014
00015 #define SIGN_BITMASK 0x80000000
00016
00018 #define IR(x) ((udword&)(x))
00019
00021 #define SIR(x) ((sdword&)(x))
00022
00024 #define AIR(x) (IR(x)&0x7fffffff)
00025
00027 #define FR(x) ((float&)(x))
00028
00031
00032 #define IS_NEGATIVE_FLOAT(x) ((x)<0)
00033
00036 inline_ float FastFabs(float x)
00037 {
00038 udword FloatBits = IR(x)&0x7fffffff;
00039 return FR(FloatBits);
00040 }
00041
00043 inline_ float FastSqrt(float square)
00044 {
00045 #if defined(_MSC_VER) && not defined(_WIN64)
00046 float retval;
00047
00048 __asm {
00049 mov eax, square
00050 sub eax, 0x3F800000
00051 sar eax, 1
00052 add eax, 0x3F800000
00053 mov [retval], eax
00054 }
00055 return retval;
00056 #else
00057 return sqrt(square);
00058 #endif
00059 }
00060
00062 inline_ float fsat(float f)
00063 {
00064 udword y = (udword&)f & ~((sdword&)f >>31);
00065 return (float&)y;
00066 }
00067
00069 inline_ float frsqrt(float f)
00070 {
00071 float x = f * 0.5f;
00072 udword y = 0x5f3759df - ((udword&)f >> 1);
00073
00074 (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
00075
00076 return (float&)y;
00077 }
00078
00080 inline_ float InvSqrt(const float& x)
00081 {
00082 udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;
00083 float y = *(float*)&tmp;
00084 return y * (1.47f - 0.47f * x * y * y);
00085 }
00086
00089 inline_ float RSqrt(float number)
00090 {
00091 long i;
00092 float x2, y;
00093 const float threehalfs = 1.5f;
00094
00095 x2 = number * 0.5f;
00096 y = number;
00097 i = * (long *) &y;
00098 i = 0x5f3759df - (i >> 1);
00099 y = * (float *) &i;
00100 y = y * (threehalfs - (x2 * y * y));
00101
00102 return y;
00103 }
00104
00106 inline_ float fsqrt(float f)
00107 {
00108 udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
00109
00110
00111
00112 return (float&)y;
00113 }
00114
00116 inline_ float fepsilon(float f)
00117 {
00118 udword b = (udword&)f & 0xff800000;
00119 udword a = b | 0x00000001;
00120 (float&)a -= (float&)b;
00121
00122 return (float&)a;
00123 }
00124
00126 inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; }
00127 inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; }
00128 inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; }
00129 inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; }
00130
00131 inline_ bool IsValidFloat(float value)
00132 {
00133 if(IsNAN(value)) return false;
00134 if(IsIndeterminate(value)) return false;
00135 if(IsPlusInf(value)) return false;
00136 if(IsMinusInf(value)) return false;
00137 return true;
00138 }
00139
00140 #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x));
00141
00142
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00174 inline_ float ComputeFloatEpsilon()
00175 {
00176 float f = 1.0f;
00177 ((udword&)f)^=1;
00178 return f - 1.0f;
00179 }
00180
00181 inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
00182 {
00183 return x*x < epsilon;
00184 }
00185
00186 #define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0
00187 #define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0
00188 #define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0
00189 #define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0
00190
00191 #define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1
00192 #define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1
00193 #define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1
00194 #define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1
00195
00196 #define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2
00197 #define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2
00198 #define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2
00199 #define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2
00200
00201 #define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3
00202 #define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3
00203 #define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3
00204 #define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3
00205
00206 #define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4
00207 #define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4
00208 #define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4
00209 #define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4
00210
00211 #define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5
00212 #define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5
00213 #define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5
00214 #define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5
00215
00216 #define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6
00217 #define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6
00218 #define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6
00219 #define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6
00220
00221 #define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7
00222 #define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7
00223 #define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7
00224 #define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7
00225
00227 inline_ float FCMax2(float a, float b)
00228 {
00229 #if defined(_MSC_VER) && not defined(_WIN64)
00230 float Res;
00231 _asm fld [a]
00232 _asm fld [b]
00233 FCOMI_ST1
00234 FCMOVB_ST1
00235 _asm fstp [Res]
00236 _asm fcomp
00237 return Res;
00238 #else
00239 return (a > b) ? a : b;
00240 #endif
00241 }
00242
00244 inline_ float FCMin2(float a, float b)
00245 {
00246 #if defined(_MSC_VER) && not defined(_WIN64)
00247 float Res;
00248 _asm fld [a]
00249 _asm fld [b]
00250 FCOMI_ST1
00251 FCMOVNB_ST1
00252 _asm fstp [Res]
00253 _asm fcomp
00254 return Res;
00255 #else
00256 return (a < b) ? a : b;
00257 #endif
00258 }
00259
00261 inline_ float FCMax3(float a, float b, float c)
00262 {
00263 #if defined(_MSC_VER) && not defined(_WIN64)
00264 float Res;
00265 _asm fld [a]
00266 _asm fld [b]
00267 _asm fld [c]
00268 FCOMI_ST1
00269 FCMOVB_ST1
00270 FCOMI_ST2
00271 FCMOVB_ST2
00272 _asm fstp [Res]
00273 _asm fcompp
00274 return Res;
00275 #else
00276 return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
00277 #endif
00278 }
00279
00281 inline_ float FCMin3(float a, float b, float c)
00282 {
00283 #if defined(_MSC_VER) && not defined(_WIN64)
00284 float Res;
00285 _asm fld [a]
00286 _asm fld [b]
00287 _asm fld [c]
00288 FCOMI_ST1
00289 FCMOVNB_ST1
00290 FCOMI_ST2
00291 FCMOVNB_ST2
00292 _asm fstp [Res]
00293 _asm fcompp
00294 return Res;
00295 #else
00296 return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
00297 #endif
00298 }
00299
00300 inline_ int ConvertToSortable(float f)
00301 {
00302 int& Fi = (int&)f;
00303 int Fmask = (Fi>>31);
00304 Fi ^= Fmask;
00305 Fmask &= ~(1<<31);
00306 Fi -= Fmask;
00307 return Fi;
00308 }
00309
00310 enum FPUMode
00311 {
00312 FPU_FLOOR = 0,
00313 FPU_CEIL = 1,
00314 FPU_BEST = 2,
00315
00316 FPU_FORCE_DWORD = 0x7fffffff
00317 };
00318
00319 FUNCTION ICECORE_API FPUMode GetFPUMode();
00320 FUNCTION ICECORE_API void SaveFPU();
00321 FUNCTION ICECORE_API void RestoreFPU();
00322 FUNCTION ICECORE_API void SetFPUFloorMode();
00323 FUNCTION ICECORE_API void SetFPUCeilMode();
00324 FUNCTION ICECORE_API void SetFPUBestMode();
00325
00326 FUNCTION ICECORE_API void SetFPUPrecision24();
00327 FUNCTION ICECORE_API void SetFPUPrecision53();
00328 FUNCTION ICECORE_API void SetFPUPrecision64();
00329 FUNCTION ICECORE_API void SetFPURoundingChop();
00330 FUNCTION ICECORE_API void SetFPURoundingUp();
00331 FUNCTION ICECORE_API void SetFPURoundingDown();
00332 FUNCTION ICECORE_API void SetFPURoundingNear();
00333
00334 FUNCTION ICECORE_API int intChop(const float& f);
00335 FUNCTION ICECORE_API int intFloor(const float& f);
00336 FUNCTION ICECORE_API int intCeil(const float& f);
00337
00338 #endif // __ICEFPU_H__