Go to the documentation of this file.
43 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
44 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x04
51 #include <sys/ioctl.h>
55 #if defined(__APPLE__) && defined(__MACH__)
56 #include <mach/mach_time.h>
71 static LARGE_INTEGER freq;
74 if (!QueryPerformanceFrequency(&freq))
77 if (!QueryPerformanceCounter(&ts))
79 return UINT64_C(1000000000) * ts.QuadPart / freq.QuadPart;
80 #elif defined(__APPLE__) && defined(__MACH__)
81 static mach_timebase_info_data_t tb_info;
83 if (mach_timebase_info(&tb_info) != KERN_SUCCESS)
86 return mach_absolute_time() * tb_info.numer / tb_info.denom;
87 #elif HAVE_CLOCK_GETTIME
91 #ifdef CLOCK_MONOTONIC_RAW
92 id = CLOCK_MONOTONIC_RAW;
99 if (clock_gettime(
id, &ts) < 0)
101 return UINT64_C(1000000000) * ts.tv_sec + ts.tv_nsec;
138 const uint32_t t = x ^ (x << 11);
145 return xs_state[3] = (
w ^ (
w >> 19)) ^ (t ^ (t >> 8));
161 static_assert(
sizeof(
int) <=
sizeof(uint32_t),
"int larger than 32 bits");
177 w = u1 * u1 + u2 * u2;
180 w = sqrt((-2.0 *
log(
w)) /
w);
189 if ((cached = !cached)) {
232 #define RANDOMIZE_DIST(buf, ftype, width, mean, stddev) \
235 *(buf)++ = (ftype) ((mean) + (stddev) * checkasm_rand_norm()); \
239 for (; width; width -= 2) { \
241 z1 = marsaglia(&z2); \
242 *(buf)++ = (ftype) ((mean) + (stddev) * z1); \
243 *(buf)++ = (ftype) ((mean) + (stddev) * z2); \
269 memset(buf, 0xAA, bytes);
286 static inline int clz(
const unsigned int mask)
291 #elif defined(_MSC_VER) && !defined(__clang__)
294 static inline int clz(
const unsigned int mask)
296 unsigned long leading_zero = 0;
297 _BitScanReverse(&leading_zero,
mask);
298 return (31 - leading_zero);
302 static inline int clz(
const unsigned int mask)
304 return __builtin_clz(
mask);
311 const int bits = 8 *
sizeof(x) -
clz(x);
331 #define DEF_CHECKASM_INIT_MASK(BITS, PIXEL) \
332 void checkasm_init_mask##BITS(PIXEL *buf, const int width, const PIXEL mask_pixel) \
337 int step = 0, mode = 0, mask = mask_pixel; \
338 for (int i = 0; i < width; i++, step--) { \
340 step = imax(shift_rand(width), 1); \
341 mode = checkasm_rand() & 7; \
342 mask = shift_rand(mask_pixel); \
345 const PIXEL low = checkasm_rand_uint32() & mask; \
346 const PIXEL high = mask_pixel - low; \
348 case PAT_ZERO: buf[i] = 0; break; \
349 case PAT_ONE: buf[i] = mask_pixel; break; \
350 case PAT_RAND: buf[i] = checkasm_rand_uint32() & mask_pixel; break; \
351 case PAT_LOW: buf[i] = low; break; \
352 case PAT_HIGH: buf[i] = high; break; \
353 case PAT_ALTLO: buf[i] = (i & 1) ? high : low; break; \
354 case PAT_ALTHI: buf[i] = (i & 1) ? low : high; break; \
355 case PAT_MIX: buf[i] = (checkasm_rand() & 1) ? low : high; break; \
372 fprintf(
f,
"\x1b[0;%dm",
color);
375 vfprintf(
f, fmt,
arg);
379 fprintf(
f,
"\x1b[0m");
385 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
386 HANDLE con = GetStdHandle(
f == stderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
388 return con && con != INVALID_HANDLE_VALUE && GetConsoleMode(con, &con_mode)
389 && SetConsoleMode(con, con_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
394 if (isatty(
f == stderr ? 2 : 1)) {
395 const char *
const term = getenv(
"TERM");
396 return term && strcmp(term,
"dumb");
413 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
414 CONSOLE_SCREEN_BUFFER_INFO csbi;
415 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
416 return csbi.srWindow.Right - csbi.srWindow.Left + 1;
418 #elif defined(__OS2__)
422 #elif HAVE_IOCTL && defined(TIOCGWINSZ)
424 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &
w) != -1)
432 assert(json->
level > 0);
434 for (
int i = 0;
i < json->
level;
i++)
435 fputc(
' ', json->
file);
440 fprintf(json->
file,
"\"%s\": ",
key);
441 vfprintf(json->
file, fmt, ap);
448 assert(json->
level > 0);
450 for (
int i = 0;
i < json->
level;
i++)
451 fputc(
' ', json->
file);
454 fprintf(json->
file,
"\"%s\": \"",
key);
456 fputc(
'"', json->
file);
460 case '\\': fputs(
"\\\\", json->
file);
break;
461 case '"': fputs(
"\\\"", json->
file);
break;
462 case '\n': fputs(
"\\n", json->
file);
break;
463 default: fputc(*str, json->
file);
break;
467 fputc(
'"', json->
file);
474 for (
int i = 0;
i < json->
level;
i++)
475 fputc(
' ', json->
file);
489 assert(json->
level >= 2);
492 fputc(
'\n', json->
file);
493 for (
int i = 0;
i < json->
level;
i++)
494 fputc(
' ', json->
file);
523 if (llabs((
int64_t) x.
i - y.
i) <= max_ulp)
530 const unsigned max_ulp,
const int len)
532 for (
int i = 0;
i <
len;
i++)
545 const float eps,
const int len)
547 for (
int i = 0;
i <
len;
i++)
555 const unsigned max_ulp)
561 const float eps,
const unsigned max_ulp,
564 for (
int i = 0;
i <
len;
i++)
577 const double eps,
const unsigned len)
579 for (
unsigned i = 0;
i <
len;
i++)
587 const int w,
const int h,
int *
const err)
594 fprintf(stderr,
"%s (%dx%d):\n",
name,
w,
h);
598 #define PRINT_LINE(buf1, buf2, xstart, xend, xpad, fmt, fmtw) \
600 for (int x = xstart; x < xend; x++) { \
601 if (buf1[x] != buf2[x]) \
602 checkasm_fprintf(stderr, COLOR_RED, " " fmt, buf1[x]); \
604 fprintf(stderr, " " fmt, buf1[x]); \
606 for (int pad = xend; pad < xstart + xpad; pad++) \
607 fprintf(stderr, &" "[9 - fmtw]); \
610 #define PRINT_RECT(type, buf1, buf2, ystart, yend, xstart, xend, fmt, fmtw) \
612 const type *ptr1 = (buf1) + ystart * stride1; \
613 const type *ptr2 = (buf2) + ystart * stride1; \
614 const int elem_size = 2 * (fmtw + 1) + 1; \
615 const int display_elems = imin(term_width / elem_size, xend - xstart); \
616 for (int y = ystart; y < yend; y++) { \
617 for (int xpos = xstart; xpos < xend; xpos += display_elems) { \
618 const int xstep = imin(xpos + display_elems, xend); \
619 if (xpos == xstart) \
620 checkasm_fprintf(stderr, COLOR_BLUE, "%3d: ", y); \
622 fprintf(stderr, " "); \
623 PRINT_LINE(ptr1, ptr2, xpos, xstep, display_elems, fmt, fmtw); \
624 fprintf(stderr, " "); \
625 PRINT_LINE(ptr2, ptr1, xpos, xstep, display_elems, fmt, fmtw); \
626 fprintf(stderr, " "); \
627 for (int x = xpos; x < xstep; x++) { \
628 if (ptr1[x] != ptr2[x]) \
629 checkasm_fprintf(stderr, COLOR_RED, "x"); \
631 fprintf(stderr, "."); \
633 fprintf(stderr, "\n"); \
640 #define CHECK_RECT(buf1, buf2, ystart, yend, xstart, xend, msg, compare, type, fmt, \
643 const int xw = xend - xstart; \
644 for (int y = ystart; y < yend; y++) { \
645 if (compare(&buf1[y * stride1 + xstart], &buf2[y * stride2 + xstart], xw)) \
647 if (check_err(file, line, name, w, h, &err)) \
650 int yprint = y < 0 ? y : ystart; \
652 fprintf(stderr, " %s (%dx%d, from idx [%d]):\n", msg, xend - xstart, \
653 yend - yprint, xstart); \
654 PRINT_RECT(type, buf1, buf2, yprint, yend, xstart, xend, fmt, fmtw); \
659 #define DEF_CHECKASM_CHECK_BODY(compare, type, fmt, fmtw) \
661 const int overhead = 5 + 3 + 3; \
662 const int term_width = get_terminal_width() - overhead; \
663 const int aligned_w = (w + align_w - 1) & ~(align_w - 1); \
664 stride1 /= sizeof(type); \
665 stride2 /= sizeof(type); \
668 CHECK_RECT(buf1, buf2, 0, h, 0, w, "", compare, type, fmt, fmtw); \
669 if (align_h >= 1) { \
670 const int aligned_h = (h + align_h - 1) & ~(align_h - 1); \
671 CHECK_RECT(buf1, buf2, -padding, 0, -padding, w + padding, "overwrite top", \
672 compare, type, fmt, fmtw); \
673 CHECK_RECT(buf1, buf2, aligned_h, aligned_h + padding, -padding, \
674 w + padding, "overwrite bottom", compare, type, fmt, fmtw); \
676 CHECK_RECT(buf1, buf2, 0, h, -padding, 0, "overwrite left", compare, type, fmt, \
678 CHECK_RECT(buf1, buf2, 0, h, aligned_w, aligned_w + padding, "overwrite right", \
679 compare, type, fmt, fmtw); \
683 #define cmp_int(a, b, len) (!memcmp(a, b, (len) * sizeof(*(a))))
684 #define DEF_CHECKASM_CHECK_FUNC(type, fmt, fmtw) \
685 int checkasm_check_impl_##type(const char *file, int line, const type *buf1, \
686 ptrdiff_t stride1, const type *buf2, \
687 ptrdiff_t stride2, int w, int h, const char *name, \
688 int align_w, int align_h, int padding) \
690 DEF_CHECKASM_CHECK_BODY(cmp_int, type, fmt, fmtw); \
704 ptrdiff_t stride1, const
float *buf2, ptrdiff_t stride2,
705 int w,
int h, const
char *
name,
unsigned max_ulp,
706 int align_w,
int align_h,
int padding)
708 #define cmp_float(a, b, len) float_near_ulp_array(a, b, max_ulp, len)
static int clz(const unsigned int mask)
void checkasm_randomize_distf(float *buf, int width, CheckasmDist dist)
Fill a float buffer with normally distributed random values.
void checkasm_randomize_dist(double *buf, int width, CheckasmDist dist)
Fill a double buffer with normally distributed random values.
double stddev
Standard deviation (spread) of the distribution.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
static double marsaglia(double *z2)
void checkasm_randomize_mask16(uint16_t *buf, int width, uint16_t mask)
Fill a uint16_t buffer with random values chosen uniformly within a mask.
#define DEF_CHECKASM_CHECK_FUNC(type, fmt, fmtw)
void checkasm_srand(unsigned seed)
int checkasm_float_near_abs_eps_array_ulp(const float *const a, const float *const b, const float eps, const unsigned max_ulp, const int len)
Compare float arrays using both epsilon and ULP tolerances.
static int get_terminal_width(void)
#define u(width, name, range_min, range_max)
void checkasm_clear8(uint8_t *buf, int width, uint8_t val)
Fill a uint8_t buffer with a constant value.
int checkasm_float_near_abs_eps_ulp(const float a, const float b, const float eps, const unsigned max_ulp)
Compare floats using both epsilon and ULP tolerances.
static int check_err(const char *const file, const int line, const char *const name, const int w, const int h, int *const err)
void checkasm_randomize_mask8(uint8_t *buf, int width, uint8_t mask)
Fill a uint8_t buffer with random values chosen uniformly within a mask.
double checkasm_randf(void)
Generate a random double-precision floating-point number.
void checkasm_randomize_range(double *buf, int width, double range)
Fill a double buffer with random values chosen uniformly below a limit.
static COLD int should_use_color(FILE *const f)
CHECKASM_API CheckasmKey CHECKASM_API void CHECKASM_API int checkasm_fail_func(const char *msg,...) CHECKASM_PRINTF(1
Mark the current function as failed with a custom message.
static double val(void *priv, double ch)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
void checkasm_json(CheckasmJson *json, const char *key, const char *const fmt,...)
static __device__ float fabsf(float a)
int checkasm_float_near_abs_eps(const float a, const float b, const float eps)
Compare floats using absolute epsilon tolerance.
static void * checkasm_mallocz(const size_t size)
void checkasm_randomize_norm(double *buf, int width)
Fill a double buffer with values from a standard normal distribution.
int32_t checkasm_rand_int32(void)
Generate a random 32-bit signed integer.
void checkasm_init(void *buf, size_t bytes)
Initialize a buffer with pathological test patterns.
static int use_printf_color[2]
int checkasm_float_near_abs_eps_array(const float *const a, const float *const b, const float eps, const int len)
Compare float arrays using absolute epsilon tolerance.
#define DEF_CHECKASM_CHECK_BODY(compare, type, fmt, fmtw)
uint64_t checkasm_gettime_nsec(void)
#define float_near_abs_eps
void checkasm_randomize(void *bufp, size_t bytes)
Fill a buffer with uniformly chosen random bytes.
static __device__ float fabs(float a)
double mean
Mean (center) of the distribution.
#define cmp_float(a, b, len)
double checkasm_rand_norm(void)
Generate a random number from the standard normal distribution.
int checkasm_check_impl_float_ulp(const char *file, int line, const float *buf1, ptrdiff_t stride1, const float *buf2, ptrdiff_t stride2, int w, int h, const char *name, unsigned max_ulp, int align_w, int align_h, int padding)
Compare float buffers with ULP tolerance.
int checkasm_double_near_abs_eps_array(const double *const a, const double *const b, const double eps, const unsigned len)
Compare double arrays using absolute epsilon tolerance.
unsigned checkasm_seed(void)
static int is_negative(const intfloat u)
void checkasm_json_push(CheckasmJson *json, const char *const key, const char type)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
#define i(width, name, range_min, range_max)
Test writing API for checkasm.
void checkasm_randomize_normf(float *buf, int width)
Fill a float buffer with values from a standard normal distribution.
NOINLINE void checkasm_noop(void *ptr)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
CHECKASM_API void checkasm_init_mask8(uint8_t *buf, int width, uint8_t mask)
Initialize a uint8_t buffer with pathological values within a mask.
#define va_copy(dst, src)
static ALWAYS_INLINE uint64_t gettime_nsec(int is_seed)
uint64_t checkasm_gettime_nsec_diff(uint64_t t)
static unsigned int stdc_leading_zeros_ui(unsigned int value)
#define RANDOMIZE_DIST(buf, ftype, width, mean, stddev)
void checkasm_json_pop(CheckasmJson *json, char type)
Describes a normal (Gaussian) distribution.
Utility functions for checkasm tests.
int checkasm_float_near_ulp_array(const float *const a, const float *const b, const unsigned max_ulp, const int len)
Compare float arrays using ULP tolerance.
#define double_near_abs_eps
int checkasm_float_near_ulp(const float a, const float b, const unsigned max_ulp)
Compare floats using ULP (Units in Last Place) tolerance.
COLD void checkasm_setup_fprintf(void)
static int shift_rand(int x)
void checkasm_randomize_rangef(float *buf, int width, float range)
Fill a float buffer with random values chosen uniformly below a limit.
int checkasm_rand(void)
Generate a random non-negative integer.
static uint32_t xs_state[4]
void checkasm_clear(void *buf, size_t bytes)
Clear a buffer to a pre-determined pattern (currently 0xAA)
#define DEF_CHECKASM_INIT_MASK(BITS, PIXEL)
void checkasm_clear16(uint16_t *buf, int width, uint16_t val)
Fill a uint16_t buffer with a constant value.
int checkasm_double_near_abs_eps(const double a, const double b, const double eps)
Compare doubles using absolute epsilon tolerance.
uint32_t checkasm_rand_uint32(void)
Generate a random 32-bit unsigned integer.
void checkasm_json_str(CheckasmJson *json, const char *key, const char *str)
void checkasm_fprintf(FILE *const f, const int color, const char *const fmt,...)
#define float_near_abs_eps_ulp
double checkasm_rand_dist(CheckasmDist dist)
Generate a normally distributed random number.
char * checkasm_vasprintf(const char *fmt, va_list arg)