FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/utils.c
Date: 2026-08-28 22:32:55
Exec Total Coverage
Lines: 139 300 46.3%
Functions: 36 70 51.4%
Branches: 140 1626 8.6%

Line Branch Exec Source
1 /*
2 * Copyright © 2025, Niklas Haas
3 * Copyright © 2018, VideoLAN and dav1d authors
4 * Copyright © 2018, Two Orioles, LLC
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <assert.h>
30 #include <inttypes.h>
31 #include <limits.h>
32 #include <math.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38
39 #include "checkasm_config.h"
40
41 #ifdef _WIN32
42 #include <windows.h>
43 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
44 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x04
45 #endif
46 #else
47 #if HAVE_ISATTY
48 #include <unistd.h>
49 #endif
50 #if HAVE_IOCTL
51 #include <sys/ioctl.h>
52 #endif
53 #endif
54
55 #if defined(__APPLE__) && defined(__MACH__)
56 #include <mach/mach_time.h>
57 #endif
58
59 #include "checkasm/test.h"
60 #include "checkasm/utils.h"
61 #include "internal.h"
62
63 NOINLINE void checkasm_noop(void *ptr)
64 {
65 (void) ptr;
66 }
67
68 static ALWAYS_INLINE uint64_t gettime_nsec(int is_seed)
69 {
70 #ifdef _WIN32
71 static LARGE_INTEGER freq;
72 LARGE_INTEGER ts;
73 if (!freq.QuadPart) {
74 if (!QueryPerformanceFrequency(&freq))
75 return -1;
76 }
77 if (!QueryPerformanceCounter(&ts))
78 return -1;
79 return UINT64_C(1000000000) * ts.QuadPart / freq.QuadPart;
80 #elif defined(__APPLE__) && defined(__MACH__)
81 static mach_timebase_info_data_t tb_info;
82 if (!tb_info.denom) {
83 if (mach_timebase_info(&tb_info) != KERN_SUCCESS)
84 return -1;
85 }
86 return mach_absolute_time() * tb_info.numer / tb_info.denom;
87 #elif HAVE_CLOCK_GETTIME
88 struct timespec ts;
89 clockid_t id;
90 98 if (!is_seed) {
91 #ifdef CLOCK_MONOTONIC_RAW
92 id = CLOCK_MONOTONIC_RAW;
93 #else
94 id = CLOCK_MONOTONIC;
95 #endif
96 } else {
97 98 id = CLOCK_REALTIME;
98 }
99
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
98 if (clock_gettime(id, &ts) < 0)
100 return -1;
101 98 return UINT64_C(1000000000) * ts.tv_sec + ts.tv_nsec;
102 #else
103 return -1;
104 #endif
105 }
106
107 uint64_t checkasm_gettime_nsec(void)
108 {
109 return gettime_nsec(0);
110 }
111
112 uint64_t checkasm_gettime_nsec_diff(uint64_t t)
113 {
114 return gettime_nsec(0) - t;
115 }
116
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 unsigned checkasm_seed(void)
118 {
119 98 return (unsigned) gettime_nsec(1);
120 }
121
122 // (parallel) xoshiro128++ from https://prng.di.unimi.it/
123 typedef struct CheckasmRand {
124 #define CHECKASM_PRNG_NUM 4
125 uint32_t s0[CHECKASM_PRNG_NUM];
126 uint32_t s1[CHECKASM_PRNG_NUM];
127 uint32_t s2[CHECKASM_PRNG_NUM];
128 uint32_t s3[CHECKASM_PRNG_NUM];
129 } CheckasmRand;
130
131 static CheckasmRand checkasm_prng;
132
133 static ALWAYS_INLINE uint32_t rotl(const uint32_t x, int k)
134 {
135 700810304 return (x << k) | (x >> (32 - k));
136 }
137
138 /* Single round of a parallel xoshiro128++, generates a full block */
139 static ALWAYS_INLINE void xoshiro128pp(CheckasmRand *restrict xs, uint32_t *restrict buf)
140 {
141
2/4
✓ Branch 0 taken 350405152 times.
✓ Branch 1 taken 87601288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
438006440 for (int i = 0; i < CHECKASM_PRNG_NUM; i++) {
142 350405152 buf[i] = rotl(xs->s0[i] + xs->s3[i], 7) + xs->s0[i];
143
144 350405152 const uint32_t t = xs->s1[i] << 9;
145 350405152 xs->s2[i] ^= xs->s0[i];
146 350405152 xs->s3[i] ^= xs->s1[i];
147 350405152 xs->s1[i] ^= xs->s2[i];
148 350405152 xs->s0[i] ^= xs->s3[i];
149 350405152 xs->s2[i] ^= t;
150 700810304 xs->s3[i] = rotl(xs->s3[i], 11);
151 }
152 87601288 }
153
154 21900331 static void prng(CheckasmRand *restrict xs, uint8_t *restrict buf, size_t size)
155 {
156 uint32_t tmp[CHECKASM_PRNG_NUM];
157 21900331 const size_t block_size = sizeof(tmp);
158 21900331 CheckasmRand xs_copy = *xs;
159
160
2/2
✓ Branch 0 taken 87601288 times.
✓ Branch 1 taken 21900331 times.
109501619 while (size >= block_size) {
161 xoshiro128pp(&xs_copy, tmp);
162 87601288 memcpy(buf, tmp, block_size);
163 87601288 buf += block_size;
164 87601288 size -= block_size;
165 }
166
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21900331 times.
21900331 if (size) {
168 xoshiro128pp(&xs_copy, tmp);
169 memcpy(buf, tmp, size);
170 }
171
172 21900331 *xs = xs_copy;
173 21900331 }
174
175 /* Efficient wrapper for generating individual random integers, by caching
176 * the result of a single call to the underlying generator() */
177 static struct {
178 #define PRNG_CACHE_SIZE 64
179 uint8_t buf8 [PRNG_CACHE_SIZE];
180 uint16_t buf16[PRNG_CACHE_SIZE >> 1];
181 uint32_t buf32[PRNG_CACHE_SIZE >> 2];
182 uint64_t buf64[PRNG_CACHE_SIZE >> 3];
183 int num8;
184 int num16;
185 int num32;
186 int num64;
187 } prng_cache;
188
189 static_assert(PRNG_CACHE_SIZE % sizeof(uint32_t[CHECKASM_PRNG_NUM]) == 0,
190 "PRNG_CACHE_SIZE should be a multiple of uint32_t[CHECKASM_PRNG_NUM]");
191
192 #define DEF_CHECKASM_RAND(BITS, TYPE, NAME) \
193 TYPE checkasm_rand_##NAME(void) \
194 { \
195 if (!prng_cache.num##BITS) { \
196 prng(&checkasm_prng, (uint8_t *) prng_cache.buf##BITS, \
197 sizeof(prng_cache.buf##BITS)); \
198 prng_cache.num##BITS = ARRAY_SIZE(prng_cache.buf##BITS); \
199 } \
200 \
201 union { \
202 TYPE type; \
203 uint##BITS##_t raw; \
204 } val; \
205 val.raw = prng_cache.buf##BITS[--prng_cache.num##BITS]; \
206 return val.type; \
207 }
208
209 DEF_CHECKASM_RAND(8, int8_t, int8)
210
2/2
✓ Branch 0 taken 5519351 times.
✓ Branch 1 taken 347718459 times.
353237810 DEF_CHECKASM_RAND(8, uint8_t, uint8)
211 DEF_CHECKASM_RAND(16, int16_t, int16)
212 DEF_CHECKASM_RAND(16, uint16_t, uint16)
213 DEF_CHECKASM_RAND(32, int32_t, int32)
214
2/2
✓ Branch 0 taken 16380962 times.
✓ Branch 1 taken 245468355 times.
261849317 DEF_CHECKASM_RAND(32, uint32_t, uint32)
215 DEF_CHECKASM_RAND(32, float, float32)
216 DEF_CHECKASM_RAND(64, int64_t, int64)
217 DEF_CHECKASM_RAND(64, uint64_t, uint64)
218 DEF_CHECKASM_RAND(64, double, float64)
219
220 240888 static inline uint64_t splitmix64(uint64_t *state)
221 {
222 240888 uint64_t z = (*state += 0x9e3779b97f4a7c15);
223
224 240888 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
225 240888 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
226 240888 return z ^ (z >> 31);
227 }
228
229 30111 void checkasm_srand(unsigned seed)
230 {
231 /* Seed using splitmix64() as recommended by xoroshiro128 authors */
232 30111 uint64_t s = seed;
233
234
2/2
✓ Branch 0 taken 120444 times.
✓ Branch 1 taken 30111 times.
150555 for (int i = 0; i < CHECKASM_PRNG_NUM; i++) {
235 120444 const uint64_t a = splitmix64(&s);
236 120444 const uint64_t b = splitmix64(&s);
237
238 120444 checkasm_prng.s0[i] = (uint32_t) a;
239 120444 checkasm_prng.s1[i] = (uint32_t) b;
240 120444 checkasm_prng.s2[i] = a >> 32;
241 120444 checkasm_prng.s3[i] = b >> 32;
242 }
243
244 /* discard cached random bytes */
245 30111 prng_cache.num8 = prng_cache.num16 = prng_cache.num32 = prng_cache.num64 = 0;
246 30111 }
247
248 2908 int checkasm_rand(void)
249 {
250 static_assert(sizeof(int) <= sizeof(uint32_t), "int larger than 32 bits");
251 2908 return checkasm_rand_uint32() & INT_MAX;
252 }
253
254 double checkasm_randf(void)
255 {
256 return checkasm_rand_uint32() / (UINT32_MAX + 1.0);
257 }
258
259 /* Marsaglia polar method */
260 40504 static inline double marsaglia(double *z2)
261 {
262 double u1, u2, w;
263 do {
264 51042 u1 = 2.0 / UINT32_MAX * checkasm_rand_uint32() - 1.0;
265 51042 u2 = 2.0 / UINT32_MAX * checkasm_rand_uint32() - 1.0;
266 51042 w = u1 * u1 + u2 * u2;
267
2/2
✓ Branch 0 taken 10538 times.
✓ Branch 1 taken 40504 times.
51042 } while (w >= 1.0);
268
269 40504 w = sqrt((-2.0 * log(w)) / w);
270 40504 *z2 = u2 * w;
271 40504 return u1 * w;
272 }
273
274 double checkasm_rand_norm(void)
275 {
276 static int cached;
277 static double cache;
278 if ((cached = !cached)) {
279 return marsaglia(&cache);
280 } else {
281 return cache;
282 }
283 }
284
285 double checkasm_rand_dist(CheckasmDist dist)
286 {
287 return dist.mean + dist.stddev * checkasm_rand_norm();
288 }
289
290 18 void checkasm_randomize(void *buf, size_t bytes)
291 {
292 18 prng(&checkasm_prng, buf, bytes);
293 18 }
294
295 void checkasm_randomize_mask8(uint8_t *buf, int width, uint8_t mask)
296 {
297 prng(&checkasm_prng, (uint8_t *) buf, width * sizeof(*buf));
298 for (int i = 0; i < width; i++)
299 buf[i] &= mask;
300 }
301
302 void checkasm_randomize_mask16(uint16_t *buf, int width, uint16_t mask)
303 {
304 prng(&checkasm_prng, (uint8_t *) buf, width * sizeof(*buf));
305 for (int i = 0; i < width; i++)
306 buf[i] &= mask;
307 }
308
309 void checkasm_randomize_range(double *buf, int width, double range)
310 {
311 const double scale = range / (UINT32_MAX + 1.0);
312 while (width--)
313 *buf++ = scale * checkasm_rand_uint32();
314 }
315
316 void checkasm_randomize_rangef(float *buf, int width, float range)
317 {
318 const float scale = (float) (range / (UINT32_MAX + 1.0));
319 while (width--)
320 *buf++ = scale * checkasm_rand_uint32();
321 }
322
323 void checkasm_randomize_interval(double *buf, int width, double low, double high)
324 {
325 const double scale = (high - low) / (double) UINT32_MAX;
326 while (width--)
327 *buf++ = scale * checkasm_rand_uint32() + low;
328 }
329
330 void checkasm_randomize_intervalf(float *buf, int width, float low, float high)
331 {
332 const float scale = (high - low) / (float) UINT32_MAX;
333 while (width--)
334 *buf++ = scale * checkasm_rand_uint32() + low;
335 }
336
337 #define RANDOMIZE_DIST(buf, ftype, width, mean, stddev) \
338 do { \
339 if ((width) & 1) { \
340 *(buf)++ = (ftype) ((mean) + (stddev) * checkasm_rand_norm()); \
341 (width) ^= 1; \
342 } \
343 \
344 for (; width; width -= 2) { \
345 double z1, z2; \
346 z1 = marsaglia(&z2); \
347 *(buf)++ = (ftype) ((mean) + (stddev) * z1); \
348 *(buf)++ = (ftype) ((mean) + (stddev) * z2); \
349 } \
350 } while (0)
351
352 168 void checkasm_randomize_dist(double *buf, int width, CheckasmDist dist)
353 {
354
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✓ Branch 4 taken 17808 times.
✓ Branch 5 taken 168 times.
17976 RANDOMIZE_DIST(buf, double, width, dist.mean, dist.stddev);
355 168 }
356
357 130 void checkasm_randomize_distf(float *buf, int width, CheckasmDist dist)
358 {
359
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
✓ Branch 4 taken 22696 times.
✓ Branch 5 taken 130 times.
22826 RANDOMIZE_DIST(buf, float, width, dist.mean, dist.stddev);
360 130 }
361
362 void checkasm_randomize_norm(double *buf, int width)
363 {
364 RANDOMIZE_DIST(buf, double, width, 0.0, 1.0);
365 }
366
367 void checkasm_randomize_normf(float *buf, int width)
368 {
369 RANDOMIZE_DIST(buf, float, width, 0.0, 1.0);
370 }
371
372 28156 void checkasm_clear(void *buf, size_t bytes)
373 {
374 28156 memset(buf, 0xAA, bytes);
375 28156 }
376
377 void checkasm_clear8(uint8_t *buf, int width, uint8_t val)
378 {
379 memset(buf, val, width);
380 }
381
382 void checkasm_clear16(uint16_t *buf, int width, uint16_t val)
383 {
384 while (width--)
385 *buf++ = val;
386 }
387
388 #if HAVE_STDBIT_H
389 #include <stdbit.h>
390
391 static inline int clz(const unsigned int mask)
392 {
393 return stdc_leading_zeros_ui(mask);
394 }
395
396 #elif defined(_MSC_VER) && !defined(__clang__)
397 #include <intrin.h>
398
399 static inline int clz(const unsigned int mask)
400 {
401 unsigned long leading_zero = 0;
402 _BitScanReverse(&leading_zero, mask);
403 return (31 - leading_zero);
404 }
405
406 #else /* !_MSC_VER */
407 2908 static inline int clz(const unsigned int mask)
408 {
409 2908 return __builtin_clz(mask);
410 }
411 #endif /* !_MSC_VER */
412
413 /* Randomly downshift an integer */
414 2908 static int shift_rand(int x)
415 {
416 2908 const int bits = 8 * sizeof(x) - clz(x);
417
1/2
✓ Branch 0 taken 2908 times.
✗ Branch 1 not taken.
2908 return x ? (x >> (checkasm_rand() % bits)) : 0;
418 }
419
420 enum {
421 PAT_ZERO, // all zero
422 PAT_ONE, // all one
423 PAT_RAND, // random data
424 PAT_LOW, // all low
425 PAT_HIGH, // all high
426 PAT_ALTLO, // alternating low and high
427 PAT_ALTHI, // alternating high and low
428 PAT_MIX, // random mix of low and high
429 };
430
431 112 void checkasm_init(void *buf, size_t bytes)
432 {
433 112 checkasm_init_mask8(buf, (int) bytes, 0xFF);
434 112 }
435
436 #define DEF_CHECKASM_INIT_MASK(BITS, PIXEL) \
437 void checkasm_init_mask##BITS(PIXEL *buf, const int width, const PIXEL mask_pixel) \
438 { \
439 if (!width) \
440 return; \
441 \
442 int step = 0, mode = 0, mask = mask_pixel; \
443 for (int i = 0; i < width; i++, step--) { \
444 if (!step) { \
445 step = imax(shift_rand(width), 1); \
446 mode = checkasm_rand_uint8() & 7; \
447 mask = shift_rand(mask_pixel); \
448 } \
449 \
450 const PIXEL low = checkasm_rand_uint##BITS() & mask; \
451 const PIXEL high = mask_pixel - low; \
452 switch (mode) { \
453 case PAT_ZERO: buf[i] = 0; break; \
454 case PAT_ONE: buf[i] = mask_pixel; break; \
455 case PAT_RAND: buf[i] = checkasm_rand_uint##BITS() & mask_pixel; break; \
456 case PAT_LOW: buf[i] = low; break; \
457 case PAT_HIGH: buf[i] = high; break; \
458 case PAT_ALTLO: buf[i] = (i & 1) ? high : low; break; \
459 case PAT_ALTHI: buf[i] = (i & 1) ? low : high; break; \
460 case PAT_MIX: buf[i] = (checkasm_rand_uint8() & 1) ? low : high; break; \
461 } \
462 } \
463 }
464
465
19/21
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 1454 times.
✓ Branch 3 taken 274021162 times.
✓ Branch 9 taken 55692785 times.
✓ Branch 10 taken 29141024 times.
✓ Branch 11 taken 5187066 times.
✓ Branch 12 taken 10728821 times.
✓ Branch 13 taken 36196542 times.
✓ Branch 14 taken 11574319 times.
✓ Branch 15 taken 51475385 times.
✓ Branch 16 taken 74026674 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 5787153 times.
✓ Branch 20 taken 5787166 times.
✓ Branch 21 taken 25737692 times.
✓ Branch 22 taken 25737693 times.
✓ Branch 24 taken 37004467 times.
✓ Branch 25 taken 37022207 times.
✓ Branch 26 taken 274022616 times.
✓ Branch 27 taken 112 times.
274022728 DEF_CHECKASM_INIT_MASK(8, uint8_t)
466 DEF_CHECKASM_INIT_MASK(16, uint16_t)
467
468 static int use_printf_color[2];
469 static char statusline[256];
470 static int statusline_visible;
471
472 /* Print colored text to stderr if the terminal supports it */
473 2882 int checkasm_vfprintf(FILE *const f, const int color, const char *const fmt, va_list arg)
474 {
475 2882 size_t fmt_len = strlen(fmt);
476 2882 int use_color = use_printf_color[f == stderr];
477
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2882 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2882 if (!use_color || !fmt_len)
478 2882 return vfprintf(f, fmt, arg);
479
480 if (f == stderr && statusline_visible) {
481 fprintf(f, "\r\033[K"); /* clear line */
482 statusline_visible = 0;
483 }
484
485 if (color >= 0)
486 fprintf(f, "\x1b[0;%dm", color);
487
488 int ret = vfprintf(f, fmt, arg);
489
490 if (color >= 0)
491 fprintf(f, "\x1b[0m");
492
493 if (f == stderr && statusline[0] && fmt[fmt_len - 1] == '\n') {
494 fprintf(f, "%s", statusline);
495 statusline_visible = 1;
496 }
497
498 return ret;
499 }
500
501 30209 void checkasm_statusline(const char *status)
502 {
503
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 30111 times.
30209 if (!status)
504 98 status = "";
505
506
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 30209 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
30209 if (!use_printf_color[1] || !strcmp(statusline, status))
507 30209 return; /* don't re-paint unchanged status */
508
509 snprintf(statusline, sizeof(statusline), "%s", status);
510
511 if (statusline_visible) {
512 fprintf(stderr, "\r\033[K");
513 statusline_visible = 0;
514 }
515
516 if (statusline[0]) {
517 fprintf(stderr, "%s", statusline);
518 statusline_visible = 1;
519 }
520 }
521
522 196 static COLD int should_use_color(FILE *const f)
523 {
524 #ifdef _WIN32
525 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
526 HANDLE con = GetStdHandle(f == stderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
527 DWORD con_mode = 0;
528 return con && con != INVALID_HANDLE_VALUE && GetConsoleMode(con, &con_mode)
529 && SetConsoleMode(con, con_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
530 #else
531 return 0;
532 #endif
533 #elif HAVE_ISATTY
534
3/4
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 196 times.
196 if (isatty(f == stderr ? 2 : 1)) {
535 const char *const term = getenv("TERM");
536 return term && strcmp(term, "dumb");
537 }
538 196 return 0;
539 #else
540 return 0;
541 #endif
542 }
543
544 98 COLD void checkasm_setup_fprintf(void)
545 {
546 98 use_printf_color[0] = should_use_color(stdout);
547 98 use_printf_color[1] = should_use_color(stderr);
548 98 }
549
550 25453 static int get_terminal_width(void)
551 {
552 #ifdef _WIN32
553 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
554 CONSOLE_SCREEN_BUFFER_INFO csbi;
555 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
556 return csbi.srWindow.Right - csbi.srWindow.Left + 1;
557 #endif
558 #elif defined(__OS2__)
559 int dst[2];
560 _scrsize(dst);
561 return dst[0];
562 #elif HAVE_IOCTL && defined(TIOCGWINSZ)
563 struct winsize w;
564
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25453 times.
25453 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
565 return w.ws_col;
566 #endif
567 25453 return 80;
568 }
569
570 void checkasm_json(CheckasmJson *json, const char *key, const char *const fmt, ...)
571 {
572 assert(json->level > 0);
573 fputs(json->nonempty ? ",\n" : "\n", json->file);
574 for (int i = 0; i < json->level; i++)
575 fputc(' ', json->file);
576
577 va_list ap;
578 va_start(ap, fmt);
579 if (key)
580 fprintf(json->file, "\"%s\": ", key);
581 vfprintf(json->file, fmt, ap);
582 va_end(ap);
583 json->nonempty = 1;
584 }
585
586 void checkasm_json_str(CheckasmJson *json, const char *key, const char *str)
587 {
588 assert(json->level > 0);
589 fputs(json->nonempty ? ",\n" : "\n", json->file);
590 for (int i = 0; i < json->level; i++)
591 fputc(' ', json->file);
592
593 if (key)
594 fprintf(json->file, "\"%s\": \"", key);
595 else
596 fputc('"', json->file);
597
598 while (*str) {
599 switch (*str) {
600 case '\\': fputs("\\\\", json->file); break;
601 case '"': fputs("\\\"", json->file); break;
602 case '\n': fputs("\\n", json->file); break;
603 default: fputc(*str, json->file); break;
604 }
605 str++;
606 }
607 fputc('"', json->file);
608 json->nonempty = 1;
609 }
610
611 void checkasm_json_push(CheckasmJson *json, const char *const key, const char type)
612 {
613 fputs(json->nonempty ? ",\n" : "\n", json->file);
614 for (int i = 0; i < json->level; i++)
615 fputc(' ', json->file);
616
617 if (key) {
618 fprintf(json->file, "\"%s\": %c", key, type);
619 } else {
620 fputc(type, json->file);
621 }
622
623 json->level += 2;
624 json->nonempty = 0;
625 }
626
627 void checkasm_json_pop(CheckasmJson *json, char type)
628 {
629 assert(json->level >= 2);
630 json->level -= 2;
631 if (json->nonempty) {
632 fputc('\n', json->file);
633 for (int i = 0; i < json->level; i++)
634 fputc(' ', json->file);
635 }
636 fputc(type, json->file);
637 json->nonempty = 1;
638 }
639
640 /* float compare support code */
641 typedef union {
642 float f;
643 uint32_t i;
644 } intfloat;
645
646 4343816 static int is_negative(const intfloat u)
647 {
648 4343816 return u.i >> 31;
649 }
650
651 2171908 int checkasm_float_near_ulp(const float a, const float b, const unsigned max_ulp)
652 {
653 intfloat x, y;
654
655 2171908 x.f = a;
656 2171908 y.f = b;
657
658
2/2
✓ Branch 2 taken 1177 times.
✓ Branch 3 taken 2170731 times.
2171908 if (is_negative(x) != is_negative(y)) {
659 // handle -0.0 == +0.0
660 1177 return a == b;
661 }
662
663
2/2
✓ Branch 0 taken 2170726 times.
✓ Branch 1 taken 5 times.
2170731 if (llabs((int64_t) x.i - y.i) <= max_ulp)
664 2170726 return 1;
665
666 5 return 0;
667 }
668
669 100195 int checkasm_float_near_ulp_array(const float *const a, const float *const b,
670 const unsigned max_ulp, const int len)
671 {
672
2/2
✓ Branch 0 taken 2166788 times.
✓ Branch 1 taken 100195 times.
2266983 for (int i = 0; i < len; i++)
673
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2166788 times.
2166788 if (!float_near_ulp(a[i], b[i], max_ulp))
674 return 0;
675
676 100195 return 1;
677 }
678
679 876626 int checkasm_float_near_abs_eps(const float a, const float b, const float eps)
680 {
681 876626 return fabsf(a - b) < eps;
682 }
683
684 197 int checkasm_float_near_abs_eps_array(const float *const a, const float *const b,
685 const float eps, const int len)
686 {
687
2/2
✓ Branch 0 taken 866626 times.
✓ Branch 1 taken 197 times.
866823 for (int i = 0; i < len; i++)
688
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 866626 times.
866626 if (!float_near_abs_eps(a[i], b[i], eps))
689 return 0;
690
691 197 return 1;
692 }
693
694 5120 int checkasm_float_near_abs_eps_ulp(const float a, const float b, const float eps,
695 const unsigned max_ulp)
696 {
697
3/4
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5115 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5120 return float_near_ulp(a, b, max_ulp) || float_near_abs_eps(a, b, eps);
698 }
699
700 int checkasm_float_near_abs_eps_array_ulp(const float *const a, const float *const b,
701 const float eps, const unsigned max_ulp,
702 const int len)
703 {
704 for (int i = 0; i < len; i++)
705 if (!float_near_abs_eps_ulp(a[i], b[i], eps, max_ulp))
706 return 0;
707
708 return 1;
709 }
710
711 70879 int checkasm_double_near_abs_eps(const double a, const double b, const double eps)
712 {
713 70879 return fabs(a - b) < eps;
714 }
715
716 11 int checkasm_double_near_abs_eps_array(const double *const a, const double *const b,
717 const double eps, const unsigned len)
718 {
719
2/2
✓ Branch 0 taken 41068 times.
✓ Branch 1 taken 11 times.
41079 for (unsigned i = 0; i < len; i++)
720
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 41068 times.
41068 if (!double_near_abs_eps(a[i], b[i], eps))
721 return 0;
722
723 11 return 1;
724 }
725
726 static int check_err(const char *const file, const int line, const char *const name,
727 const int w, const int h, int *const err)
728 {
729 if (*err)
730 return 0;
731 if (!checkasm_fail_func("%s:%d", file, line))
732 return 1;
733 *err = 1;
734 fprintf(stderr, "%s (%dx%d):\n", name, w, h);
735 return 0;
736 }
737
738 #define PRINT_LINE(buf1, buf2, xstart, xend, xpad, fmt, fmtw) \
739 do { \
740 for (int x = xstart; x < xend; x++) { \
741 if (buf1[x] != buf2[x]) \
742 checkasm_fprintf(stderr, COLOR_RED, " " fmt, buf1[x]); \
743 else \
744 fprintf(stderr, " " fmt, buf1[x]); \
745 } \
746 for (int pad = xend; pad < xstart + xpad; pad++) \
747 fprintf(stderr, &" "[9 - fmtw]); \
748 } while (0)
749
750 #define PRINT_RECT(type, buf1, buf2, ystart, yend, xstart, xend, fmt, fmtw) \
751 do { \
752 const type *ptr1 = (buf1) + ystart * stride1; \
753 const type *ptr2 = (buf2) + ystart * stride1; \
754 const int elem_size = 2 * (fmtw + 1) + 1; \
755 const int display_elems = imin(term_width / elem_size, xend - xstart); \
756 for (int y = ystart; y < yend; y++) { \
757 for (int xpos = xstart; xpos < xend; xpos += display_elems) { \
758 const int xstep = imin(xpos + display_elems, xend); \
759 if (xpos == xstart) /* line change */ \
760 checkasm_fprintf(stderr, COLOR_BLUE, "%3d: ", y); \
761 else \
762 fprintf(stderr, " "); \
763 PRINT_LINE(ptr1, ptr2, xpos, xstep, display_elems, fmt, fmtw); \
764 fprintf(stderr, " "); \
765 PRINT_LINE(ptr2, ptr1, xpos, xstep, display_elems, fmt, fmtw); \
766 fprintf(stderr, " "); \
767 for (int x = xpos; x < xstep; x++) { \
768 if (ptr1[x] != ptr2[x]) \
769 checkasm_fprintf(stderr, COLOR_RED, "x"); \
770 else \
771 fprintf(stderr, "."); \
772 } \
773 fprintf(stderr, "\n"); \
774 } \
775 ptr1 += stride1; \
776 ptr2 += stride2; \
777 } \
778 } while (0)
779
780 #define CHECK_RECT(buf1, buf2, ystart, yend, xstart, xend, msg, compare, type, fmt, \
781 fmtw) \
782 do { \
783 const int xw = xend - xstart; \
784 for (int y = ystart; y < yend; y++) { \
785 if (compare(&buf1[y * stride1 + xstart], &buf2[y * stride2 + xstart], xw)) \
786 continue; \
787 if (check_err(file, line, name, w, h, &err)) \
788 return 1; \
789 /* Exclude unneeded lines on overwrite above */ \
790 int yprint = y < 0 ? y : ystart; \
791 if (msg[0]) \
792 fprintf(stderr, " %s (%dx%d, from idx [%d]):\n", msg, xend - xstart, \
793 yend - yprint, xstart); \
794 PRINT_RECT(type, buf1, buf2, yprint, yend, xstart, xend, fmt, fmtw); \
795 break; \
796 } \
797 } while (0)
798
799 #define DEF_CHECKASM_CHECK_BODY(compare, type, fmt, fmtw) \
800 do { \
801 const int overhead = 5 + 3 + 3; \
802 const int term_width = get_terminal_width() - overhead; \
803 const int aligned_w = (w + align_w - 1) & ~(align_w - 1); \
804 stride1 /= sizeof(type); \
805 stride2 /= sizeof(type); \
806 \
807 int err = 0; \
808 CHECK_RECT(buf1, buf2, 0, h, 0, w, "", compare, type, fmt, fmtw); \
809 if (align_h >= 1) { \
810 const int aligned_h = (h + align_h - 1) & ~(align_h - 1); \
811 CHECK_RECT(buf1, buf2, -padding, 0, -padding, w + padding, "overwrite top", \
812 compare, type, fmt, fmtw); \
813 CHECK_RECT(buf1, buf2, aligned_h, aligned_h + padding, -padding, \
814 w + padding, "overwrite bottom", compare, type, fmt, fmtw); \
815 } \
816 CHECK_RECT(buf1, buf2, 0, h, -padding, 0, "overwrite left", compare, type, fmt, \
817 fmtw); \
818 CHECK_RECT(buf1, buf2, 0, h, aligned_w, aligned_w + padding, "overwrite right", \
819 compare, type, fmt, fmtw); \
820 return err; \
821 } while (0)
822
823 #define cmp_int(a, b, len) (!memcmp(a, b, (len) * sizeof(*(a))))
824 #define DEF_CHECKASM_CHECK_FUNC(type, fmt, fmtw) \
825 int checkasm_check_impl_##type(const char *file, int line, const type *buf1, \
826 ptrdiff_t stride1, const type *buf2, \
827 ptrdiff_t stride2, int w, int h, const char *name, \
828 int align_w, int align_h, int padding) \
829 { \
830 DEF_CHECKASM_CHECK_BODY(cmp_int, type, fmt, fmtw); \
831 }
832
833 DEF_CHECKASM_CHECK_FUNC(int, "%9d", 9)
834 DEF_CHECKASM_CHECK_FUNC(int8_t, "%4" PRId8, 4)
835
10/156
✓ Branch 1 taken 14114 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 14114 times.
✓ Branch 47 taken 550 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 550 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✓ Branch 148 taken 14114 times.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✓ Branch 193 taken 14114 times.
✓ Branch 194 taken 550 times.
✓ Branch 195 taken 14114 times.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 219 not taken.
✗ Branch 220 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✓ Branch 240 taken 14114 times.
✓ Branch 241 taken 550 times.
42892 DEF_CHECKASM_CHECK_FUNC(int16_t, "%6" PRId16, 6)
836
10/156
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 64 times.
✓ Branch 47 taken 4 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 4 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✓ Branch 148 taken 64 times.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✓ Branch 193 taken 64 times.
✓ Branch 194 taken 4 times.
✓ Branch 195 taken 64 times.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 219 not taken.
✗ Branch 220 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✓ Branch 240 taken 64 times.
✓ Branch 241 taken 4 times.
196 DEF_CHECKASM_CHECK_FUNC(int32_t, "%9" PRId32, 9)
837
838 DEF_CHECKASM_CHECK_FUNC(unsigned, "%08x", 8)
839
17/156
✓ Branch 1 taken 215284 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 215284 times.
✓ Branch 47 taken 7146 times.
✓ Branch 48 taken 3704 times.
✓ Branch 49 taken 3442 times.
✓ Branch 50 taken 29632 times.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✓ Branch 97 taken 29632 times.
✓ Branch 98 taken 3704 times.
✓ Branch 99 taken 29632 times.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✓ Branch 146 taken 29632 times.
✓ Branch 147 taken 3704 times.
✓ Branch 148 taken 215284 times.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✓ Branch 193 taken 215284 times.
✓ Branch 194 taken 7146 times.
✓ Branch 195 taken 215284 times.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 219 not taken.
✗ Branch 220 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✓ Branch 240 taken 215284 times.
✓ Branch 241 taken 7146 times.
712262 DEF_CHECKASM_CHECK_FUNC(uint8_t, "%02" PRIx8, 2)
840
17/156
✓ Branch 1 taken 478824 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 478824 times.
✓ Branch 47 taken 15220 times.
✓ Branch 48 taken 10374 times.
✓ Branch 49 taken 4846 times.
✓ Branch 50 taken 82992 times.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✓ Branch 97 taken 82992 times.
✓ Branch 98 taken 10374 times.
✓ Branch 99 taken 82992 times.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✓ Branch 146 taken 82992 times.
✓ Branch 147 taken 10374 times.
✓ Branch 148 taken 478824 times.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✓ Branch 193 taken 478824 times.
✓ Branch 194 taken 15220 times.
✓ Branch 195 taken 478824 times.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 219 not taken.
✗ Branch 220 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✓ Branch 240 taken 478824 times.
✓ Branch 241 taken 15220 times.
1617676 DEF_CHECKASM_CHECK_FUNC(uint16_t, "%04" PRIx16, 4)
841
10/156
✓ Branch 1 taken 7216 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 7216 times.
✓ Branch 47 taken 451 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 451 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✓ Branch 148 taken 7216 times.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✓ Branch 193 taken 7216 times.
✓ Branch 194 taken 451 times.
✓ Branch 195 taken 7216 times.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 219 not taken.
✗ Branch 220 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✓ Branch 240 taken 7216 times.
✓ Branch 241 taken 451 times.
22099 DEF_CHECKASM_CHECK_FUNC(uint32_t, "%08" PRIx32, 8)
842
843 2082 int checkasm_check_impl_float_ulp(const char *file, int line, const float *buf1,
844 ptrdiff_t stride1, const float *buf2, ptrdiff_t stride2,
845 int w, int h, const char *name, unsigned max_ulp,
846 int align_w, int align_h, int padding)
847 {
848 #define cmp_float(a, b, len) float_near_ulp_array(a, b, max_ulp, len)
849
10/156
✓ Branch 2 taken 33312 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 33312 times.
✓ Branch 48 taken 2082 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 2082 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✓ Branch 152 taken 33312 times.
✗ Branch 153 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✓ Branch 197 taken 33312 times.
✓ Branch 198 taken 2082 times.
✓ Branch 200 taken 33312 times.
✗ Branch 201 not taken.
✗ Branch 203 not taken.
✗ Branch 204 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 210 not taken.
✗ Branch 211 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✗ Branch 218 not taken.
✗ Branch 219 not taken.
✗ Branch 221 not taken.
✗ Branch 222 not taken.
✗ Branch 224 not taken.
✗ Branch 225 not taken.
✗ Branch 228 not taken.
✗ Branch 229 not taken.
✗ Branch 231 not taken.
✗ Branch 232 not taken.
✗ Branch 234 not taken.
✗ Branch 235 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 243 not taken.
✗ Branch 244 not taken.
✓ Branch 245 taken 33312 times.
✓ Branch 246 taken 2082 times.
102018 DEF_CHECKASM_CHECK_BODY(cmp_float, float, "%7g", 7);
850 #undef cmp_float
851 }
852
853 1205 char *checkasm_vasprintf(const char *fmt, va_list arg)
854 {
855 va_list arg2;
856 1205 va_copy(arg2, arg);
857 1205 int len = vsnprintf(NULL, 0, fmt, arg2);
858 1205 va_end(arg2);
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1205 times.
1205 if (len < 0)
860 return NULL;
861
862 1205 char *buf = checkasm_mallocz(len + 1);
863 1205 vsnprintf(buf, len + 1, fmt, arg);
864 1205 return buf;
865 }
866