#include #include #include #include #define FP_BITS(fp) (*(DWORD *)&(fp)) #define FP_ABS_BITS(fp) (FP_BITS(fp)&0x7FFFFFFF) #define FP_SIGN_BIT(fp) (FP_BITS(fp)&0x80000000) #define FP_ONE_BITS 0x3F800000 // r = 1/p #define FP_INV(r,p) \ { \ int _i = 2 * FP_ONE_BITS - *(int *)&(p); \ r = *(float *)&_i; \ r = r * (2.0f - (p) * r); \ } #define FP_EXP(e,p) \ { \ int _i; \ e = -1.44269504f * (float)0x00800000 * (p); \ _i = (int)e + 0x3F800000; \ e = *(float *)&_i; \ } #define FP_NORM_TO_BYTE(i,p) \ { \ float _n = (p) + 1.0f; \ i = *(int *)&_n; \ if (i>= 0x40000000) i = 0xFF; \ else if (i <=0x3f800000) i = 0; \ else i = ((i)>> 15) & 0xFF; \ } inline unsigned long FP_NORM_TO_BYTE2(float p) { float fpTmp = p + 1.0f; return ((*(unsigned *)&fpTmp)>> 15) & 0xFF; } inline unsigned long FP_NORM_TO_BYTE3(float p) { float ftmp = p + 12582912.0f; return ((*(unsigned long *)&ftmp) & 0xFF); } static unsigned int fast_sqrt_table[0x10000]; // declare table of square roots typedef union FastSqrtUnion { float f; unsigned int i; } FastSqrtUnion; void build_sqrt_table() { unsigned int i; FastSqrtUnion s; for (i = 0; i <= 0x7FFF; i++) { // Build a float with the bit pattern i as mantissa // and an exponent of 0, stored as 127 s.i = (i << 8) | (0x7F << 23); s.f = (float)sqrt(s.f); // Take the square root then strip the first 7 bits of // the mantissa into the table fast_sqrt_table[i + 0x8000] = (s.i & 0x7FFFFF); // Repeat the process, this time with an exponent of 1, // stored as 128 s.i = (i << 8) | (0x80 << 23); s.f = (float)sqrt(s.f); fast_sqrt_table[i] = (s.i & 0x7FFFFF); } } inline float fastsqrt(float n) { if (FP_BITS(n) == 0) return 0.0; // check for square root of 0 FP_BITS(n) = fast_sqrt_table[(FP_BITS(n)>> 8) & 0xFFFF] | ((((FP_BITS(n) - 0x3F800000)>> 1) + 0x3F800000) & 0x7F800000); return n; } // At the assembly level the recommended workaround for the second FIST bug is the same for the first; // inserting the FRNDINT instruction immediately preceding the FIST instruction. __forceinline void FloatToInt(int *int_pointer, float f) { __asm fld f __asm mov edx,int_pointer __asm FRNDINT __asm fistp dword ptr [edx]; } int main(int argc, char* argv[]) { float t, it, test_sqrt; int i = 0; build_sqrt_table(); t = 1234.121234f; test_sqrt = fastsqrt(t); printf("sqrt expected %20.10f approx %20.10f\n", sqrt(t), test_sqrt); FP_INV(it,t); printf("inv expected %20.10f approx %20.10f\n", 1/t, it); i = 0xdeafbabe; FloatToInt(&i, t); printf("ftol expected %d actual %d %08X\n", (int)t, i, i); return 0; }

AltStyle によって変換されたページ (->オリジナル) /