2014-02-06 23 views
1

MSVC 2012沒有rint()函數。對於32位,我使用以下內容:在x86-64中實現rint()

double rint(double x) { 
    __asm { 
     fld x 
     frndint 
    } 
} 

這不適用於x64。有_mm_round_sd()但需要SSE4。什麼是獲得相同行爲的有效的無分支方式?

+1

如果你關心的指令數量足夠靈活,不管候選者是否真的無分支,幾個​​用於將float四捨五入到最接近的整數的C實現在http://blog.frama-c.com/上。 index.php?post/2013/05/02/nearbyintf1及以下。將這些調整爲雙精度是調整一對常量的問題。 (注意:第一個實現不會舍入到最接近的偶數,但會舍入到最接近的整數,並且只與最接近的不同 - 即使是關係也不同)。 –

回答

2

RINT 64位模式

#include <emmintrin.h> 

static inline double rint (double const x) { 
    return (double)_mm_cvtsd_si32(_mm_load_sd(&x)); 
} 

見昂納霧的Optimizing C++ manual爲lrint

32位模式

// Example 14.19 
static inline int lrint (double const x) { // Round to nearest integer 
    int n; 
    #if defined(__unix__) || defined(__GNUC__) 
    // 32-bit Linux, Gnu/AT&T syntax: 
    __asm ("fldl %1 \n fistpl %0 " : "=m"(n) : "m"(x) : "memory"); 
    #else 
    // 32-bit Windows, Intel/MASM syntax: 
    __asm fld qword ptr x; 
    __asm fistp dword ptr n; 
    #endif 
    return n; 
} 

64位模式

// Example 14.21. // Only for SSE2 or x64 
#include <emmintrin.h> 

static inline int lrint (double const x) { 
    return _mm_cvtsd_si32(_mm_load_sd(&x)); 
} 

編輯: 我剛剛意識到這種方法將限制值爲+/- 2^31。如果你想要SSE2版本更大的版本,這很複雜(但SSE4.1很容易)。例如,查看文件vectorf128.h中Agner Fog's Vector Class中的圓函數。