2014-08-31 58 views
0

我们正在尝试制作不同操作的矢量内在库,其中一个库获取数字的绝对值。但是,我的教授只限于double如何使用内在函数对double执行绝对值?

我是相当新的x86的内部函数指令集,所以我希望有人能赐教。

这是我到目前为止有:

void vectorAbs(double *x, double *y, unsigned int N); 
int main() 
{ 
    double x[] = { -1, -2, -3, -4, -5, -6 }; 
    double y[] = { 2, 2, 2, 2, 2, 2 }; 
    double *pX = x, *pY = y; 

    vectorAbs(pX, pY, 6); 
} 

void vectorAbs(double *x, double *y, unsigned int N) 
{ 
    __m128d xVar; 
    __m128d yVar; 

    printf("\nSquare of x : \n"); 
    for (int i = 0; i < N; i += 2) 
    { 
     xVar = _mm_loadu_pd(&x[i]); // load *x[i] to xVar 

     yVar = _mm_abs_epi16(xVar); // abs of x 
     _mm_storeu_pd(&y[i], yVar); // store yVar to y[i] 

     printf("%lf, %lf, ", y[i], y[i + 1]); 
    } 
    system("pause"); 

} 

而我得到的错误是:

没有运营商 “=” 匹配这些操作数

操作数类型是: __m128d = __m128i

+0

'_mm_abs_epi16'计算* 16位整数的绝对值* – 2014-08-31 09:32:57

+0

哦,accdg我的小抄,它只能做多达32位整数。但我们需要使用128位。这会成为一个问题吗?因为我的主要问题是如何将我的double转换为int,因此它可以获得绝对值。或基本上如何获得双倍的绝对值。 – nutellafella 2014-08-31 09:38:46

+0

它将128位视为8位有符号16位整数,并计算每一个的绝对值 - 这绝对不是您想要的。转换为整数显然会丢失大量信息。你或许应该实现自己的绝对值在比较初级的操作 - 比较为零,然后否定/从零减去如果是小于零,等 – 2014-08-31 09:50:21

回答

2

您只需清除标志位矢量中的两个双精度值。每个double的符号位都位于向量位63和127中。这可以通过使用固有函数_mm_and_pd的单个指令(andpd)完成。另一种方法是将两个双打合理地移位一位,然后右移一位。这两个值可以使用_mm_slli_epi64和_mm_srli_epi64内部函数并行移位。这里有一个例子:

#include <stdio.h> 
#include <stdlib.h> 
#include <intrin.h> 

void vectorAbs(double *x, double *y, unsigned int N); 
int main() 
{ 
    double x[] = { -1, -2, -3, -4, -5, -6 }; 
    double y[] = { 2, 2, 2, 2, 2, 2 }; 
    double *pX = x, *pY = y; 

    vectorAbs(pX, pY, 6); 
} 

__m128d abs_sample1 (__m128d val) 
    { 
    return _mm_castsi128_pd (_mm_srli_epi64 (_mm_slli_epi64 (_mm_castpd_si128 (val), 1), 1)); 
    } 

__m128d abs_sample2 (__m128d val) 
    { 
    const __m128d mask = _mm_castsi128_pd (_mm_set1_epi64x (0x7FFFFFFFFFFFFFFF)); 
    return _mm_and_pd (mask, val); 
    } 

void vectorAbs(double *x, double *y, unsigned int N) 
{ 
    __m128d xVar; 
    __m128d yVar; 

    printf("\nSquare of x : \n"); 
    for (int i = 0; i < N; i += 2) 
    { 
     xVar = _mm_loadu_pd(&x[i]); // load *x[i] to xVar 

     yVar = abs_sample1(xVar); // abs of x 
     _mm_storeu_pd(&y[i], yVar); // store yVar to y[i] 
     printf("%lf, %lf, ", y[i], y[i + 1]); 
    } 
    system("pause"); 

} 
+0

'__m128d面膜= _mm_castsi128_pd(_mm_setr_epi32(-1,0x7FFFFFFF,-1,0x7FFFFFFF) ); yVar = _mm_and_pd(xVar,mask);' – 2014-09-04 15:41:37