代码之家  ›  专栏  ›  技术社区  ›  robottobor

在x86上将float转换成int的最快方法是什么

  •  21
  • robottobor  · 技术社区  · 17 年前

    在x86 CPU上将浮点数转换为int的最快方法是什么?对于以下任意组合,最好是在C中或组件(可以在C中排列)中:

    • 32/64/80位浮点-32/64位整数

    我在寻找一种比让编译器来做还快的技术。

    10 回复  |  直到 17 年前
        2
  •  13
  •   Matthieu kelly    11 年前
        3
  •  9
  •   finnw    13 年前

    static const float Snapper=3<<22;
    
    union UFloatInt {
     int i;
     float f;
    };
    
    /** by Vlad Kaipetsky
    portable assuming FP24 set to nearest rounding mode
    efficient on x86 platform
    */
    inline int toInt( float fval )
    {
      Assert( fabs(fval)<=0x003fffff ); // only 23 bit values handled
      UFloatInt &fi = *(UFloatInt *)&fval;
      fi.f += Snapper;
      return ( (fi.i)&0x007fffff ) - 0x00400000;
    }
    
        5
  •  6
  •   dreamlax    17 年前

        6
  •  6
  •   phuclv    11 年前

    lua_Number

    /*
    @@ lua_number2int is a macro to convert lua_Number to int.
    @@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
    ** CHANGE them if you know a faster way to convert a lua_Number to
    ** int (with any rounding method and without throwing errors) in your
    ** system. In Pentium machines, a naive typecast from double to int
    ** in C is extremely slow, so any alternative is worth trying.
    */
    
    /* On a Pentium, resort to a trick */
    #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
        (defined(__i386) || defined (_M_IX86) || defined(__i386__))
    
    /* On a Microsoft compiler, use assembler */
    #if defined(_MSC_VER)
    
    #define lua_number2int(i,d)   __asm fld d   __asm fistp i
    #define lua_number2integer(i,n)     lua_number2int(i, n)
    
    /* the next trick should work on any Pentium, but sometimes clashes
       with a DirectX idiosyncrasy */
    #else
    
    union luai_Cast { double l_d; long l_l; };
    #define lua_number2int(i,d) \
      { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
    #define lua_number2integer(i,n)     lua_number2int(i, n)
    
    #endif
    
    /* this option always works, but may be slow */
    #else
    #define lua_number2int(i,d) ((i)=(int)(d))
    #define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
    
    #endif
    
        8
  •  3
  •   Cody Gray Felix    12 年前

    MSDN doc _mm_cvtsd_si64x

     #include <intrin.h>
     #pragma intrinsic(_mm_cvtsd_si64x)
     long long _inline double2int(const double &d)
     {
         return _mm_cvtsd_si64x(*(__m128d*)&d);
     }
    

            i=double2int(d);
    000000013F651085  cvtsd2si    rax,mmword ptr [rsp+38h]  
    000000013F65108C  mov         qword ptr [rsp+28h],rax  
    

        _control87(_RC_NEAR,_MCW_RC);
    

    float.h _control87()

    _asm fld d
    _asm fistp i
    
        9
  •  3
  •   the swine    12 年前

    i = (int)f

    int convert(float x)
    {
        int n;
        __asm {
            fld x
            fisttp n // the extra 't' means truncate
        }
        return n;
    }
    

    #include <xmmintrin.h>
    int convert(float x)
    {
        return _mm_cvtt_ss2si(_mm_load_ss(&x)); // extra 't' means truncate
    }
    

    fistp

    void Set_Trunc()
    {
        // cw is a 16-bit register [_ _ _ ic rc1 rc0 pc1 pc0 iem _ pm um om zm dm im]
        __asm {
            push ax // use stack to store the control word
            fnstcw word ptr [esp]
            fwait // needed to make sure the control word is there
            mov ax, word ptr [esp] // or pop ax ...
            or ax, 0xc00 // set both rc bits (alternately "or ah, 0xc")
            mov word ptr [esp], ax // ... and push ax
            fldcw word ptr [esp]
            pop ax
        }
    }
    
    void convertArray(int *dest, const float *src, int n)
    {
        Set_Trunc();
        __asm {
            mov eax, src
            mov edx, dest
            mov ecx, n // load loop variables
    
            cmp ecx, 0
            je bottom // handle zero-length arrays
    
        top:
            fld dword ptr [eax]
            fistp dword ptr [edx]
            loop top // decrement ecx, jump to top
        bottom:
        }
    }
    

        10
  •  -7
  •   user14504    17 年前