1 #if !defined(SIMDE_TESTS_H)
2 #define SIMDE_TESTS_H
3 
4 #define SIMDE_NO_CHECK_IMMEDIATE_CONSTANT
5 
6 #include "../simde/simde-common.h"
7 
8 #include <time.h>
9 #include <stdlib.h>
10 #include <math.h>
11 #include <inttypes.h>
12 #include <stdarg.h>
13 
14 typedef enum SimdeTestVecPos {
15   SIMDE_TEST_VEC_POS_FIRST  =  1,
16   SIMDE_TEST_VEC_POS_MIDDLE =  0,
17   SIMDE_TEST_VEC_POS_LAST   = -1
18 } SimdeTestVecPos;
19 
20 HEDLEY_DIAGNOSTIC_PUSH
21 SIMDE_DIAGNOSTIC_DISABLE_VLA_
22 SIMDE_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION_
23 SIMDE_DIAGNOSTIC_DISABLE_PADDED_
24 SIMDE_DIAGNOSTIC_DISABLE_ZERO_AS_NULL_POINTER_CONSTANT_
25 SIMDE_DIAGNOSTIC_DISABLE_CAST_FUNCTION_TYPE_
26 SIMDE_DIAGNOSTIC_DISABLE_NON_CONSTANT_AGGREGATE_INITIALIZER_
27 SIMDE_DIAGNOSTIC_DISABLE_C99_EXTENSIONS_
28 SIMDE_DIAGNOSTIC_DISABLE_NO_EMMS_INSTRUCTION_
29 SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_
30 SIMDE_DIAGNOSTIC_DISABLE_ANNEX_K_
31 SIMDE_DIAGNOSTIC_DISABLE_DISABLED_MACRO_EXPANSION_
32 
33 #if \
34     HEDLEY_HAS_BUILTIN(__builtin_abort) || \
35     HEDLEY_GCC_VERSION_CHECK(3,4,6) || \
36     HEDLEY_ARM_VERSION_CHECK(4,1,0)
37   #define simde_abort() __builtin_abort()
38 #elif defined(SIMDE_HAVE_STDLIB_H)
39   #define simde_abort() abort()
40 #endif
41 
42 #define SIMDE_TEST_ASSERT_CONTINUE 0
43 #define SIMDE_TEST_ASSERT_TRAP 1
44 #define SIMDE_TEST_ASSERT_ABORT 2
45 #if !defined(SIMDE_TEST_ASSERT_FAILURE)
46   #if defined(SIMDE_TEST_BARE)
47     #define SIMDE_TEST_ASSERT_FAILURE SIMDE_TEST_ASSERT_CONTINUE
48   #else
49     #define SIMDE_TEST_ASSERT_FAILURE SIMDE_TEST_ASSERT_ABORT
50   #endif
51 #endif
52 
53 #if !defined(SIMDE_TEST_ASSERT_ABORT) && !defined(SIMDE_TEST_ASSERT_CONTINUE) && !defined(SIMDE_TEST_ASSERT_TRAP)
54   #if defined(SIMDE_TEST_BARE)
55     #define SIMDE_TEST_ASSERT_CONTINUE
56   #else
57     #define SIMDE_TEST_ASSERT_ABORT
58   #endif
59 #endif
60 
61 #if SIMDE_TEST_ASSERT_FAILURE == SIMDE_TEST_ASSERT_ABORT
62   #define SIMDE_TEST_ASSERT_RETURN(value) ((void) 0)
63 #else
64   #define SIMDE_TEST_ASSERT_RETURN(value) return value
65 #endif
66 
67 #if defined(SIMDE_TEST_BARE)
68   #define SIMDE_CODEGEN_FP stderr
69 #else
70   #define SIMDE_CODEGEN_FP stdout
71 #endif
72 
73 #if SIMDE_TEST_ASSERT_FAILURE == 2
74   HEDLEY_NO_RETURN
75 #endif
76 HEDLEY_PRINTF_FORMAT(1, 2)
77 static void
simde_test_debug_printf_(const char * format,...)78 simde_test_debug_printf_(const char* format, ...) {
79   va_list ap;
80 
81   va_start(ap, format);
82   vfprintf(stderr, format, ap);
83   va_end(ap);
84   fflush(stderr);
85 
86   /* Debug trap is great for local development where you can attach a
87    * debugger, but processes exiting with a SIGTRAP seem to be rather
88    * confusing for CI. */
89   #if SIMDE_TEST_ASSERT_FAILURE == 1
90     simde_trap();
91   #elif SIMDE_TEST_ASSERT_FAILURE == 2
92     simde_abort();
93   #endif
94 }
95 
96 HEDLEY_PRINTF_FORMAT(3, 4)
97 static void
simde_test_codegen_snprintf_(char * str,size_t size,const char * format,...)98 simde_test_codegen_snprintf_(char* str, size_t size, const char* format, ...) {
99   va_list ap;
100   int w;
101 
102   va_start(ap, format);
103   w = vsnprintf(str, size, format, ap);
104   va_end(ap);
105 
106   if (w > HEDLEY_STATIC_CAST(int, size)) {
107     simde_test_debug_printf_("Not enough space to write value (given %zu bytes, need %d bytes)\n", size, w + 1);
108   }
109 }
110 
111 static void
simde_test_codegen_f32(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],simde_float32 value)112 simde_test_codegen_f32(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], simde_float32 value) {
113   if (simde_math_isnan(value)) {
114     simde_test_codegen_snprintf_(buf, buf_len, "           SIMDE_MATH_NANF");
115   } else if (simde_math_isinf(value)) {
116     simde_test_codegen_snprintf_(buf, buf_len, "%5cSIMDE_MATH_INFINITYF", value < 0 ? '-' : ' ');
117   } else {
118     simde_test_codegen_snprintf_(buf, buf_len, "SIMDE_FLOAT32_C(%9.2f)", HEDLEY_STATIC_CAST(double, value));
119   }
120 }
121 
122 static void
simde_test_codegen_f64(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],simde_float64 value)123 simde_test_codegen_f64(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], simde_float64 value) {
124   if (simde_math_isnan(value)) {
125     simde_test_codegen_snprintf_(buf, buf_len, "            SIMDE_MATH_NAN");
126   } else if (simde_math_isinf(value)) {
127     simde_test_codegen_snprintf_(buf, buf_len, "%7cSIMDE_MATH_INFINITY", value < 0 ? '-' : ' ');
128   } else {
129     simde_test_codegen_snprintf_(buf, buf_len, "SIMDE_FLOAT64_C(%9.2f)", HEDLEY_STATIC_CAST(double, value));
130   }
131 }
132 
133 static void
simde_test_codegen_i8(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],int8_t value)134 simde_test_codegen_i8(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], int8_t value) {
135   if (value == INT8_MIN) {
136     simde_test_codegen_snprintf_(buf, buf_len, "     INT8_MIN");
137   } else if (value == INT8_MAX) {
138     simde_test_codegen_snprintf_(buf, buf_len, "     INT8_MAX");
139   } else {
140     simde_test_codegen_snprintf_(buf, buf_len, "%cINT8_C(%4" PRId8 ")", (value < 0) ? '-' : ' ', HEDLEY_STATIC_CAST(int8_t, (value < 0) ? -value : value));
141   }
142 }
143 
144 static void
simde_test_codegen_i16(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],int16_t value)145 simde_test_codegen_i16(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], int16_t value) {
146   if (value == INT16_MIN) {
147     simde_test_codegen_snprintf_(buf, buf_len, "%15s", "INT16_MIN");
148   } else if (value == INT16_MAX) {
149     simde_test_codegen_snprintf_(buf, buf_len, "%15s", "INT16_MAX");
150   } else {
151     simde_test_codegen_snprintf_(buf, buf_len, "%cINT16_C(%6" PRId16 ")", (value < 0) ? '-' : ' ', HEDLEY_STATIC_CAST(int16_t, (value < 0) ? -value : value));
152   }
153 }
154 
155 static void
simde_test_codegen_i32(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],int32_t value)156 simde_test_codegen_i32(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], int32_t value) {
157   if (value == INT32_MIN) {
158     simde_test_codegen_snprintf_(buf, buf_len, "%20s", "INT32_MIN");
159   } else if (value == INT32_MAX) {
160     simde_test_codegen_snprintf_(buf, buf_len, "%20s", "INT32_MAX");
161   } else {
162     simde_test_codegen_snprintf_(buf, buf_len, "%cINT32_C(%12" PRId32 ")", (value < 0) ? '-' : ' ', HEDLEY_STATIC_CAST(int32_t, (value < 0) ? -value : value));
163   }
164 }
165 
166 static void
simde_test_codegen_i64(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],int64_t value)167 simde_test_codegen_i64(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], int64_t value) {
168   if (value == INT64_MIN) {
169     simde_test_codegen_snprintf_(buf, buf_len, "%29s", "INT64_MIN");
170   } else if (value == INT64_MAX) {
171     simde_test_codegen_snprintf_(buf, buf_len, "%29s", "INT64_MAX");
172   } else {
173     simde_test_codegen_snprintf_(buf, buf_len, "%cINT64_C(%20" PRId64 ")", (value < 0) ? '-' : ' ', HEDLEY_STATIC_CAST(int64_t, (value < 0) ? -value : value));
174   }
175 }
176 
177 static void
simde_test_codegen_u8(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],uint8_t value)178 simde_test_codegen_u8(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], uint8_t value) {
179   if (value == UINT8_MAX) {
180     simde_test_codegen_snprintf_(buf, buf_len, "   UINT8_MAX");
181   } else {
182     simde_test_codegen_snprintf_(buf, buf_len, "UINT8_C(%3" PRIu8 ")", value);
183   }
184 }
185 
186 static void
simde_test_codegen_u16(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],uint16_t value)187 simde_test_codegen_u16(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], uint16_t value) {
188   if (value == UINT16_MAX) {
189     simde_test_codegen_snprintf_(buf, buf_len, "%15s", "UINT16_MAX");
190   } else {
191     simde_test_codegen_snprintf_(buf, buf_len, "UINT16_C(%5" PRIu16 ")", value);
192   }
193 }
194 
195 static void
simde_test_codegen_u32(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],uint32_t value)196 simde_test_codegen_u32(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], uint32_t value) {
197   if (value == UINT32_MAX) {
198     simde_test_codegen_snprintf_(buf, buf_len, "%20s", "UINT32_MAX");
199   } else {
200     simde_test_codegen_snprintf_(buf, buf_len, "UINT32_C(%10" PRIu32 ")", value);
201   }
202 }
203 
204 static void
simde_test_codegen_u64(size_t buf_len,char buf[HEDLEY_ARRAY_PARAM (buf_len)],uint64_t value)205 simde_test_codegen_u64(size_t buf_len, char buf[HEDLEY_ARRAY_PARAM(buf_len)], uint64_t value) {
206   if (value == UINT64_MAX) {
207     simde_test_codegen_snprintf_(buf, buf_len, "%29s", "UINT64_MAX");
208   } else {
209     simde_test_codegen_snprintf_(buf, buf_len, "UINT64_C(%20" PRIu64 ")", value);
210   }
211 }
212 
213 static void
simde_test_codegen_write_indent(int indent)214 simde_test_codegen_write_indent(int indent) {
215   for (int i = 0 ; i < indent ; i++) {
216     fputs("  ", SIMDE_CODEGEN_FP);
217   }
218 }
219 
simde_test_codegen_rand(void)220 static int simde_test_codegen_rand(void) {
221   /* Single-threaded programs are so nice */
222   static int is_init = 0;
223   if (HEDLEY_UNLIKELY(!is_init)) {
224     FILE* fp = fopen("/dev/urandom", "r");
225     if (fp == NULL)
226       fp = fopen("/dev/random", "r");
227 
228     if (fp != NULL) {
229       unsigned int seed;
230       size_t nread = fread(&seed, sizeof(seed), 1, fp);
231       fclose(fp);
232       if (nread == 1) {
233         srand(seed);
234         is_init = 1;
235       }
236     }
237 
238     if (!is_init) {
239       srand(HEDLEY_STATIC_CAST(unsigned int, time(NULL)));
240       is_init = 1;
241     }
242   }
243 
244   return rand();
245 }
246 
247 static void
simde_test_codegen_random_memory(size_t buf_len,uint8_t buf[HEDLEY_ARRAY_PARAM (buf_len)])248 simde_test_codegen_random_memory(size_t buf_len, uint8_t buf[HEDLEY_ARRAY_PARAM(buf_len)]) {
249   for (size_t i = 0 ; i < buf_len ; i++) {
250     buf[i] = HEDLEY_STATIC_CAST(uint8_t, simde_test_codegen_rand() & 0xff);
251   }
252 }
253 
254 static simde_float32
simde_test_codegen_random_f32(simde_float32 min,simde_float32 max)255 simde_test_codegen_random_f32(simde_float32 min, simde_float32 max) {
256   simde_float32 v = (HEDLEY_STATIC_CAST(simde_float32, simde_test_codegen_rand()) / (HEDLEY_STATIC_CAST(simde_float32, RAND_MAX) / (max - min))) + min;
257   return simde_math_roundf(v * SIMDE_FLOAT32_C(100.0)) / SIMDE_FLOAT32_C(100.0);
258 }
259 
260 static simde_float64
simde_test_codegen_random_f64(simde_float64 min,simde_float64 max)261 simde_test_codegen_random_f64(simde_float64 min, simde_float64 max) {
262   simde_float64 v = (HEDLEY_STATIC_CAST(simde_float64, simde_test_codegen_rand()) / (HEDLEY_STATIC_CAST(simde_float64, RAND_MAX) / (max - min))) + min;
263   return simde_math_round(v * SIMDE_FLOAT64_C(100.0)) / SIMDE_FLOAT64_C(100.0);
264 }
265 
266 typedef enum SimdeTestVecFloatMask {
267   SIMDE_TEST_VEC_FLOAT_DEFAULT  = 0,
268   SIMDE_TEST_VEC_FLOAT_PAIR     = 1,
269   SIMDE_TEST_VEC_FLOAT_NAN      = 2,
270   SIMDE_TEST_VEC_FLOAT_EQUAL    = 4,
271   SIMDE_TEST_VEC_FLOAT_ROUND    = 8
272 }
273 #if \
274     (HEDLEY_HAS_ATTRIBUTE(flag_enum) && !defined(HEDLEY_IBM_VERSION)) && \
275     (!defined(__cplusplus) || SIMDE_DETECT_CLANG_VERSION_CHECK(5,0,0))
276   __attribute__((__flag_enum__))
277 #endif
278 SimdeTestVecFloatType;
279 
280 /* This is a bit messy, sorry.  And I haven't really tested with
281  * anything greater than 4-element vectors, there is no input
282  * validation, etc.  I'm not going to lose any sleep since it's
283  * just a test harness, but you probably shouldn't use this API
284  * directly since there is a good chance it will change. */
285 
286 static void
simde_test_codegen_calc_pair(int pairwise,size_t test_sets,size_t vectors_per_set,size_t elements_per_vector,size_t pos,size_t * a,size_t * b)287 simde_test_codegen_calc_pair(int pairwise, size_t test_sets, size_t vectors_per_set, size_t elements_per_vector, size_t pos, size_t* a, size_t* b) {
288   (void) test_sets; // <- for validating ranges
289 
290   if (pairwise) {
291     *a = (((pos * 2) + 0) % elements_per_vector) + ((((pos * 2) + 0) / elements_per_vector) * elements_per_vector);
292     *b = (((pos * 2) + 1) % elements_per_vector) + ((((pos * 2) + 1) / elements_per_vector) * elements_per_vector);
293   } else {
294     size_t elements_per_set = elements_per_vector * vectors_per_set;
295     size_t set_num = pos / elements_per_vector;
296     size_t pos_in_set = pos % elements_per_vector;
297 
298     *a = (elements_per_set * set_num) + pos_in_set;
299     *b = *a + elements_per_vector;
300   }
301 }
302 
303 static void
simde_test_codegen_float_set_value_(size_t element_size,size_t pos,void * values,simde_float32 f32_val,simde_float64 f64_val)304 simde_test_codegen_float_set_value_(size_t element_size, size_t pos, void* values, simde_float32 f32_val, simde_float64 f64_val) {
305   switch (element_size) {
306     case sizeof(simde_float32):
307       HEDLEY_REINTERPRET_CAST(simde_float32*, values)[pos] = f32_val;
308       break;
309     case sizeof(simde_float64):
310       HEDLEY_REINTERPRET_CAST(simde_float64*, values)[pos] = f64_val;
311       break;
312   }
313 }
314 
315 static void
simde_test_codegen_random_vfX_full_(size_t test_sets,size_t vectors_per_set,size_t elements_per_vector,size_t elem_size,void * values,simde_float64 min,simde_float64 max,SimdeTestVecFloatType vec_type)316 simde_test_codegen_random_vfX_full_(
317     size_t test_sets, size_t vectors_per_set, size_t elements_per_vector,
318     size_t elem_size, void* values,
319     simde_float64 min, simde_float64 max,
320     SimdeTestVecFloatType vec_type) {
321   for (size_t i = 0 ; i < (test_sets * vectors_per_set * elements_per_vector) ; i++) {
322     simde_float64 v = simde_test_codegen_random_f64(min, max);
323     if (vec_type & SIMDE_TEST_VEC_FLOAT_ROUND) {
324       if (simde_test_codegen_rand() & 7) {
325         do {
326           v = HEDLEY_STATIC_CAST(simde_float64, HEDLEY_STATIC_CAST(int64_t, v));
327           if (simde_test_codegen_rand() & 7)
328             v += 0.5;
329         } while (v > max || v < min);
330       }
331     }
332     simde_test_codegen_float_set_value_(elem_size, i, values, HEDLEY_STATIC_CAST(simde_float32, v), v);
333   }
334 
335   int pairwise = !!(vec_type & SIMDE_TEST_VEC_FLOAT_PAIR);
336   size_t pos = 0;
337   size_t a, b;
338 
339   if (vec_type & SIMDE_TEST_VEC_FLOAT_NAN) {
340     simde_test_codegen_calc_pair(pairwise, test_sets, vectors_per_set, elements_per_vector, pos++, &a, &b);
341     simde_test_codegen_float_set_value_(elem_size, a, values, SIMDE_MATH_NANF, SIMDE_MATH_NAN);
342 
343     simde_test_codegen_calc_pair(pairwise, test_sets, vectors_per_set, elements_per_vector, pos++, &a, &b);
344     simde_test_codegen_float_set_value_(elem_size, b, values, SIMDE_MATH_NANF, SIMDE_MATH_NAN);
345 
346     simde_test_codegen_calc_pair(pairwise, test_sets, vectors_per_set, elements_per_vector, pos++, &a, &b);
347     simde_test_codegen_float_set_value_(elem_size, a, values, SIMDE_MATH_NANF, SIMDE_MATH_NAN);
348     simde_test_codegen_float_set_value_(elem_size, b, values, SIMDE_MATH_NANF, SIMDE_MATH_NAN);
349   }
350 
351   if (vec_type & SIMDE_TEST_VEC_FLOAT_EQUAL) {
352     simde_test_codegen_calc_pair(pairwise, test_sets, vectors_per_set, elements_per_vector, pos++, &a, &b);
353     simde_float64 v = simde_test_codegen_random_f64(min, max);
354     simde_test_codegen_float_set_value_(elem_size, a, values, HEDLEY_STATIC_CAST(simde_float32, v), v);
355     simde_test_codegen_float_set_value_(elem_size, b, values, HEDLEY_STATIC_CAST(simde_float32, v), v);
356   }
357 }
358 
359 static void
simde_test_codegen_random_vf32_full(size_t test_sets,size_t vectors_per_set,size_t elements_per_vector,simde_float32 values[HEDLEY_ARRAY_PARAM (test_sets * vectors_per_set * elements_per_vector)],simde_float32 min,simde_float32 max,SimdeTestVecFloatType vec_type)360 simde_test_codegen_random_vf32_full(
361     size_t test_sets, size_t vectors_per_set, size_t elements_per_vector,
362     simde_float32 values[HEDLEY_ARRAY_PARAM(test_sets * vectors_per_set * elements_per_vector)],
363     simde_float32 min, simde_float32 max,
364     SimdeTestVecFloatType vec_type) {
365   simde_test_codegen_random_vfX_full_(test_sets, vectors_per_set, elements_per_vector,
366       sizeof(simde_float32), values,
367       HEDLEY_STATIC_CAST(simde_float64, min), HEDLEY_STATIC_CAST(simde_float64, max),
368       vec_type);
369 }
370 
371 static void
simde_test_codegen_random_vf64_full(size_t test_sets,size_t vectors_per_set,size_t elements_per_vector,simde_float64 values[HEDLEY_ARRAY_PARAM (test_sets * vectors_per_set * elements_per_vector)],simde_float64 min,simde_float64 max,SimdeTestVecFloatType vec_type)372 simde_test_codegen_random_vf64_full(
373     size_t test_sets, size_t vectors_per_set, size_t elements_per_vector,
374     simde_float64 values[HEDLEY_ARRAY_PARAM(test_sets * vectors_per_set * elements_per_vector)],
375     simde_float64 min, simde_float64 max,
376     SimdeTestVecFloatType vec_type) {
377   simde_test_codegen_random_vfX_full_(test_sets, vectors_per_set, elements_per_vector,
378       sizeof(simde_float64), values,
379       min, max,
380       vec_type);
381 }
382 
383 static void
simde_test_codegen_random_vf32(size_t elem_count,simde_float32 values[HEDLEY_ARRAY_PARAM (elem_count)],simde_float32 min,simde_float32 max)384 simde_test_codegen_random_vf32(size_t elem_count, simde_float32 values[HEDLEY_ARRAY_PARAM(elem_count)], simde_float32 min, simde_float32 max) {
385   for (size_t i = 0 ; i < elem_count ; i++) {
386     values[i] = simde_test_codegen_random_f32(min, max);
387   }
388 }
389 
390 static void
simde_test_codegen_random_vf64(size_t elem_count,simde_float64 values[HEDLEY_ARRAY_PARAM (elem_count)],simde_float64 min,simde_float64 max)391 simde_test_codegen_random_vf64(size_t elem_count, simde_float64 values[HEDLEY_ARRAY_PARAM(elem_count)], simde_float64 min, simde_float64 max) {
392   for (size_t i = 0 ; i < elem_count ; i++) {
393     values[i] = simde_test_codegen_random_f64(min, max);
394   }
395 }
396 
397 #define SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(T, symbol_identifier) \
398   static T simde_test_codegen_random_##symbol_identifier(void) { \
399     T r; \
400     simde_test_codegen_random_memory(sizeof(r), HEDLEY_REINTERPRET_CAST(uint8_t*, &r)); \
401     return r; \
402   }
403 
SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(int8_t,i8)404 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(int8_t,    i8)
405 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(int16_t,  i16)
406 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(int32_t,  i32)
407 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(int64_t,  i64)
408 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(uint8_t,   u8)
409 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(uint16_t, u16)
410 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(uint32_t, u32)
411 SIMDE_TEST_CODEGEN_GENERATE_RANDOM_INT_FUNC_(uint64_t, u64)
412 
413 #define SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(T, symbol_identifier, elements_per_line) \
414   static void \
415   simde_test_codegen_write_v##symbol_identifier(int indent, size_t elem_count, T values[HEDLEY_ARRAY_PARAM(elem_count)], SimdeTestVecPos pos) { \
416     switch (pos) { \
417       case SIMDE_TEST_VEC_POS_FIRST: \
418         simde_test_codegen_write_indent(indent); \
419         indent++; \
420         fputs("{ ", SIMDE_CODEGEN_FP); \
421         break; \
422       case SIMDE_TEST_VEC_POS_MIDDLE: \
423       case SIMDE_TEST_VEC_POS_LAST: \
424         indent++; \
425         simde_test_codegen_write_indent(indent); \
426         break; \
427     } \
428  \
429     fputs("{ ", SIMDE_CODEGEN_FP); \
430     for (size_t i = 0 ; i < elem_count ; i++) { \
431       if (i != 0) { \
432         fputc(',', SIMDE_CODEGEN_FP); \
433         if ((i % elements_per_line) == 0) { \
434           fputc('\n', SIMDE_CODEGEN_FP); \
435           simde_test_codegen_write_indent(indent + 1); \
436         } else { \
437           fputc(' ', SIMDE_CODEGEN_FP); \
438         } \
439       } \
440  \
441       char buf[53]; \
442       simde_test_codegen_##symbol_identifier(sizeof(buf), buf, values[i]); \
443       fputs(buf, SIMDE_CODEGEN_FP); \
444     } \
445     fputs(" }", SIMDE_CODEGEN_FP); \
446  \
447     switch (pos) { \
448       case SIMDE_TEST_VEC_POS_FIRST: \
449       case SIMDE_TEST_VEC_POS_MIDDLE: \
450         fputc(',', SIMDE_CODEGEN_FP); \
451         break; \
452       case SIMDE_TEST_VEC_POS_LAST: \
453         fputs(" },", SIMDE_CODEGEN_FP); \
454         break; \
455     } \
456  \
457     fputc('\n', SIMDE_CODEGEN_FP); \
458   }
459 
460 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(simde_float32, f32, 4)
461 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(simde_float64, f64, 4)
462 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(int8_t, i8, 8)
463 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(int16_t, i16, 8)
464 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(int32_t, i32, 8)
465 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(int64_t, i64, 4)
466 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(uint8_t, u8, 8)
467 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(uint16_t, u16, 8)
468 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(uint32_t, u32, 8)
469 SIMDE_TEST_CODEGEN_GENERATE_WRITE_VECTOR_FUNC_(uint64_t, u64, 4)
470 
471 #define SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(T, symbol_identifier) \
472   static void \
473   simde_test_codegen_write_##symbol_identifier(int indent, T value, SimdeTestVecPos pos) { \
474     switch (pos) { \
475       case SIMDE_TEST_VEC_POS_FIRST: \
476         simde_test_codegen_write_indent(indent); \
477         indent++; \
478         fputs("{ ", SIMDE_CODEGEN_FP); \
479         break; \
480       case SIMDE_TEST_VEC_POS_MIDDLE: \
481       case SIMDE_TEST_VEC_POS_LAST: \
482         indent++; \
483         simde_test_codegen_write_indent(indent); \
484         break; \
485     } \
486  \
487     { \
488       char buf[53]; \
489       simde_test_codegen_##symbol_identifier(sizeof(buf), buf, value); \
490       fputs(buf, SIMDE_CODEGEN_FP); \
491     } \
492  \
493     switch (pos) { \
494       case SIMDE_TEST_VEC_POS_FIRST: \
495       case SIMDE_TEST_VEC_POS_MIDDLE: \
496         fputc(',', SIMDE_CODEGEN_FP); \
497         break; \
498       case SIMDE_TEST_VEC_POS_LAST: \
499         fputs(" },", SIMDE_CODEGEN_FP); \
500         break; \
501     } \
502  \
503     fputc('\n', SIMDE_CODEGEN_FP); \
504   }
505 
506 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(int8_t,    i8)
507 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(int16_t,  i16)
508 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(int32_t,  i32)
509 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(int64_t,  i64)
510 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(uint8_t,   u8)
511 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(uint16_t, u16)
512 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(uint32_t, u32)
513 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(uint64_t, u64)
514 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(simde_float32, f32)
515 SIMDE_TEST_CODEGEN_WRITE_SCALAR_FUNC_(simde_float64, f64)
516 
517 HEDLEY_DIAGNOSTIC_PUSH
518 SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL_
519 
520 static int
521 simde_test_equal_f32(simde_float32 a, simde_float32 b, simde_float32 slop) {
522   if (simde_math_isnan(a)) {
523     return simde_math_isnan(b);
524   } else if (simde_math_isinf(a)) {
525     return !((a < b) || (a > b));
526   } else {
527     simde_float32 lo = a - slop;
528     if (HEDLEY_UNLIKELY(lo == a))
529       lo = simde_math_nextafterf(a, -SIMDE_MATH_INFINITYF);
530 
531     simde_float32 hi = a + slop;
532     if (HEDLEY_UNLIKELY(hi == a))
533       hi = simde_math_nextafterf(a, SIMDE_MATH_INFINITYF);
534 
535     return ((b >= lo) && (b <= hi));
536   }
537 }
538 
539 static int
simde_test_equal_f64(simde_float64 a,simde_float64 b,simde_float64 slop)540 simde_test_equal_f64(simde_float64 a, simde_float64 b, simde_float64 slop) {
541   if (simde_math_isnan(a)) {
542     return simde_math_isnan(b);
543   } else if (simde_math_isinf(a)) {
544     return !((a < b) || (a > b));
545   } else {
546     simde_float64 lo = a - slop;
547     if (HEDLEY_UNLIKELY(lo == a))
548       lo = simde_math_nextafter(a, -SIMDE_MATH_INFINITY);
549 
550     simde_float64 hi = a + slop;
551     if (HEDLEY_UNLIKELY(hi == a))
552       hi = simde_math_nextafter(a, SIMDE_MATH_INFINITY);
553 
554     return ((b >= lo) && (b <= hi));
555   }
556 }
557 
558 HEDLEY_DIAGNOSTIC_POP
559 
560 static float
simde_test_f32_precision_to_slop(int precision)561 simde_test_f32_precision_to_slop(int precision) {
562   return simde_math_powf(SIMDE_FLOAT32_C(10.0), -HEDLEY_STATIC_CAST(float, precision));
563 }
564 
565 static double
simde_test_f64_precision_to_slop(int precision)566 simde_test_f64_precision_to_slop(int precision) {
567   return simde_math_pow(SIMDE_FLOAT64_C(10.0), -HEDLEY_STATIC_CAST(double, precision));
568 }
569 
570 static int
simde_assert_equal_vf32_(size_t vec_len,simde_float32 const a[HEDLEY_ARRAY_PARAM (vec_len)],simde_float32 const b[HEDLEY_ARRAY_PARAM (vec_len)],simde_float32 slop,const char * filename,int line,const char * astr,const char * bstr)571 simde_assert_equal_vf32_(
572     size_t vec_len, simde_float32 const a[HEDLEY_ARRAY_PARAM(vec_len)], simde_float32 const b[HEDLEY_ARRAY_PARAM(vec_len)], simde_float32 slop,
573     const char* filename, int line, const char* astr, const char* bstr) {
574   for (size_t i = 0 ; i < vec_len ; i++) {
575     if (HEDLEY_UNLIKELY(!simde_test_equal_f32(a[i], b[i], slop))) {
576       simde_test_debug_printf_("%s:%d: assertion failed: %s[%zu] ~= %s[%zu] (%f ~= %f)\n",
577               filename, line, astr, i, bstr, i, HEDLEY_STATIC_CAST(double, a[i]), HEDLEY_STATIC_CAST(double, b[i]));
578       SIMDE_TEST_ASSERT_RETURN(1);
579     }
580   }
581   return 0;
582 }
583 #define simde_assert_equal_vf32(vec_len, a, b, precision) simde_assert_equal_vf32_(vec_len, a, b, simde_test_f32_precision_to_slop(precision), __FILE__, __LINE__, #a, #b)
584 
585 static int
simde_assert_equal_f32_(simde_float32 a,simde_float32 b,simde_float32 slop,const char * filename,int line,const char * astr,const char * bstr)586 simde_assert_equal_f32_(simde_float32 a, simde_float32 b, simde_float32 slop,
587     const char* filename, int line, const char* astr, const char* bstr) {
588   if (HEDLEY_UNLIKELY(!simde_test_equal_f32(a, b, slop))) {
589     simde_test_debug_printf_("%s:%d: assertion failed: %s ~= %s (%f ~= %f)\n",
590         filename, line, astr, bstr, HEDLEY_STATIC_CAST(double, a), HEDLEY_STATIC_CAST(double, b));
591     SIMDE_TEST_ASSERT_RETURN(1);
592   }
593   return 0;
594 }
595 #define simde_assert_equal_f32(a, b, precision) simde_assert_equal_f32_(a, b, simde_test_f32_precision_to_slop(precision), __FILE__, __LINE__, #a, #b)
596 
597 static int
simde_assert_equal_vf64_(size_t vec_len,simde_float64 const a[HEDLEY_ARRAY_PARAM (vec_len)],simde_float64 const b[HEDLEY_ARRAY_PARAM (vec_len)],simde_float64 slop,const char * filename,int line,const char * astr,const char * bstr)598 simde_assert_equal_vf64_(
599     size_t vec_len, simde_float64 const a[HEDLEY_ARRAY_PARAM(vec_len)], simde_float64 const b[HEDLEY_ARRAY_PARAM(vec_len)], simde_float64 slop,
600     const char* filename, int line, const char* astr, const char* bstr) {
601   for (size_t i = 0 ; i < vec_len ; i++) {
602     if (HEDLEY_UNLIKELY(!simde_test_equal_f64(a[i], b[i], slop))) {
603       simde_test_debug_printf_("%s:%d: assertion failed: %s[%zu] ~= %s[%zu] (%f ~= %f)\n",
604               filename, line, astr, i, bstr, i, HEDLEY_STATIC_CAST(double, a[i]), HEDLEY_STATIC_CAST(double, b[i]));
605       SIMDE_TEST_ASSERT_RETURN(1);
606     }
607   }
608   return 0;
609 }
610 #define simde_assert_equal_vf64(vec_len, a, b, precision) simde_assert_equal_vf64_(vec_len, a, b, simde_test_f64_precision_to_slop(precision), __FILE__, __LINE__, #a, #b)
611 
612 static int
simde_assert_equal_f64_(simde_float64 a,simde_float64 b,simde_float64 slop,const char * filename,int line,const char * astr,const char * bstr)613 simde_assert_equal_f64_(simde_float64 a, simde_float64 b, simde_float64 slop,
614     const char* filename, int line, const char* astr, const char* bstr) {
615   if (HEDLEY_UNLIKELY(!simde_test_equal_f64(a, b, slop))) {
616     simde_test_debug_printf_("%s:%d: assertion failed: %s ~= %s (%f ~= %f)\n",
617         filename, line, astr, bstr, a, b);
618     SIMDE_TEST_ASSERT_RETURN(1);
619   }
620   return 0;
621 }
622 #define simde_assert_equal_f64(a, b, precision) simde_assert_equal_f64_(a, b, simde_test_f64_precision_to_slop(precision), __FILE__, __LINE__, #a, #b)
623 
624 #define SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(T, symbol_identifier, fmt) \
625   static int \
626   simde_assert_equal_v##symbol_identifier##_( \
627       size_t vec_len, const T a[HEDLEY_ARRAY_PARAM(vec_len)], const T b[HEDLEY_ARRAY_PARAM(vec_len)], \
628       const char* filename, int line, const char* astr, const char* bstr) { \
629     for (size_t i = 0 ; i < vec_len ; i++) { \
630       if (HEDLEY_UNLIKELY(a[i] != b[i])) { \
631         simde_test_debug_printf_("%s:%d: assertion failed: %s[%zu] == %s[%zu] (%" fmt " == %" fmt ")\n", \
632               filename, line, astr, i, bstr, i, a[i], b[i]); \
633         SIMDE_TEST_ASSERT_RETURN(1); \
634       } \
635     } \
636     return 0; \
637   } \
638   \
639   static int \
640   simde_assert_equal_##symbol_identifier##_(T a, T b, \
641       const char* filename, int line, const char* astr, const char* bstr) { \
642     if (HEDLEY_UNLIKELY(a != b)) { \
643       simde_test_debug_printf_("%s:%d: assertion failed: %s == %s (%" fmt " == %" fmt ")\n", \
644             filename, line, astr, bstr, a, b); \
645       SIMDE_TEST_ASSERT_RETURN(1); \
646     } \
647     return 0; \
648   } \
649   \
650   static int \
651   simde_assert_close_v##symbol_identifier##_( \
652       size_t vec_len, const T a[HEDLEY_ARRAY_PARAM(vec_len)], const T b[HEDLEY_ARRAY_PARAM(vec_len)], const T slop, \
653       const char* filename, int line, const char* astr, const char* bstr) { \
654     for (size_t i = 0 ; i < vec_len ; i++) { \
655       if (((a[i] + slop) < b[i]) || ((a[i] - slop) > b[i])) { \
656         simde_test_debug_printf_("%s:%d: assertion failed: %s[%zu] == %s[%zu] (%" fmt " == %" fmt ")\n", \
657               filename, line, astr, i, bstr, i, a[i], b[i]); \
658         SIMDE_TEST_ASSERT_RETURN(1); \
659       } \
660     } \
661     return 0; \
662   } \
663   \
664   static int \
665   simde_assert_close_##symbol_identifier##_(T a, T b, T slop, \
666       const char* filename, int line, const char* astr, const char* bstr) { \
667     if (((a + slop) < b) || ((a - slop) > b)) { \
668       simde_test_debug_printf_("%s:%d: assertion failed: %s == %s +/- %" fmt " (%" fmt " == %" fmt ")\n", \
669             filename, line, astr, bstr, slop, a, b); \
670       SIMDE_TEST_ASSERT_RETURN(1); \
671     } \
672     return 0; \
673   }
674 
675 static int
simde_assert_equal_i_(int a,int b,const char * filename,int line,const char * astr,const char * bstr)676 simde_assert_equal_i_(int a, int b, const char* filename, int line, const char* astr, const char* bstr) {
677   if (HEDLEY_UNLIKELY(a != b)) {
678     simde_test_debug_printf_("%s:%d: assertion failed: %s == %s (%d == %d)\n",
679           filename, line, astr, bstr, a, b);
680     SIMDE_TEST_ASSERT_RETURN(1);
681   }
682   return 0;
683 }
684 
685 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(int8_t,    i8,  PRId8)
686 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(int16_t,  i16, PRId16)
687 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(int32_t,  i32, PRId32)
688 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(int64_t,  i64, PRId64)
689 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(uint8_t,   u8,  PRIu8)
690 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(uint16_t, u16, PRIu16)
691 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(uint32_t, u32, PRIu32)
692 SIMDE_TEST_GENERATE_ASSERT_EQUAL_FUNC_(uint64_t, u64, PRIu64)
693 
694 #define simde_assert_equal_vi8(vec_len, a, b) do { if (simde_assert_equal_vi8_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
695 #define simde_assert_equal_vi16(vec_len, a, b) do { if (simde_assert_equal_vi16_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
696 #define simde_assert_equal_vi32(vec_len, a, b) do { if (simde_assert_equal_vi32_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
697 #define simde_assert_equal_vi64(vec_len, a, b) do { if (simde_assert_equal_vi64_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
698 #define simde_assert_equal_vu8(vec_len, a, b) do { if (simde_assert_equal_vu8_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
699 #define simde_assert_equal_vu16(vec_len, a, b) do { if (simde_assert_equal_vu16_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
700 #define simde_assert_equal_vu32(vec_len, a, b) do { if (simde_assert_equal_vu32_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
701 #define simde_assert_equal_vu64(vec_len, a, b) do { if (simde_assert_equal_vu64_(vec_len, a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
702 
703 #define simde_assert_equal_i8(a, b) do { if (simde_assert_equal_i8_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
704 #define simde_assert_equal_i16(a, b) do { if (simde_assert_equal_i16_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
705 #define simde_assert_equal_i32(a, b) do { if (simde_assert_equal_i32_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
706 #define simde_assert_equal_i64(a, b) do { if (simde_assert_equal_i64_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
707 #define simde_assert_equal_u8(a, b) do { if (simde_assert_equal_u8_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
708 #define simde_assert_equal_u16(a, b) do { if (simde_assert_equal_u16_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
709 #define simde_assert_equal_u32(a, b) do { if (simde_assert_equal_u32_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
710 #define simde_assert_equal_u64(a, b) do { if (simde_assert_equal_u64_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
711 #define simde_assert_equal_i(a, b) do { if (simde_assert_equal_i_(a, b, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
712 
713 #define simde_assert_close_vi8(vec_len, a, b, slop) do { if (simde_assert_close_vi8_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
714 #define simde_assert_close_vi16(vec_len, a, b, slop) do { if (simde_assert_close_vi16_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
715 #define simde_assert_close_vi32(vec_len, a, b, slop) do { if (simde_assert_close_vi32_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
716 #define simde_assert_close_vi64(vec_len, a, b, slop) do { if (simde_assert_close_vi64_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
717 #define simde_assert_close_vu8(vec_len, a, b, slop) do { if (simde_assert_close_vu8_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
718 #define simde_assert_close_vu16(vec_len, a, b, slop) do { if (simde_assert_close_vu16_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
719 #define simde_assert_close_vu32(vec_len, a, b, slop) do { if (simde_assert_close_vu32_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
720 #define simde_assert_close_vu64(vec_len, a, b, slop) do { if (simde_assert_close_vu64_(vec_len, a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
721 
722 #define simde_assert_close_i8(a, b, slop) do { if (simde_assert_close_i8_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
723 #define simde_assert_close_i16(a, b, slop) do { if (simde_assert_close_i16_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
724 #define simde_assert_close_i32(a, b, slop) do { if (simde_assert_close_i32_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
725 #define simde_assert_close_i64(a, b, slop) do { if (simde_assert_close_i64_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
726 #define simde_assert_close_u8(a, b, slop) do { if (simde_assert_close_u8_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
727 #define simde_assert_close_u16(a, b, slop) do { if (simde_assert_close_u16_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
728 #define simde_assert_close_u32(a, b, slop) do { if (simde_assert_close_u32_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
729 #define simde_assert_close_u64(a, b, slop) do { if (simde_assert_close_u64_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
730 #define simde_assert_close_i(a, b, slop) do { if (simde_assert_close_i_(a, b, slop, __FILE__, __LINE__, #a, #b)) { return 1; } } while (0)
731 
732 /* Since each test is compiled in 4 different versions (C/C++ and
733  * native/emul), we need to be able to generate different symbols
734  * depending on preprocessor macros. */
735 #if defined(SIMDE_NO_NATIVE)
736   #if defined(__cplusplus)
737     #define SIMDE_TEST_GENERATE_VARIANT_SYMBOL_CURRENT(name) HEDLEY_CONCAT(name,_emul_cpp)
738     #define SIMDE_TEST_GENERATE_VARIANT_NAME_CURRENT(name) #name "/emul/cpp"
739   #else
740     #define SIMDE_TEST_GENERATE_VARIANT_SYMBOL_CURRENT(name) HEDLEY_CONCAT(name,_emul_c)
741     #define SIMDE_TEST_GENERATE_VARIANT_NAME_CURRENT(name) #name "/emul/c"
742   #endif
743 #else
744   #if defined(__cplusplus)
745     #define SIMDE_TEST_GENERATE_VARIANT_SYMBOL_CURRENT(name) HEDLEY_CONCAT(name,_native_cpp)
746     #define SIMDE_TEST_GENERATE_VARIANT_NAME_CURRENT(name) #name "/native/cpp"
747   #else
748     #define SIMDE_TEST_GENERATE_VARIANT_SYMBOL_CURRENT(name) HEDLEY_CONCAT(name,_native_c)
749     #define SIMDE_TEST_GENERATE_VARIANT_NAME_CURRENT(name) #name "/native/c"
750   #endif
751 #endif
752 
753 /* The bare version basically assumes you just want to run a single
754  * test suite.  It doesn't use munit, or any other dependencies so
755  * it's easy to use with creduce. */
756 #if defined(SIMDE_TEST_BARE)
757   #define SIMDE_TEST_FUNC_LIST_BEGIN static const struct { int (* func)(void); const char* name; } test_suite_tests[] = {
758   #define SIMDE_TEST_FUNC_LIST_ENTRY(name) { test_simde_##name, #name },
759   #define SIMDE_TEST_FUNC_LIST_END };
760   #define SIMDE_MUNIT_TEST_ARGS void
761 #else
762   HEDLEY_DIAGNOSTIC_PUSH
763   SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_
764   SIMDE_DIAGNOSTIC_DISABLE_OLD_STYLE_CAST_
765   SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_
766   SIMDE_DIAGNOSTIC_DISABLE_RESERVED_ID_MACRO_
767   #include "munit/munit.h"
768   HEDLEY_DIAGNOSTIC_POP
769 
770   #if \
771       HEDLEY_HAS_ATTRIBUTE(unused) || \
772       HEDLEY_GCC_VERSION_CHECK(3,1,0)
773     #define SIMDE_MUNIT_TEST_ARGS __attribute__((__unused__)) const MunitParameter params[], __attribute__((__unused__)) void* data
774   #else
775     /* Compilers other than emscripten are fine with casting away
776      * arguments. */
777     #define SIMDE_MUNIT_TEST_ARGS void
778   #endif
779 
780   #define SIMDE_TEST_FUNC_LIST_BEGIN static MunitTest test_suite_tests[] = {
781   #if defined(__cplusplus)
782     #define SIMDE_TEST_FUNC_LIST_ENTRY(name) { \
783         const_cast<char*>("/" SIMDE_TEST_GENERATE_VARIANT_NAME_CURRENT(name)), \
784         HEDLEY_REINTERPRET_CAST(MunitTestFunc, test_simde_##name), \
785         NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
786   #else
787     #define SIMDE_TEST_FUNC_LIST_ENTRY(name) { \
788         (char*) "/" SIMDE_TEST_GENERATE_VARIANT_NAME_CURRENT(name), \
789         HEDLEY_REINTERPRET_CAST(MunitTestFunc, test_simde_##name), \
790         NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
791   #endif
792   #define SIMDE_TEST_FUNC_LIST_END { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } };
793 
794   #define SIMDE_TEST_SUITE_DECLARE_GETTERS(name) \
795     HEDLEY_C_DECL MunitSuite* HEDLEY_CONCAT(name, _native_c)(void); \
796     HEDLEY_C_DECL MunitSuite* HEDLEY_CONCAT(name, _emul_c)(void); \
797     HEDLEY_C_DECL MunitSuite* HEDLEY_CONCAT(name, _native_cpp)(void); \
798     HEDLEY_C_DECL MunitSuite* HEDLEY_CONCAT(name, _emul_cpp)(void);
799 #endif
800 
801 #endif /* !defined(SIMDE_TESTS_H) */
802