1 /* Check (assertions)
2  * Portable Snippets - https://gitub.com/nemequ/portable-snippets
3  * Created by Evan Nemerson <evan@nemerson.com>
4  *
5  *   To the extent possible under law, the authors have waived all
6  *   copyright and related or neighboring rights to this code.  For
7  *   details, see the Creative Commons Zero 1.0 Universal license at
8  *   https://creativecommons.org/publicdomain/zero/1.0/
9  *
10  * SPDX-License-Identifier: CC0-1.0
11  */
12 
13 #if !defined(SIMDE_CHECK_H)
14 #define SIMDE_CHECK_H
15 
16 #if !defined(SIMDE_NDEBUG) && !defined(SIMDE_DEBUG)
17 #  define SIMDE_NDEBUG 1
18 #endif
19 
20 #include "hedley.h"
21 #include "simde-diagnostic.h"
22 #include <stdint.h>
23 
24 #if !defined(_WIN32)
25 #  define SIMDE_SIZE_MODIFIER "z"
26 #  define SIMDE_CHAR_MODIFIER "hh"
27 #  define SIMDE_SHORT_MODIFIER "h"
28 #else
29 #  if defined(_M_X64) || defined(__amd64__)
30 #    define SIMDE_SIZE_MODIFIER "I64"
31 #  else
32 #    define SIMDE_SIZE_MODIFIER ""
33 #  endif
34 #  define SIMDE_CHAR_MODIFIER ""
35 #  define SIMDE_SHORT_MODIFIER ""
36 #endif
37 
38 #if defined(_MSC_VER) &&  (_MSC_VER >= 1500)
39 #  define SIMDE_PUSH_DISABLE_MSVC_C4127_ __pragma(warning(push)) __pragma(warning(disable:4127))
40 #  define SIMDE_POP_DISABLE_MSVC_C4127_ __pragma(warning(pop))
41 #else
42 #  define SIMDE_PUSH_DISABLE_MSVC_C4127_
43 #  define SIMDE_POP_DISABLE_MSVC_C4127_
44 #endif
45 
46 #if !defined(simde_errorf)
47 #  if defined(__has_include)
48 #    if __has_include(<stdio.h>)
49 #      include <stdio.h>
50 #    endif
51 #  elif defined(SIMDE_STDC_HOSTED)
52 #    if SIMDE_STDC_HOSTED == 1
53 #      include <stdio.h>
54 #    endif
55 #  elif defined(__STDC_HOSTED__)
56 #    if __STDC_HOSTETD__ == 1
57 #      include <stdio.h>
58 #    endif
59 #  endif
60 
61 #  include "debug-trap.h"
62 
63    HEDLEY_DIAGNOSTIC_PUSH
64    SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_
65 #  if defined(EOF)
66 #    define simde_errorf(format, ...) (fprintf(stderr, format, __VA_ARGS__), abort())
67 #  else
68 #    define simde_errorf(format, ...) (simde_trap())
69 #  endif
70    HEDLEY_DIAGNOSTIC_POP
71 #endif
72 
73 #define simde_error(msg) simde_errorf("%s", msg)
74 
75 #if defined(SIMDE_NDEBUG) || \
76     (defined(__cplusplus) && (__cplusplus < 201103L)) || \
77     (defined(__STDC__) && (__STDC__ < 199901L))
78 #  if defined(SIMDE_CHECK_FAIL_DEFINED)
79 #    define simde_assert(expr)
80 #  else
81 #    if defined(HEDLEY_ASSUME)
82 #      define simde_assert(expr) HEDLEY_ASSUME(expr)
83 #    elif HEDLEY_GCC_VERSION_CHECK(4,5,0)
84 #      define simde_assert(expr) ((void) (!!(expr) ? 1 : (__builtin_unreachable(), 1)))
85 #    elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
86 #      define simde_assert(expr) __assume(expr)
87 #    else
88 #      define simde_assert(expr)
89 #    endif
90 #  endif
91 #  define simde_assert_true(expr) simde_assert(expr)
92 #  define simde_assert_false(expr) simde_assert(!(expr))
93 #  define simde_assert_type_full(prefix, suffix, T, fmt, a, op, b) simde_assert(((a) op (b)))
94 #  define simde_assert_double_equal(a, b, precision)
95 #  define simde_assert_string_equal(a, b)
96 #  define simde_assert_string_not_equal(a, b)
97 #  define simde_assert_memory_equal(size, a, b)
98 #  define simde_assert_memory_not_equal(size, a, b)
99 #else
100 #  define simde_assert(expr) \
101     do { \
102       if (!HEDLEY_LIKELY(expr)) { \
103         simde_error("assertion failed: " #expr "\n"); \
104       } \
105       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
106     } while (0) \
107     SIMDE_POP_DISABLE_MSVC_C4127_
108 
109 #  define simde_assert_true(expr) \
110     do { \
111       if (!HEDLEY_LIKELY(expr)) { \
112         simde_error("assertion failed: " #expr " is not true\n"); \
113       } \
114       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
115     } while (0) \
116     SIMDE_POP_DISABLE_MSVC_C4127_
117 
118 #  define simde_assert_false(expr) \
119     do { \
120       if (!HEDLEY_LIKELY(!(expr))) { \
121         simde_error("assertion failed: " #expr " is not false\n"); \
122       } \
123       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
124     } while (0) \
125     SIMDE_POP_DISABLE_MSVC_C4127_
126 
127 #  define simde_assert_type_full(prefix, suffix, T, fmt, a, op, b)   \
128     do { \
129       T simde_tmp_a_ = (a); \
130       T simde_tmp_b_ = (b); \
131       if (!(simde_tmp_a_ op simde_tmp_b_)) { \
132         simde_errorf("assertion failed: %s %s %s (" prefix "%" fmt suffix " %s " prefix "%" fmt suffix ")\n", \
133                      #a, #op, #b, simde_tmp_a_, #op, simde_tmp_b_); \
134       } \
135       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
136     } while (0) \
137     SIMDE_POP_DISABLE_MSVC_C4127_
138 
139 #  define simde_assert_double_equal(a, b, precision) \
140     do { \
141       const double simde_tmp_a_ = (a); \
142       const double simde_tmp_b_ = (b); \
143       const double simde_tmp_diff_ = ((simde_tmp_a_ - simde_tmp_b_) < 0) ? \
144         -(simde_tmp_a_ - simde_tmp_b_) : \
145         (simde_tmp_a_ - simde_tmp_b_); \
146       if (HEDLEY_UNLIKELY(simde_tmp_diff_ > 1e-##precision)) { \
147         simde_errorf("assertion failed: %s == %s (%0." #precision "g == %0." #precision "g)\n", \
148                      #a, #b, simde_tmp_a_, simde_tmp_b_); \
149       } \
150       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
151     } while (0) \
152     SIMDE_POP_DISABLE_MSVC_C4127_
153 
154 #  include <string.h>
155 #  define simde_assert_string_equal(a, b) \
156     do { \
157       const char* simde_tmp_a_ = a; \
158       const char* simde_tmp_b_ = b; \
159       if (HEDLEY_UNLIKELY(strcmp(simde_tmp_a_, simde_tmp_b_) != 0)) { \
160         simde_errorf("assertion failed: string %s == %s (\"%s\" == \"%s\")\n", \
161                      #a, #b, simde_tmp_a_, simde_tmp_b_); \
162       } \
163       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
164     } while (0) \
165     SIMDE_POP_DISABLE_MSVC_C4127_
166 
167 #  define simde_assert_string_not_equal(a, b) \
168     do { \
169       const char* simde_tmp_a_ = a; \
170       const char* simde_tmp_b_ = b; \
171       if (HEDLEY_UNLIKELY(strcmp(simde_tmp_a_, simde_tmp_b_) == 0)) { \
172         simde_errorf("assertion failed: string %s != %s (\"%s\" == \"%s\")\n", \
173                      #a, #b, simde_tmp_a_, simde_tmp_b_); \
174       } \
175       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
176     } while (0) \
177     SIMDE_POP_DISABLE_MSVC_C4127_
178 
179 #  define simde_assert_memory_equal(size, a, b) \
180     do { \
181       const unsigned char* simde_tmp_a_ = (const unsigned char*) (a); \
182       const unsigned char* simde_tmp_b_ = (const unsigned char*) (b); \
183       const size_t simde_tmp_size_ = (size); \
184       if (HEDLEY_UNLIKELY(memcmp(simde_tmp_a_, simde_tmp_b_, simde_tmp_size_)) != 0) { \
185         size_t simde_tmp_pos_; \
186         for (simde_tmp_pos_ = 0 ; simde_tmp_pos_ < simde_tmp_size_ ; simde_tmp_pos_++) { \
187           if (simde_tmp_a_[simde_tmp_pos_] != simde_tmp_b_[simde_tmp_pos_]) { \
188             simde_errorf("assertion failed: memory %s == %s, at offset %" SIMDE_SIZE_MODIFIER "u\n", \
189                          #a, #b, simde_tmp_pos_); \
190             break; \
191           } \
192         } \
193       } \
194       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
195     } while (0) \
196     SIMDE_POP_DISABLE_MSVC_C4127_
197 
198 #  define simde_assert_memory_not_equal(size, a, b) \
199     do { \
200       const unsigned char* simde_tmp_a_ = (const unsigned char*) (a); \
201       const unsigned char* simde_tmp_b_ = (const unsigned char*) (b); \
202       const size_t simde_tmp_size_ = (size); \
203       if (HEDLEY_UNLIKELY(memcmp(simde_tmp_a_, simde_tmp_b_, simde_tmp_size_)) == 0) { \
204         simde_errorf("assertion failed: memory %s != %s (%" SIMDE_SIZE_MODIFIER "u bytes)\n", \
205                      #a, #b, simde_tmp_size_); \
206       } \
207       SIMDE_PUSH_DISABLE_MSVC_C4127_ \
208     } while (0) \
209     SIMDE_POP_DISABLE_MSVC_C4127_
210 #endif
211 
212 #define simde_assert_type(T, fmt, a, op, b) \
213   simde_assert_type_full("", "", T, fmt, a, op, b)
214 
215 #define simde_assert_char(a, op, b) \
216   simde_assert_type_full("'\\x", "'", char, "02" SIMDE_CHAR_MODIFIER "x", a, op, b)
217 #define simde_assert_uchar(a, op, b) \
218   simde_assert_type_full("'\\x", "'", unsigned char, "02" SIMDE_CHAR_MODIFIER "x", a, op, b)
219 #define simde_assert_short(a, op, b) \
220   simde_assert_type(short, SIMDE_SHORT_MODIFIER "d", a, op, b)
221 #define simde_assert_ushort(a, op, b) \
222   simde_assert_type(unsigned short, SIMDE_SHORT_MODIFIER "u", a, op, b)
223 #define simde_assert_int(a, op, b) \
224   simde_assert_type(int, "d", a, op, b)
225 #define simde_assert_uint(a, op, b) \
226   simde_assert_type(unsigned int, "u", a, op, b)
227 #define simde_assert_long(a, op, b) \
228   simde_assert_type(long int, "ld", a, op, b)
229 #define simde_assert_ulong(a, op, b) \
230   simde_assert_type(unsigned long int, "lu", a, op, b)
231 #define simde_assert_llong(a, op, b) \
232   simde_assert_type(long long int, "lld", a, op, b)
233 #define simde_assert_ullong(a, op, b) \
234   simde_assert_type(unsigned long long int, "llu", a, op, b)
235 
236 #define simde_assert_size(a, op, b) \
237   simde_assert_type(size_t, SIMDE_SIZE_MODIFIER "u", a, op, b)
238 
239 #define simde_assert_float(a, op, b) \
240   simde_assert_type(float, "f", a, op, b)
241 #define simde_assert_double(a, op, b) \
242   simde_assert_type(double, "g", a, op, b)
243 #define simde_assert_ptr(a, op, b) \
244   simde_assert_type(const void*, "p", a, op, b)
245 
246 #define simde_assert_int8(a, op, b) \
247   simde_assert_type(int8_t, PRIi8, a, op, b)
248 #define simde_assert_uint8(a, op, b) \
249   simde_assert_type(uint8_t, PRIu8, a, op, b)
250 #define simde_assert_int16(a, op, b) \
251   simde_assert_type(int16_t, PRIi16, a, op, b)
252 #define simde_assert_uint16(a, op, b) \
253   simde_assert_type(uint16_t, PRIu16, a, op, b)
254 #define simde_assert_int32(a, op, b) \
255   simde_assert_type(int32_t, PRIi32, a, op, b)
256 #define simde_assert_uint32(a, op, b) \
257   simde_assert_type(uint32_t, PRIu32, a, op, b)
258 #define simde_assert_int64(a, op, b) \
259   simde_assert_type(int64_t, PRIi64, a, op, b)
260 #define simde_assert_uint64(a, op, b) \
261   simde_assert_type(uint64_t, PRIu64, a, op, b)
262 
263 #define simde_assert_ptr_equal(a, b) \
264   simde_assert_ptr(a, ==, b)
265 #define simde_assert_ptr_not_equal(a, b) \
266   simde_assert_ptr(a, !=, b)
267 #define simde_assert_null(ptr) \
268   simde_assert_ptr(ptr, ==, NULL)
269 #define simde_assert_not_null(ptr) \
270   simde_assert_ptr(ptr, !=, NULL)
271 #define simde_assert_ptr_null(ptr) \
272   simde_assert_ptr(ptr, ==, NULL)
273 #define simde_assert_ptr_not_null(ptr) \
274   simde_assert_ptr(ptr, !=, NULL)
275 
276 #endif /* !defined(SIMDE_CHECK_H) */
277