6#ifndef __SOLIDC_MACROS__
7#define __SOLIDC_MACROS__
21 printf("%s:%d [%s]: Assertion '%s' failed.\n", __FILE__, __LINE__, __func__, #cond); \
26#define ASSERT_EQ(a, b) \
31 printf("%s:%d [%s]: Assertion '%s == %s' failed (%ld != %ld).\n", __FILE__, __LINE__, __func__, #a, #b, \
32 (intptr_t)_a, (intptr_t)_b); \
37#define ASSERT_NE(a, b) \
42 printf("%s:%d [%s]: Assertion '%s != %s' failed (both are %ld).\n", __FILE__, __LINE__, __func__, #a, #b, \
48#define ASSERT_TRUE(cond) \
51 printf("%s:%d [%s]: Assertion '%s' is not true.\n", __FILE__, __LINE__, __func__, #cond); \
56#define ASSERT_STR_EQ(a, b) \
58 const char* _a = (a); \
59 const char* _b = (b); \
60 if (_a == NULL || _b == NULL) { \
62 printf("%s:%d [%s]: Assertion '%s == %s' failed (one is NULL).\n", __FILE__, __LINE__, __func__, #a, \
66 } else if (strcmp(_a, _b) != 0) { \
67 printf("%s:%d [%s]: Assertion '%s == %s' failed (\"%s\" != \"%s\").\n", __FILE__, __LINE__, __func__, #a, \
73#define ASSERT_NULL(ptr) \
75 if ((ptr) != NULL) { \
76 printf("%s:%d [%s]: Expected '%s' to be NULL.\n", __FILE__, __LINE__, __func__, #ptr); \
81#define ASSERT_NOT_NULL(ptr) \
83 if ((ptr) == NULL) { \
84 printf("%s:%d [%s]: Expected '%s' to not be NULL.\n", __FILE__, __LINE__, __func__, #ptr); \
89#define ASSERT_RANGE(val, min, max) \
91 typeof(val) _val = (val); \
92 typeof(min) _min = (min); \
93 typeof(max) _max = (max); \
94 if (_val < _min || _val > _max) { \
95 printf("%s:%d [%s]: Value %ld is not in range [%ld, %ld].\n", __FILE__, __LINE__, __func__, (long)_val, \
96 (long)_min, (long)_max); \
101#define ASSERT_FLOAT_EQ(a, b, epsilon) \
103 double _a = (double)(a); \
104 double _b = (double)(b); \
105 double _eps = (double)(epsilon); \
106 if ((_a - _b) > _eps || (_b - _a) > _eps) { \
107 printf("%s:%d [%s]: Float assertion '%s == %s' failed (%.6f != %.6f, epsilon=%.6f).\n", __FILE__, \
108 __LINE__, __func__, #a, #b, _a, _b, _eps); \
117#if defined(__cplusplus)
118#define STATIC_ASSERT(cond, msg) static_assert(cond, msg)
120#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
124#if defined(__GNUC__) || defined(__clang__)
125#define PRINTF_FORMAT(fmt, va) __attribute__((format(printf, fmt, va)))
127#define PRINTF_FORMAT(fmt, va)
131#if defined(__GNUC__) || defined(__clang__)
132#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
133#elif defined(_MSC_VER)
134#define WARN_UNUSED_RESULT _Check_return_
136#define WARN_UNUSED_RESULT
139#define IS_POWER_OF_2(n) ((n) > 0 && ((n) & ((n) - 1)) == 0)
140#define STATIC_CHECK_POWER_OF_2(n) STATIC_ASSERT(IS_POWER_OF_2(n), #n " is not a power of 2")
146#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
147#define ZERO_MEMORY(ptr, size) memset(ptr, 0, size)
148#define ZERO_STRUCT(s) memset(&(s), 0, sizeof(s))
149#define ZERO_ARRAY(arr) memset(arr, 0, sizeof(arr))
155#define MIN(a, b) ((a) < (b) ? (a) : (b))
156#define MAX(a, b) ((a) > (b) ? (a) : (b))
157#define ABS(x) ((x) < 0 ? -(x) : (x))
158#define CLAMP(x, min, max) (MIN(MAX(x, min), max))
161 typeof(a) _tmp = a; \
167#define SET_BIT(num, pos) ((num) |= (1ULL << (pos)))
168#define CLEAR_BIT(num, pos) ((num) &= ~(1ULL << (pos)))
169#define TOGGLE_BIT(num, pos) ((num) ^= (1ULL << (pos)))
170#define CHECK_BIT(num, pos) (((num) >> (pos)) & 1)
173#define ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
174#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
175#define IS_ALIGNED(x, align) (((x) & ((align) - 1)) == 0)
178#define ROUND_UP_POW2(x) \
180 typeof(x) _x = (x); \
187 if (sizeof(_x) > 4) _x |= _x >> 32; \
195#define STREQ(a, b) (strcmp(a, b) == 0)
196#define STRNEQ(a, b, n) (strncmp(a, b, n) == 0)
197#define STR_EMPTY(s) ((s) == NULL || (s)[0] == '\0')
198#define STR_NOT_EMPTY(s) ((s) != NULL && (s)[0] != '\0')
205#define DEBUG_PRINT(fmt, ...) (void)fmt;
206#define DEBUG_VAR(var) (void)var;
207#define DEBUG_STR(str) (void)str;
209#define DEBUG_PRINT(fmt, ...) printf("[DEBUG] %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
210#define DEBUG_VAR(var) printf("[DEBUG] %s:%d: %s = %ld\n", __FILE__, __LINE__, #var, (long)(var))
211#define DEBUG_STR(str) printf("[DEBUG] %s:%d: %s = \"%s\"\n", __FILE__, __LINE__, #str, (str) ? (str) : "NULL")
214#define LOG_ERROR(fmt, ...) \
215 fprintf(stderr, "[ERROR] %s:%d [%s]: " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
217#define LOG_WARN(fmt, ...) fprintf(stderr, "[WARN] %s:%d [%s]: " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
219#define LOG_INFO(fmt, ...) printf("[INFO] %s:%d [%s]: " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
225#define FOR_EACH_ARRAY(item, array) \
226 for (typeof((array)[0])*item = (array), *_end = (array) + ARRAY_SIZE(array); item < _end; ++item)
228#define FOR_EACH_RANGE(var, start, end) for (typeof(start) var = (start); var < (end); ++var)
237#define TIME_DIFF(start, end, freq) ((double)((end).QuadPart - (start).QuadPart) / (double)(freq).QuadPart)
239#define TIME_DIFF_MS(start, end, freq) ((double)((end).QuadPart - (start).QuadPart) * 1000.0 / (double)(freq).QuadPart)
244#define TIME_DIFF(start, end) \
245 ((double)((end).tv_sec - (start).tv_sec) + (double)((end).tv_nsec - (start).tv_nsec) / 1e9)
248#define TIME_DIFF_MS(start, end) \
249 ((double)((end).tv_sec - (start).tv_sec) * 1000.0 + (double)((end).tv_nsec - (start).tv_nsec) / 1.0e6)
254#define TIME_BLOCK(name, block) \
256 LARGE_INTEGER _freq, _start, _end; \
257 QueryPerformanceFrequency(&_freq); \
258 QueryPerformanceCounter(&_start); \
259 block QueryPerformanceCounter(&_end); \
260 double _time = TIME_DIFF(_start, _end, _freq); \
261 printf("Time for %s: %.6f seconds\n", name, _time); \
264#define TIME_BLOCK(name, block) \
266 struct timespec _start, _end; \
267 clock_gettime(CLOCK_MONOTONIC, &_start); \
268 block clock_gettime(CLOCK_MONOTONIC, &_end); \
269 double _time = TIME_DIFF(_start, _end); \
270 printf("Time for %s: %.6f seconds\n", name, _time); \
275#define TIME_BLOCK_MS(name, block) \
277 LARGE_INTEGER _freq, _start, _end; \
278 QueryPerformanceFrequency(&_freq); \
279 QueryPerformanceCounter(&_start); \
280 block QueryPerformanceCounter(&_end); \
281 double _ms = TIME_DIFF_MS(_start, _end, _freq); \
282 printf("Time for %s: %.3f ms\n", name, _ms); \
285#define TIME_BLOCK_MS(name, block) \
287 struct timespec _start, _end; \
288 clock_gettime(CLOCK_MONOTONIC, &_start); \
289 block clock_gettime(CLOCK_MONOTONIC, &_end); \
290 double _ms = TIME_DIFF_MS(_start, _end); \
291 printf("Time for %s: %.3f ms\n", name, _ms); \
296static inline uint64_t get_time_ns(
void) {
298 LARGE_INTEGER freq, counter;
299 QueryPerformanceFrequency(&freq);
300 QueryPerformanceCounter(&counter);
304 uint64_t seconds = counter.QuadPart / freq.QuadPart;
305 uint64_t remainder = counter.QuadPart % freq.QuadPart;
306 return (seconds * 1000000000ULL) + ((remainder * 1000000000ULL) / freq.QuadPart);
310 clock_gettime(CLOCK_MONOTONIC, &ts);
311 return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec;