SSEでの整数からdoubleへの変換
利用してint値をdoubleに変換する次の処理をSSEに置き換えるのは次のコードですむ。
int i[4]; double d[4]; d[0] = (double)i[0]; d[1] = (double)i[1]; d[2] = (double)i[2]; d[3] = (double)i[3];
__m123i val; // なんらかの整数 __m128d d01 = _mm_cvtepi32_pd(val);// 前半2要素の変換 __m128d d23 = _mm_cvtepi32_pd(_mm_srli_si128(val, 8));// 後半2要素の変換
しかしuinsigned intをdoubleに変換する次の処理を置き換えるのは一気に複雑になる。
unsigned int i[4]; double d[4]; d[0] = (double)i[0]; d[1] = (double)i[1]; d[2] = (double)i[2]; d[3] = (double)i[3];
__m123i val; // なんらかの整数 __m128d zero = _mm_set1_pd(0.0); // 2つの0.0をセット __m128d dmax = _mm_set1_pd(4294967296.0); // 前半2要素 __m128d d01 = _mm_cvtepi32_pd(val);// doubleへ変換(ただしintとして変換される) __m128d cmp0 = _mm_cmplt_pd(d01, zero);// 0.0より小さいかの判定 // 0.0より小さい場合だけ4294967296.0を加算する __m128i ofs0 = _mm_and_si128(*(__m128i*)&cmp0, *(__m128i*)&dmax); d01 = _mm_add_pd(d01, *(__m128d *)&ofs0); // 後半2要素にも同じ事を行う __m128d d23 = _mm_cvtepi32_pd(_mm_srli_si128(val, 8)); __m128d cmp1 = _mm_cmplt_pd(d23, zero); __m128i ofs1 = _mm_and_si128(*(__m128i*)&cmp1, *(__m128i*)&dmax); d23 = _mm_add_pd(d23, *(__m128d *)&ofs1);
もう少し命令数を減らせそうな気もするけど、思いつかない。