Skip to content

Commit b46c1c3

Browse files
sse4.2: added the implementation for mm_cmpestra
1 parent 6ee040c commit b46c1c3

3 files changed

Lines changed: 279 additions & 0 deletions

File tree

simde/simde-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ typedef SIMDE_FLOAT64_TYPE simde_float64;
693693
# if defined(SIMDE_ARCH_AARCH64)
694694
# define SIMDE_BUG_CLANG_45541
695695
# endif
696+
# define SIMDE_BUG_CLANG_45959
696697
# endif
697698
# if defined(HEDLEY_EMSCRIPTEN_VERSION)
698699
# define SIMDE_BUG_EMSCRIPTEN_MISSING_IMPL /* Placeholder for (as yet) unfiled issues. */

simde/x86/sse4.2.h

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