перемещать нижнее и верхнее значения __m128 - PullRequest
1 голос
/ 15 января 2020

Как переместить нижний и верхний значения с плавающей точкой __m128 на две __m128 и очистить нулями другие половины.

enter image description here

Ответы [ 2 ]

2 голосов
/ 15 января 2020

Поскольку вы не указали, я предполагаю, что намерением является использование встроенных функций SSE. Я также предполагаю, что по крайней мере SSE2 доступен, так как это в основном базовый уровень, установленный x86-64 в эти дни ...

Весьма буквальный способ сделать то, что вы описали выше, это просто скопировать младшие 64 бита введите и обнулите старшие 64 бита с помощью _mm_move_epi64()

__m128 lo2(__m128 x)
{
    return _mm_castsi128_ps(_mm_move_epi64(_mm_castps_si128(x)));
}

и используйте _mm_move_sd(), чтобы скопировать верхние 64 бита входа и скопировать младшие 64 бита с нуля

__m128 hi2(__m128 x)
{
    return _mm_castpd_ps(_mm_move_sd(_mm_castps_pd(x), _mm_setzero_pd()));
}

рабочий пример здесь

1 голос
/ 19 января 2020

Как насчет _mm_movelh_ps() и _mm_movehl_ps(), которые в сочетании с регистром всех нулей делают именно то, что вы хотите?

#include <iostream>
#include <x86intrin.h>

void print_vec(__m128 a) {
  alignas(16) float res[4];
  _mm_store_ps(res, a);
  std::cout << res[0] << '\t' << res[1] << '\t' << res[2] << '\t' << res[3]
            << '\n';
}

int main() {
  __m128 vec = _mm_set_ps(4.0f, 3.0f, 2.0f, 1.0f);

  __m128 lo = _mm_movelh_ps(vec, _mm_setzero_ps());
  __m128 hi = _mm_movehl_ps(vec, _mm_setzero_ps());

  std::cout << "Orig:\t";
  print_vec(vec);
  std::cout << "Lower:\t";
  print_vec(lo);
  std::cout << "Upper:\t";
  print_vec(hi);

  return 0;
}

Компиляция и запуск это производит:

Orig:   1   2   3   4
Lower:  1   2   0   0
Upper:  0   0   3   4
...