Reputation: 1333
I have a vector int16_t beta = {1,1,0,0,0,0,0,0}
.
I want to implement this equation with AVX2
c[i] = a[i] + (-1)^beta[i] * b[i]
where a, b, c, and beta are all AVX2 vectors of int16_t
.
I have figured out that, if I can map 1 to -32768 multiplication operation can be avoided. I mean, flipping the sign of vector b can be done using OR and NEGATE functions of simd intrinsics.
I do know that 1 can be mapped to -32768 using left shift operation, however avx2 doesn't have any bit shift operations1. Is there any way to efficiently map 1 to -32768 with simd?
Editor's footnote 1: _mm256_slli_epi16(x, 15)
does in fact exist. But there are other ways to implement the whole formula so the question is interesting after all.
Upvotes: 1
Views: 1008
Reputation: 64903
There is a quick way to conditionally negate, using _mm256_sign_epi16
. The mask is not of the right form, but it can be transformed into the right form by adding 0x7FFF to every element, so:
__m256i masks = _mm256_add_epi16(beta, _mm256_set1_epi16(0x7FFF));
__m256i res = _mm256_add_epi16(a, _mm256_sign_epi16(b, masks));
Upvotes: 4
Reputation: 23701
You can transform
c[i] = a[i] + (-1)^beta[i] * b[i]
to
c[i] = a[i] - (beta[i] AND b[i]) + ((NOT beta[i]) AND b[i])
as the original formula translates to "subtract this bit if beta[i] is set, otherwise add it".
(I have no idea what you intend to happen for c[i] = 0 + (-1) * 1
or c[i] = 1 + 1 * 1
- I'm assuming normal arithmetic addition with carries here, contrary to the index notation).
So you can just drop the indices:
c = a - (beta & b) + (!beta & b)
I don't know if that has a good mapping to AVX2 intrinsics but I would suspect it does.
Upvotes: 0