在x86-64中实现rint() [英] Implementing rint() in x86-64

查看:337
本文介绍了在x86-64中实现rint()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MSVC 2012没有rint()函数。对于32位,我使用以下内容:

pre $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
fld x
frndint
}
}

在x64中不起作用。有_mm_round_sd()但需要SSE4。什么是有效的无分支方式获得相同的行为?

解决方案

64位模式

  #include< emmintrin.h> 

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

查看Agner Fog's 为C ++优化C ++手册

32位模式

  //例14.19 
static inline int lrint(double const x){//舍入到最近的整数
int n;
#if defined(__ unix__)||定义(__ GNUC__)
// 32位Linux,Gnu / AT& T语法:
__asm(fldl%1 \\\
fistpl%0:= m(n):m (x):记忆);
#else
// 32位Windows,Intel / MASM语法:
__asm fld qword ptr x;
__asm fistp dword ptr n;
#endif
return n;

$ / code $ / pre
$ b $ 64位模式

  //例14.21。 //仅适用于SSE2或x64 
#include< emmintrin.h>

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

code



我刚刚意识到该方法将限制值为+/- 2 ^ 31。如果你想要SSE2版本更大的版本,这很复杂(但SSE4.1很容易)。例如,在文件vectorf128.h中查看Agner Fog的Vector类中的round函数。


MSVC 2012 doesn't have the rint() function. For 32-bit, I'm using the following:

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

This doesn't work in x64. There's _mm_round_sd() but that requires SSE4. What is an efficient preferrably branchless way of getting the same behavior?

解决方案

rint 64-bit mode

#include <emmintrin.h>

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

See Agner Fog's Optimizing C++ manual for lrint

32-bit mode

// 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-bit mode

// 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));
}

Edit: I just realized that this method will limit the values to to +/- 2^31. If you want a version with a larger range with SSE2 it's complicated (but easy with SSE4.1). See the round function in Agner Fog's Vector Class in the file vectorf128.h for an example.

这篇关于在x86-64中实现rint()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆