Как мога да взема реципрочната (обратната) стойност на плаващите числа с инструкции за SSE, но само за ненулеви стойности?
Фон по-долу:
Искам да нормализирам масив от вектори, така че всяко измерение да има една и съща средна стойност. В C това може да се кодира като:
float vectors[num * dim]; // input data
// step 1. compute the sum on each dimension
float norm[dim];
memset(norm, 0, dim * sizeof(float));
for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++)
norm[j] += vectors[i * dims + j];
// step 2. convert sums to reciprocal of average
for(int j = 0; j < dims; j++) if(norm[j]) norm[j] = float(num) / norm[j];
// step 3. normalize the data
for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++)
vectors[i * dims + j] *= norm[j];
Сега от съображения за ефективност искам да направя това с помощта на SSE intinsics. Setp 1 и стъпка 3 са лесни, но останах на стъпка 2. Изглежда не намирам никакъв примерен код или очевидна SSE инструкция за вземане на рециплината на стойност, ако не е нула . За разделянето _mm_rcp_ps върши работа и може би го комбинира с условно преместване, но как да получите маска, показваща кой компонент е нула?
Нямам нужда от кода на алгоритъма, описан по-горе, само от функцията "обратна, ако не е нула":
__m128 rcp_nz_ps(__m128 input) {
// ????
}
Благодаря!