Skip to content

Commit 7ebfef7

Browse files
sse4.2: added the implementation for mm_cmpestra
1 parent 482124f commit 7ebfef7

3 files changed

Lines changed: 277 additions & 0 deletions

File tree

simde/simde-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ typedef SIMDE_FLOAT64_TYPE simde_float64;
697697
# if defined(SIMDE_ARCH_AARCH64)
698698
# define SIMDE_BUG_CLANG_45541
699699
# endif
700+
# define SIMDE_BUG_CLANG_45959
700701
# endif
701702
# if defined(HEDLEY_EMSCRIPTEN_VERSION)
702703
# define SIMDE_BUG_EMSCRIPTEN_MISSING_IMPL /* Placeholder for (as yet) unfiled issues. */

simde/x86/sse4.2.h

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,243 @@ SIMDE_BEGIN_DECLS_
9292
#define _SIDD_UNIT_MASK SIMDE_SIDD_UNIT_MASK
9393
#endif
9494

95+
SIMDE_FUNCTION_ATTRIBUTES
96+
int
97+
simde_mm_cmpestra_8_(simde__m128i a, int la, simde__m128i b, int lb, const int imm8)
98+
SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) {
99+
const int cmp_op = imm8 & 0x0c;
100+
const int polarity = imm8 & 0x30;
101+
simde__m128i_private
102+
bool_res_ = simde__m128i_to_private(simde_mm_setzero_si128()),
103+
a_ = simde__m128i_to_private(a),
104+
b_ = simde__m128i_to_private(b);
105+
const int upper_bound = (128 / 8) - 1;
106+
int a_invalid = 0;
107+
int b_invalid = 0;
108+
for(int i = 0 ; i <= upper_bound ; i++) {
109+
for(int j = 0; j <= upper_bound ; j++){
110+
int bitvalue = ((a_.i8[i] == b_.i8[j]) ? 1 : 0);
111+
if(i == la)
112+
a_invalid = 1;
113+
if(j == lb)
114+
b_invalid = 1;
115+
switch(cmp_op){
116+
case SIMDE_SIDD_CMP_EQUAL_ANY:
117+
case SIMDE_SIDD_CMP_RANGES:
118+
if(!a_invalid && !b_invalid);
119+
else
120+
bitvalue = 0;
121+
break;
122+
case SIMDE_SIDD_CMP_EQUAL_EACH:
123+
if(!a_invalid && !b_invalid);
124+
else if(a_invalid && b_invalid)
125+
bitvalue = 1;
126+
else
127+
bitvalue = 0;
128+
break;
129+
case SIMDE_SIDD_CMP_EQUAL_ORDERED:
130+
if(!a_invalid && !b_invalid);
131+
else if(a_invalid && !b_invalid)
132+
bitvalue = 1;
133+
else if(a_invalid && b_invalid)
134+
bitvalue = 1;
135+
else
136+
bitvalue = 0;
137+
break;
138+
}
139+
bool_res_.i8[i] |= (bitvalue << j);
140+
}
141+
}
142+
int32_t int_res_1 = 0;
143+
int32_t int_res_2 = 0;
144+
switch(cmp_op) {
145+
case SIMDE_SIDD_CMP_EQUAL_ANY:
146+
for(int i = 0 ; i <= upper_bound ; i++){
147+
SIMDE_VECTORIZE_REDUCTION(|:int_res_1)
148+
for(int j = 0 ; j <= upper_bound ; j++){
149+
int_res_1 |= (((bool_res_.i8[i] >> j) & 1) << i);
150+
}
151+
}
152+
break;
153+
case SIMDE_SIDD_CMP_RANGES:
154+
for(int i = 0 ; i <= upper_bound ; i++){
155+
SIMDE_VECTORIZE_REDUCTION(|:int_res_1)
156+
for(int j = 0 ; j <= upper_bound ; j++){
157+
int_res_1 |= ((((bool_res_.i8[i] >> j) & 1) & ((bool_res_.i8[i] >> (j + 1)) & 1)) << i);
158+
j += 2;
159+
}
160+
}
161+
break;
162+
case SIMDE_SIDD_CMP_EQUAL_EACH:
163+
SIMDE_VECTORIZE_REDUCTION(|:int_res_1)
164+
for(int i = 0 ; i <= upper_bound ; i++){
165+
int_res_1 |= (((bool_res_.i8[i] >> i) & 1) << i);
166+
}
167+
break;
168+
case SIMDE_SIDD_CMP_EQUAL_ORDERED:
169+
int_res_1 = 0xff;
170+
for(int i = 0 ; i <= upper_bound ; i++){
171+
int k = i;
172+
HEDLEY_DIAGNOSTIC_PUSH
173+
#if defined(SIMDE_BUG_CLANG_45959)
174+
#pragma clang diagnostic ignored "-Wsign-conversion"
175+
#endif
176+
SIMDE_VECTORIZE_REDUCTION(&:int_res_1)
177+
for(int j = 0 ; j <= (upper_bound-i) ; j++){
178+
int_res_1 &= (((bool_res_.i8[k] >> j) & 1 ) << i) ;
179+
k += 1;
180+
}
181+
HEDLEY_DIAGNOSTIC_POP
182+
}
183+
break;
184+
}
185+
for(int i = 0; i <= upper_bound ; i++){
186+
if(polarity & SIMDE_SIDD_NEGATIVE_POLARITY){
187+
if(polarity & SIMDE_SIDD_MASKED_POSITIVE_POLARITY) {
188+
if (i >= lb) {
189+
int_res_2 |= (((int_res_1 >> i) & 1) << i);
190+
}
191+
else {
192+
int_res_2 |= ((((int_res_1 >> i) & 1) ^ (-1)) << i);
193+
}
194+
}
195+
else{
196+
int_res_2 |= ((((int_res_1 >> i) & 1) ^ (-1)) << i);
197+
}
198+
}
199+
else{
200+
int_res_2 |= ( ((int_res_1 >> i) & 1) << i);
201+
}
202+
}
203+
return !int_res_2 & (lb > upper_bound);
204+
}
205+
206+
SIMDE_FUNCTION_ATTRIBUTES
207+
int
208+
simde_mm_cmpestra_16_(simde__m128i a, int la, simde__m128i b, int lb, const int imm8)
209+
SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) {
210+
const int cmp_op = imm8 & 0x0c;
211+
const int polarity = imm8 & 0x30;
212+
simde__m128i_private
213+
bool_res_ = simde__m128i_to_private(simde_mm_setzero_si128()),
214+
a_ = simde__m128i_to_private(a),
215+
b_ = simde__m128i_to_private(b);
216+
const int upper_bound = (128 / 16) - 1;
217+
int a_invalid = 0;
218+
int b_invalid = 0;
219+
for(int i = 0 ; i <= upper_bound ; i++) {
220+
for(int j = 0; j <= upper_bound ; j++)
221+
{
222+
int bitvalue = ((a_.i16[i] == b_.i16[j]) ? 1 : 0);
223+
a_invalid = 0;
224+
b_invalid = 0;
225+
if(i >= la)
226+
a_invalid = 1;
227+
if(j >= lb)
228+
b_invalid = 1;
229+
switch(cmp_op){
230+
case SIMDE_SIDD_CMP_EQUAL_ANY:
231+
case SIMDE_SIDD_CMP_RANGES:
232+
if(!a_invalid && !b_invalid);
233+
else
234+
bitvalue = 0;
235+
break;
236+
case SIMDE_SIDD_CMP_EQUAL_EACH:
237+
if(!a_invalid && !b_invalid);
238+
else if(a_invalid && b_invalid)
239+
bitvalue = 1;
240+
else
241+
bitvalue = 0;
242+
break;
243+
case SIMDE_SIDD_CMP_EQUAL_ORDERED:
244+
if(!a_invalid && !b_invalid);
245+
else if(a_invalid && !b_invalid)
246+
bitvalue = 1;
247+
else if(a_invalid && b_invalid)
248+
bitvalue = 1;
249+
else
250+
bitvalue = 0;
251+
break;
252+
}
253+
bool_res_.i16[i] |= (bitvalue << j);
254+
}
255+
}
256+
int32_t int_res_1 = 0;
257+
int32_t int_res_2 = 0;
258+
switch(cmp_op) {
259+
case SIMDE_SIDD_CMP_EQUAL_ANY:
260+
for(int i = 0 ; i <= upper_bound ; i++){
261+
SIMDE_VECTORIZE_REDUCTION(|:int_res_1)
262+
for (int j = 0 ; j <= upper_bound ; j++){
263+
int_res_1 |= (((bool_res_.i16[i] >> j) & 1) << i) ;
264+
}
265+
}
266+
break;
267+
case SIMDE_SIDD_CMP_RANGES:
268+
for(int i = 0 ; i <= upper_bound ; i++){
269+
SIMDE_VECTORIZE_REDUCTION(|:int_res_1)
270+
for(int j = 0 ; j <= upper_bound ; j++){
271+
int_res_1 |= ((((bool_res_.i16[i] >> j) & 1) & ((bool_res_.i16[i] >> (j + 1)) & 1)) << i);
272+
j += 2;
273+
}
274+
}
275+
break;
276+
case SIMDE_SIDD_CMP_EQUAL_EACH:
277+
SIMDE_VECTORIZE_REDUCTION(|:int_res_1)
278+
for(int i = 0 ; i <= upper_bound ; i++){
279+
int_res_1 |= (((bool_res_.i16[i] >> i) & 1) << i);
280+
}
281+
break;
282+
case SIMDE_SIDD_CMP_EQUAL_ORDERED:
283+
int_res_1 = 0xffff;
284+
for(int i = 0 ; i <= upper_bound ; i++){
285+
int k = i;
286+
HEDLEY_DIAGNOSTIC_PUSH
287+
#if defined(SIMDE_BUG_CLANG_45959)
288+
#pragma clang diagnostic ignored "-Wsign-conversion"
289+
#endif
290+
SIMDE_VECTORIZE_REDUCTION(&:int_res_1)
291+
for(int j = 0 ; j <= (upper_bound-i) ; j++){
292+
int_res_1 &= (((bool_res_.i16[k] >> j) & 1) << i) ;
293+
k += 1;
294+
}
295+
HEDLEY_DIAGNOSTIC_POP
296+
}
297+
break;
298+
}
299+
for(int i = 0; i <= upper_bound ; i++){
300+
if(polarity & SIMDE_SIDD_NEGATIVE_POLARITY){
301+
if(polarity & SIMDE_SIDD_MASKED_POSITIVE_POLARITY) {
302+
if (i >= lb) {
303+
int_res_2 |= (((int_res_1 >> i) & 1) << i);
304+
}
305+
else {
306+
int_res_2 |= ((((int_res_1 >> i) & 1) ^ (-1)) << i);
307+
}
308+
}
309+
else{
310+
int_res_2 |= ((((int_res_1 >> i) & 1) ^ (-1)) << i);
311+
}
312+
}
313+
else{
314+
int_res_2 |= (((int_res_1 >> i) & 1) << i);
315+
}
316+
}
317+
return !int_res_2 & (lb > upper_bound);
318+
}
319+
320+
#if defined(SIMDE_X86_SSE4_2_NATIVE)
321+
#define simde_mm_cmpestra(a, la, b, lb, imm8) _mm_cmpestra(a, la, b, lb, imm8)
322+
#else
323+
#define simde_mm_cmpestra(a, la, b, lb, imm8) \
324+
(((imm8) & SIMDE_SIDD_UWORD_OPS) \
325+
? simde_mm_cmpestra_16_((a), (la), (b), (lb), (imm8)) \
326+
: simde_mm_cmpestra_8_((a), (la), (b), (lb), (imm8)))
327+
#endif
328+
#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES)
329+
#define _mm_cmpestra(a, la, b, lb, imm8) simde_mm_cmpestra(a, la, b, lb, imm8)
330+
#endif
331+
95332
SIMDE_FUNCTION_ATTRIBUTES
96333
int simde_mm_cmpestrs (simde__m128i a, int la, simde__m128i b, int lb, const int imm8)
97334
SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 127) {

test/x86/sse4.2.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,43 @@
2727

2828
#if defined(SIMDE_X86_SSE4_2_NATIVE) || defined(SIMDE_NO_NATIVE) || defined(SIMDE_ALWAYS_BUILD_NATIVE_TESTS)
2929

30+
31+
static MunitResult
32+
test_simde_mm_cmpestra_ranges_8(const MunitParameter params[], void* data) {
33+
(void) params;
34+
(void) data;
35+
36+
const struct {
37+
simde__m128i a;
38+
int la;
39+
simde__m128i b;
40+
int lb;
41+
int r;
42+
} test_vec[] = {
43+
{ simde_mm_set_epi8(INT8_C( 45), INT8_C( -94), INT8_C( 38), INT8_C( -11),
44+
INT8_C( 84), INT8_C(-123), INT8_C( -43), INT8_C( -49),
45+
INT8_C( 25), INT8_C( -55), INT8_C(-121), INT8_C( -6),
46+
INT8_C( 57), INT8_C( 108), INT8_C( -55), INT8_C( 69)),
47+
23 ,
48+
simde_mm_set_epi8(INT8_C( -26), INT8_C( -61), INT8_C( -21), INT8_C( -96),
49+
INT8_C( 48), INT8_C(-112), INT8_C( 95), INT8_C( -56),
50+
INT8_C( 29), INT8_C( -55), INT8_C(-121), INT8_C( -6),
51+
INT8_C( 57), INT8_C( 108), INT8_C( -55), INT8_C( 69)),
52+
28 ,
53+
0 }
54+
};
55+
56+
for (size_t i = 0 ; i < (sizeof(test_vec) / sizeof(test_vec[0])); i++) {
57+
int r;
58+
r = simde_mm_cmpestra(test_vec[i].a, test_vec[i].la, test_vec[i].b, test_vec[i].lb, 36);
59+
munit_assert_int(r, ==, test_vec[i].r);
60+
}
61+
62+
return MUNIT_OK;
63+
}
64+
65+
66+
3067
static MunitResult
3168
test_simde_mm_cmpestrs_8(const MunitParameter params[], void* data) {
3269
(void) params;
@@ -760,6 +797,8 @@ HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
760797

761798
static MunitTest test_suite_tests[] = {
762799
#if defined(SIMDE_X86_SSE4_2_NATIVE) || defined(SIMDE_NO_NATIVE) || defined(SIMDE_ALWAYS_BUILD_NATIVE_TESTS)
800+
SIMDE_TESTS_DEFINE_TEST(mm_cmpestra_ranges_8),
801+
763802
SIMDE_TESTS_DEFINE_TEST(mm_cmpestrs_8),
764803
SIMDE_TESTS_DEFINE_TEST(mm_cmpestrs_16),
765804
SIMDE_TESTS_DEFINE_TEST(mm_cmpestrz_8),

0 commit comments

Comments
 (0)