如何使用内在函数执行double的绝对值?

时间:2014-08-31 09:23:16

标签: c++ x86 sse simd intrinsics

我们正在尝试创建一个不同操作的向量内部库,其中一个正在获取该数字的绝对值。但是,我的教授仅限于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");

}

我得到的错误是:

  

没有操作员&#34; =&#34;匹配这些操作数

     

操作数类型是:__ m128d = __m128i

1 个答案:

答案 0 :(得分:2)

您需要做的就是清除向量中两个double值的符号位。每个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");

}