FFmpeg
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
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/**
30 * @file utils.h
31 * @brief Utility functions for checkasm tests
32 *
33 * This header provides utility functions commonly needed when writing checkasm
34 * tests, including:
35 * - Random number generation (uniform and normal distributions)
36 * - Memory initialization and randomization
37 * - Floating-point comparison utilities
38 * - Buffer definition and checking helpers
39 */
40
41#ifndef CHECKASM_UTILS_H
42#define CHECKASM_UTILS_H
43
44#include <stdint.h>
45
46#include "checkasm/attributes.h"
47
48/**
49 * @defgroup rng Random Number Generation
50 * @brief Functions for generating uniformly distributed random numbers
51 *
52 * These functions use the seed specified in CheckasmConfig (or a time-based
53 * seed if not specified) to generate deterministic, reproducible random values.
54 *
55 * @note The PRNG state is automatically re-seeded at the start of each test
56 * case (i.e. before each call to CheckasmTest.func), so that different CPU
57 * flags see the same sequence of random numbers, at least until control flow
58 * inside the test function diverges.
59 *
60 * @{
61 */
62
63/**
64 * @brief Generate a random non-negative integer
65 * @return Random value in range [0, INT_MAX]
66 */
68
69/**
70 * @brief Generate a random double-precision floating-point number
71 * @return Random value in range [0.0, 1.0)
72 */
73CHECKASM_API double checkasm_randf(void);
74
75/**
76 * @brief Generate a random 8-bit unsigned integer
77 * @return Random value in range [0, UINT8_MAX]
78 */
80
81/**
82 * @brief Generate a random 16-bit unsigned integer
83 * @return Random value in range [0, UINT16_MAX]
84 */
86
87/**
88 * @brief Generate a random 32-bit unsigned integer
89 * @return Random value in range [0, UINT32_MAX]
90 */
92
93/**
94 * @brief Generate a random 64-bit unsigned integer
95 * @return Random value in range [0, UINT64_MAX]
96 */
98
99/**
100 * @brief Generate a random 8-bit signed integer
101 * @return Random value in range [INT8_MIN, INT8_MAX]
102 */
104
105/**
106 * @brief Generate a random 16-bit signed integer
107 * @return Random value in range [INT16_MIN, INT16_MAX]
108 */
110
111/**
112 * @brief Generate a random 32-bit signed integer
113 * @return Random value in range [INT32_MIN, INT32_MAX]
114 */
116
117/**
118 * @brief Generate a random 64-bit signed integer
119 * @return Random value in range [INT64_MIN, INT64_MAX]
120 */
122
123/**
124 * @brief Generate a truly random 32-bit float.
125 * @return Random float value, drawn from the space of all possible float
126 * representations, including every possible NaN, Infinity etc.
127 * @see checkasm_randf(), checkasm_rand_norm(), checkasm_rand_dist()
128 */
130
131/**
132 * @brief Generate a truly random 64-bit float.
133 * @return Random float value, drawn from the space of all possible float
134 * representations, including every possible NaN, Infinity etc.
135 * @see checkasm_randf(), checkasm_rand_norm(), checkasm_rand_dist()
136 */
138
139/** @} */ /* rng */
140
141/**
142 * @brief Describes a normal (Gaussian) distribution
143 *
144 * Structure specifying the parameters of a normal distribution for use
145 * with random number generation functions.
146 */
147typedef struct CheckasmDist {
148 double mean; /**< Mean (center) of the distribution */
149 double stddev; /**< Standard deviation (spread) of the distribution */
151
152/**
153 * @def checkasm_dist_standard
154 * @brief Standard normal distribution (mean=0, stddev=1)
155 */
156#define checkasm_dist_standard ((CheckasmDist) { 0.0, 1.0 })
157
158/**
159 * @brief Generate a normally distributed random number
160 * @param[in] dist Distribution parameters (mean and standard deviation)
161 * @return Random value from the specified normal distribution
162 */
164
165/**
166 * @brief Generate a random number from the standard normal distribution
167 * @return Random value from N(0,1) distribution
168 * @see checkasm_dist_standard
169 */
171
172/**
173 * @defgroup memory Memory Initialization
174 * @brief Functions for filling buffers with various patterns of data
175 *
176 * A collection of functions to initialize memory buffers with random data,
177 * constant values, or pathological test patterns. These are useful for setting
178 * up input/output data buffers for checkasm tests.
179 * @{
180 */
181
182/**
183 * @brief Fill a buffer with uniformly chosen random bytes
184 * @param[out] buf Buffer to fill
185 * @param[in] bytes Number of bytes to randomize
186 */
187CHECKASM_API void checkasm_randomize(void *buf, size_t bytes);
188
189/**
190 * @brief Fill a uint8_t buffer with random values chosen uniformly within a mask
191 * @param[out] buf Buffer to fill
192 * @param[in] width Number of elements to randomize
193 * @param[in] mask Bit mask to apply to each random value
194 */
195CHECKASM_API void checkasm_randomize_mask8(uint8_t *buf, int width, uint8_t mask);
196
197/**
198 * @brief Fill a uint16_t buffer with random values chosen uniformly within a mask
199 * @param[out] buf Buffer to fill
200 * @param[in] width Number of elements to randomize
201 * @param[in] mask Bit mask to apply to each random value
202 */
203CHECKASM_API void checkasm_randomize_mask16(uint16_t *buf, int width, uint16_t mask);
204
205/**
206 * @brief Fill a double buffer with random values chosen uniformly below a limit
207 * @param[out] buf Buffer to fill
208 * @param[in] width Number of elements to randomize
209 * @param[in] range Exclusive upper bound on value (range is [0, range))
210 */
211CHECKASM_API void checkasm_randomize_range(double *buf, int width, double range);
212
213/**
214 * @brief Fill a float buffer with random values chosen uniformly below a limit
215 * @param[out] buf Buffer to fill
216 * @param[in] width Number of elements to randomize
217 * @param[in] range Exclusive upper bound on value (range is [0, range))
218 */
219CHECKASM_API void checkasm_randomize_rangef(float *buf, int width, float range);
220
221/**
222 * @brief Fill a double buffer with random values chosen uniformly from an interval
223 * @param[out] buf Buffer to fill
224 * @param[in] width Number of elements to randomize
225 * @param[in] low Inclusive lower bound on value
226 * @param[in] high Inclusive upper bound on value
227 */
228CHECKASM_API void checkasm_randomize_interval(double *buf, int width, double low,
229 double high);
230
231/**
232 * @brief Fill a float buffer with random values chosen uniformly from an interval
233 * @param[out] buf Buffer to fill
234 * @param[in] width Number of elements to randomize
235 * @param[in] low Inclusive lower bound on value
236 * @param[in] high Inclusive upper bound on value
237 */
238CHECKASM_API void checkasm_randomize_intervalf(float *buf, int width, float low,
239 float high);
240
241/**
242 * @brief Fill a double buffer with normally distributed random values
243 * @param[out] buf Buffer to fill
244 * @param[in] width Number of elements to randomize
245 * @param[in] dist Distribution parameters (mean and standard deviation)
246 */
247CHECKASM_API void checkasm_randomize_dist(double *buf, int width, CheckasmDist dist);
248
249/**
250 * @brief Fill a float buffer with normally distributed random values
251 * @param[out] buf Buffer to fill
252 * @param[in] width Number of elements to randomize
253 * @param[in] dist Distribution parameters (mean and standard deviation)
254 */
255CHECKASM_API void checkasm_randomize_distf(float *buf, int width, CheckasmDist dist);
256
257/**
258 * @brief Fill a double buffer with values from a standard normal distribution
259 * @param[out] buf Buffer to fill
260 * @param[in] width Number of elements to randomize
261 */
262CHECKASM_API void checkasm_randomize_norm(double *buf, int width);
263
264/**
265 * @brief Fill a float buffer with values from a standard normal distribution
266 * @param[out] buf Buffer to fill
267 * @param[in] width Number of elements to randomize
268 */
269CHECKASM_API void checkasm_randomize_normf(float *buf, int width);
270
271/**
272 * @brief Clear a buffer to a pre-determined pattern (currently 0xAA)
273 * @param[out] buf Buffer to clear
274 * @param[in] bytes Number of bytes to clear
275 */
276CHECKASM_API void checkasm_clear(void *buf, size_t bytes);
277
278/**
279 * @brief Fill a uint8_t buffer with a constant value
280 * @param[out] buf Buffer to fill
281 * @param[in] width Number of elements to set
282 * @param[in] val Value to write to each element
283 * @note This is functionally equivalent to memset(), and merely provided for
284 * consistency.
285 */
286CHECKASM_API void checkasm_clear8(uint8_t *buf, int width, uint8_t val);
287
288/**
289 * @brief Fill a uint16_t buffer with a constant value
290 * @param[out] buf Buffer to fill
291 * @param[in] width Number of elements to set
292 * @param[in] val Value to write to each element
293 */
294CHECKASM_API void checkasm_clear16(uint16_t *buf, int width, uint16_t val);
295
296/**
297 * @brief Initialize a buffer with pathological test patterns
298 *
299 * Fills a buffer with a random mixture of edge cases, test patterns, and
300 * random data designed to trigger potential bugs. The exact pattern depends
301 * on the random seed and may include a mix of low values, high values,
302 * alternating bits, random bytes, and so on.
303 *
304 * @param[out] buf Buffer to initialize
305 * @param[in] bytes Number of bytes to initialize
306 */
307CHECKASM_API void checkasm_init(void *buf, size_t bytes);
308
309/**
310 * @brief Initialize a uint8_t buffer with pathological values within a mask
311 * @param[out] buf Buffer to initialize
312 * @param[in] width Number of elements to initialize
313 * @param[in] mask Bit mask to apply to values
314 * @see checkasm_init()
315 */
316CHECKASM_API void checkasm_init_mask8(uint8_t *buf, int width, uint8_t mask);
317
318/**
319 * @brief Initialize a uint16_t buffer with pathological values within a mask
320 * @param[out] buf Buffer to initialize
321 * @param[in] width Number of elements to initialize
322 * @param[in] mask Bit mask to apply to values
323 * @see checkasm_init()
324 */
325CHECKASM_API void checkasm_init_mask16(uint16_t *buf, int width, uint16_t mask);
326
327/**
328 * @def CLEAR_BUF(buf)
329 * @brief Clear a fixed size buffer (convenience macro)
330 * @param buf Fixed-size buffer array to clear
331 */
332#define CLEAR_BUF(buf) checkasm_clear(buf, sizeof(buf))
333
334/**
335 * @def RANDOMIZE_BUF(buf)
336 * @brief Fill a fixed size buffer with random data (convenience macro)
337 * @param buf Fixed-size buffer array to randomize
338 */
339#define RANDOMIZE_BUF(buf) checkasm_randomize(buf, sizeof(buf))
340
341/**
342 * @def INITIALIZE_BUF(buf)
343 * @brief Fill a fixed size buffer with pathological test data (convenience macro)
344 * @param buf Fixed-size buffer array to initialize
345 * @see checkasm_init()
346 */
347#define INITIALIZE_BUF(buf) checkasm_init(buf, sizeof(buf))
348
349/** @} */ /* memory */
350
351/**
352 * @defgroup floatcmp Floating-Point Comparison
353 * @brief Utilities for comparing floating-point values with tolerance
354 *
355 * These functions compare floating-point values allowing for acceptable
356 * differences due to rounding, precision loss, or different computation orders.
357 * @{
358 */
359
360/**
361 * @brief Compare floats using ULP (Units in Last Place) tolerance
362 * @param[in] a First value
363 * @param[in] b Second value
364 * @param[in] max_ulp Maximum acceptable ULP distance
365 * @return Non-zero if values are within tolerance, 0 otherwise
366 */
367CHECKASM_API int checkasm_float_near_ulp(float a, float b, unsigned max_ulp);
368
369/**
370 * @brief Compare floats using absolute epsilon tolerance
371 * @param[in] a First value
372 * @param[in] b Second value
373 * @param[in] eps Maximum acceptable absolute difference
374 * @return Non-zero if |a-b| < eps, 0 otherwise
375 */
376CHECKASM_API int checkasm_float_near_abs_eps(float a, float b, float eps);
377
378/**
379 * @brief Compare floats using both epsilon and ULP tolerances
380 * @param[in] a First value
381 * @param[in] b Second value
382 * @param[in] eps Maximum acceptable absolute difference
383 * @param[in] max_ulp Maximum acceptable ULP distance
384 * @return Non-zero if within either tolerance, 0 otherwise
385 */
386CHECKASM_API int checkasm_float_near_abs_eps_ulp(float a, float b, float eps,
387 unsigned max_ulp);
388
389/**
390 * @brief Compare float arrays using ULP tolerance
391 * @param[in] a First array
392 * @param[in] b Second array
393 * @param[in] max_ulp Maximum acceptable ULP distance
394 * @param[in] len Number of elements to compare
395 * @return Non-zero if all elements are within tolerance, 0 otherwise
396 */
397CHECKASM_API int checkasm_float_near_ulp_array(const float *a, const float *b,
398 unsigned max_ulp, int len);
399
400/**
401 * @brief Compare float arrays using absolute epsilon tolerance
402 * @param[in] a First array
403 * @param[in] b Second array
404 * @param[in] eps Maximum acceptable absolute difference per element
405 * @param[in] len Number of elements to compare
406 * @return Non-zero if all elements are within tolerance, 0 otherwise
407 */
408CHECKASM_API int checkasm_float_near_abs_eps_array(const float *a, const float *b,
409 float eps, int len);
410
411/**
412 * @brief Compare float arrays using both epsilon and ULP tolerances
413 * @param[in] a First array
414 * @param[in] b Second array
415 * @param[in] eps Maximum acceptable absolute difference per element
416 * @param[in] max_ulp Maximum acceptable ULP distance
417 * @param[in] len Number of elements to compare
418 * @return Non-zero if all elements are within tolerance, 0 otherwise
419 */
420CHECKASM_API int checkasm_float_near_abs_eps_array_ulp(const float *a, const float *b,
421 float eps, unsigned max_ulp,
422 int len);
423
424/**
425 * @brief Compare doubles using absolute epsilon tolerance
426 * @param[in] a First value
427 * @param[in] b Second value
428 * @param[in] eps Maximum acceptable absolute difference
429 * @return Non-zero if |a-b| <= eps, 0 otherwise
430 */
431CHECKASM_API int checkasm_double_near_abs_eps(double a, double b, double eps);
432
433/**
434 * @brief Compare double arrays using absolute epsilon tolerance
435 * @param[in] a First array
436 * @param[in] b Second array
437 * @param[in] eps Maximum acceptable absolute difference per element
438 * @param[in] len Number of elements to compare
439 * @return Non-zero if all elements are within tolerance, 0 otherwise
440 */
441CHECKASM_API int checkasm_double_near_abs_eps_array(const double *a, const double *b,
442 double eps, unsigned len);
443
444/** @} */ /* floatcmp */
445
446/** @addtogroup aliases
447 * @{ */
448#define float_near_ulp checkasm_float_near_ulp
449#define float_near_abs_eps checkasm_float_near_abs_eps
450#define float_near_abs_eps_ulp checkasm_float_near_abs_eps_ulp
451#define float_near_ulp_array checkasm_float_near_ulp_array
452#define float_near_abs_eps_array checkasm_float_near_abs_eps_array
453#define float_near_abs_eps_array_ulp checkasm_float_near_abs_eps_array_ulp
454#define double_near_abs_eps checkasm_double_near_abs_eps
455#define double_near_abs_eps_array checkasm_double_near_abs_eps_array
456/** @} */
457
458/**
459 * @defgroup bufcmp Buffer Comparison Utilities
460 * @brief Functions and macros for comparing multi-dimensional buffers
461 *
462 * These utilities compare 2D buffers (with stride support) and detect
463 * differences, including in padding regions. Used to verify that optimized
464 * implementations produce bit-identical output to reference implementations.
465 * @{
466 */
467
468/**
469 * @def CHECKASM_ALIGN(x)
470 * @brief Declare a variable with platform-specific alignment requirements
471 * @param x Variable declaration
472 * @note This must be applied to each buffer individually!
473 *
474 * @code
475 * // correct
476 * CHECKASM_ALIGN(uint8_t buf1[64*64]);
477 * CHECKASM_ALIGN(uint8_t buf2[64*64]);
478 *
479 * // wrong
480 * CHECKASM_ALIGN(uint8_t buf1[64*64], buf2[64*64]);
481 * @endcode
482 */
483#ifdef _MSC_VER
484 #define CHECKASM_ALIGN(x) __declspec(align(CHECKASM_ALIGNMENT)) x
485#else
486 #define CHECKASM_ALIGN(x) x __attribute__((aligned(CHECKASM_ALIGNMENT)))
487#endif
488
489/**
490 * @addtogroup internal
491 * @{
492 */
493
494#define DECL_CHECK_FUNC(NAME, TYPE) \
495 int (NAME)(const char *const file, const int line, const TYPE *const buf1, \
496 const ptrdiff_t stride1, const TYPE *const buf2, const ptrdiff_t stride2, \
497 const int w, const int h, const char *const buf_name, const int align_w, \
498 const int align_h, const int padding)
499
500#define DECL_CHECKASM_CHECK_FUNC(type) \
501 CHECKASM_API DECL_CHECK_FUNC(checkasm_check_impl_##type, type)
502
507
512
513/**
514 * @brief Compare float buffers with ULP tolerance
515 */
516CHECKASM_API int checkasm_check_impl_float_ulp(const char *file, int line,
517 const float *buf1, ptrdiff_t stride1,
518 const float *buf2, ptrdiff_t stride2,
519 int w, int h, const char *name,
520 unsigned max_ulp, int align_w, int align_h,
521 int padding);
522
523#define checkasm_check_impl2(type) checkasm_check_impl_##type
524#define checkasm_check_impl(type) checkasm_check_impl2(type)
525#define checkasm_check1(type, ...) checkasm_check_impl_##type(__VA_ARGS__)
526#define checkasm_check2(type, ...) checkasm_check1(type, __FILE__, __LINE__, __VA_ARGS__)
527
528/** @} */ /* internal */
529
530/**
531 * @def checkasm_check2d(type, buf1, stride1, buf2, stride2, w, h, name, ...)
532 * @brief Compare two 2D buffers and fail test if different
533 * @param type Element type (e.g., uint8_t, int, float)
534 * @param buf1 First buffer pointer to compare
535 * @param stride1 First buffer stride in bytes
536 * @param buf2 Second buffer pointer to compare
537 * @param stride2 Second buffer stride in bytes
538 * @param w Width of the buffers in elements
539 * @param h Height of the buffers in lines
540 * @param name Name of the buffer (for error reporting)
541 * @param ... Extra parameters (e.g. max_ulp for checkasm_check2d(float_ulp, ...))
542 * @note This will automatically print a hexdump of the differing regions on
543 * failure, if verbose mode is enabled.
544 *
545 * @code
546 * CHECKASM_ALIGN(uint8_t buf1[64][64]);
547 * CHECKASM_ALIGN(uint8_t buf2[64][64]);
548 * const ptrdiff_t stride = sizeof(buf1[0]);
549 *
550 * for (int h = 8; h <= 64; h <<= 1) {
551 * for (int w = 8; w <= 64; w <<= 1) {
552 * if (checkasm_check_func(..., "myfunc_%dx%d", w, h)) {
553 * checkasm_call_ref(buf1, strude, w, h);
554 * checkasm_call_new(buf2, strude, w, h);
555 * checkasm_check2d(uint8_t, buf1, stride, buf2, stride, w, h, "buffer");
556 * }
557 * }
558 * @endcode
559 */
560#define checkasm_check2d(type, ...) checkasm_check2(type, __VA_ARGS__, 0, 0, 0)
561
562/**
563 * @def checkasm_check2d_padded(type, buf1, stride1, buf2, stride2, w, h, name,
564 * ..., align_w, align_h, padding)
565 * @brief Compare two 2D buffers, including padding regions (detect over-write)
566 * @param type Element type (e.g., uint8_t, int, float)
567 * @param buf1 First buffer pointer to compare
568 * @param stride1 First buffer stride in bytes
569 * @param buf2 Second buffer pointer to compare
570 * @param stride2 Second buffer stride in bytes
571 * @param w Width of the buffers in elements
572 * @param h Height of the buffers in lines
573 * @param name Name of the buffer (for error reporting)
574 * @param ... Extra parameters (e.g. max_ulp for checkasm_check2d_padded(float_ulp, ...))
575 * @param align_w Horizontal alignment of the allowed over-write (elements)
576 * @param align_h Vertical alignment of the allowed over-write (lines), or
577 * 0 to disable top/bottom overwrite checks.
578 * @param padding Number of extra elements/lines of padding to check (past the
579 * alignment boundaries)
580 * @see checkasm_check2d(), checkasm_check_rect_padded()
581 */
582#define checkasm_check2d_padded(type, ...) checkasm_check2(type, __VA_ARGS__)
583
584/**
585 * @def checkasm_check1d(type, buf1, buf2, len, name, ...)
586 * @brief Compare two 1D buffers and fail test if different
587 * @param type Element type (e.g., uint8_t, int, float)
588 * @param buf1 First buffer pointer to compare
589 * @param buf2 Second buffer pointer to compare
590 * @param len Length of the buffers in elements
591 * @param ... Extra parameters (e.g. max_ulp for checkasm_check(float_ulp, ...))
592 * @see checkasm_check2d()
593 *
594 * @code
595 * CHECKASM_ALIGN(uint8_t buf1[256]);
596 * CHECKASM_ALIGN(uint8_t buf2[256]);
597 * for (int w = 8; w <= 256; w <<= 1) {
598 * if (checkasm_check_func(..., "myfunc_w%d", w)) {
599 * checkasm_call_ref(buf1, w);
600 * checkasm_call_new(buf2, w);
601 * checkasm_check1d(uint8_t, buf1, buf2, w, "buffer");
602 * }
603 */
604#define checkasm_check1d(type, buf1, buf2, len, ...) \
605 checkasm_check2d(type, buf1, 0, buf2, 0, len, 1, __VA_ARGS__)
606
607/**
608 * @def checkasm_check1d_padded(type, buf1, buf2, len, name, align_w, padding)
609 * @brief Compare two 1D buffers, including padding regions (detect over-write)
610 * @param type Element type (e.g., uint8_t, int, float)
611 * @param buf1 First buffer pointer to compare
612 * @param buf2 Second buffer pointer to compare
613 * @param len Length of the buffers in elements
614 * @param name Name of the buffer (for error reporting)
615 * @param align Alignment of the allowed over-write (elements)
616 * @param padding Number of extra elements of padding to check (past the
617 * alignment boundary)
618 * @see checkasm_check2d_padded()
619 *
620 * @note For implementation reasons, this macro does not accept variadic
621 * parameters (e.g. for `float_ulp` checks). If you need those, use
622 * `checkasm_check2d_padded()` with `align_h = 0` instead.
623 */
624#define checkasm_check1d_padded(type, buf1, buf2, len, name, align, padding) \
625 checkasm_check2d_padded(type, buf1, 0, buf2, 0, len, 1, name, align, 0, padding)
626
627/** @} */ /* bufcmp */
628
629/** @addtogroup aliases
630 * @{ */
631#define checkasm_check checkasm_check2d
632#define checkasm_check_padded checkasm_check2d_padded
633/* @} */
634
635/**
636 * @defgroup bufrect Rectangular Buffer Helpers
637 * @brief Macros for creating aligned, padded 2D test buffers
638 *
639 * These macros simplify creating properly aligned and padded rectangular
640 * buffers for testing, including automatic stride calculation and padding
641 * detection support.
642 * @{
643 */
644
645/**
646 * @def CHECKASM_ROUND(x, a)
647 * @brief Round up to nearest multiple of a
648 * @param x Value to round
649 * @param a Alignment (must be power of 2)
650 * @private
651 */
652#define CHECKASM_ROUND(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
653
654/**
655 * @def BUF_RECT(type, name, w, h)
656 * @brief Declare an aligned, padded rectangular buffer
657 *
658 * Creates a properly aligned rectangular buffer with padding on all sides for
659 * use with checkasm_check_rect_padded(). Sets up associated metadata (stride,
660 * height) and declares a pointer to the usable data region.
661 *
662 * @param type Element type (e.g., uint8_t, int16_t)
663 * @param name Base name for the buffer variables
664 * @param w Width of the usable buffer region
665 * @param h Height of the usable buffer region
666 *
667 * Creates:
668 * - name_buf: Full buffer array (with padding)
669 * - name_stride: Stride in bytes
670 * - name_buf_h: Total buffer height in lines (with padding)
671 * - name: Pointer to start of usable region
672 *
673 * @code
674 * BUF_RECT(uint8_t, src, 64, 32);
675 * BUF_RECT(uint8_t, dst, 64, 32);
676 * // uint8_t *src, *dst; // now point to a 64x32 usable area
677 * INITIALIZE_BUF_RECT(src);
678 * CLEAR_BUF_RECT(dst);
679 * // ...
680 * checkasm_call_new(dst, dst_stride, src, src_stride, 64, 32);
681 * @endcode
682 */
683#define BUF_RECT(type, name, w, h) \
684 DECL_CHECK_FUNC(*checkasm_check_impl_##name##_type, type) \
685 = checkasm_check_impl_##type; \
686 CHECKASM_ALIGN(type name##_buf[((h) + 32) * (CHECKASM_ROUND(w, 64) + 64) + 64]); \
687 const int name##_buf_w = CHECKASM_ROUND(w, 64) + 64; \
688 const int name##_buf_h = (h) + 32; \
689 ptrdiff_t name##_stride = sizeof(type) * name##_buf_w; \
690 (void) checkasm_check_impl(name##_type); \
691 (void) name##_stride; \
692 (void) name##_buf_h; \
693 type *name = name##_buf + name##_buf_w * 16 + 64
694
695/**
696 * @def CLEAR_BUF_RECT(name)
697 * @brief Clear a rectangular buffer (including padding)
698 * @param name Buffer name (from BUF_RECT)
699 * @see checkasm_clear()
700 */
701#define CLEAR_BUF_RECT(name) CLEAR_BUF(name##_buf)
702
703/**
704 * @def INITIALIZE_BUF_RECT(name)
705 * @brief Initialize a rectangular buffer (including padding) with pathological values
706 * @param name Buffer name (from BUF_RECT)
707 * @see checkasm_init()
708 */
709#define INITIALIZE_BUF_RECT(name) INITIALIZE_BUF(name##_buf)
710
711/**
712 * @def RANDOMIZE_BUF_RECT(name)
713 * @brief Randomize a rectangular buffer (including padding)
714 * @param name Buffer name (from BUF_RECT)
715 * @see checkasm_randomize()
716 */
717#define RANDOMIZE_BUF_RECT(name) RANDOMIZE_BUF(name##_buf)
718
719/**
720 * @def checkasm_check_rect(rect1, ...)
721 * @brief Compare two rectangular buffers
722 * @param rect1 First buffer (from BUF_RECT)
723 * @param ... rect2, stride2, w, h, name
724 * @see checkasm_check2d()
725 */
726#define checkasm_check_rect(rect1, ...) checkasm_check2d(rect1##_type, rect1, __VA_ARGS__)
727
728/**
729 * @def checkasm_check_rect_padded(rect1, ...)
730 * @brief Compare two rectangular buffers including padding
731 * @param rect1 First buffer (from BUF_RECT)
732 * @param ... rect2, stride2, w, h, name
733 * @see checkasm_check2d()
734 */
735#define checkasm_check_rect_padded(rect1, ...) \
736 checkasm_check2d_padded(rect1##_type, rect1, __VA_ARGS__, 1, 1, 8)
737
738/**
739 * @def checkasm_check_rect_padded_align(rect1, ...)
740 * @brief Compare two rectangular buffers, with custom alignment (over-write)
741 * @param rect1 First buffer (from BUF_RECT)
742 * @param ... rect2, stride2, w, h, name, align
743 * @see checkasm_check2d_padded()
744 *
745 * @code
746 * // Code is allowed to over-write up to 16 elements on the right edge only
747 * checkasm_check_rect_padded_align(src, src_stride, dst, dst_stride, w, h,
748 * "buffer", 16, 1);
749 * @endcode
750 */
751#define checkasm_check_rect_padded_align(rect1, ...) \
752 checkasm_check2d_padded(rect1##_type, rect1, __VA_ARGS__, 8)
753
754/**
755 * @def CHECK_BUF_RECT(buf1, buf2, w, h)
756 * @brief Compare two rectangular buffers (convenience macro)
757 * @param buf1 First buffer (from BUF_RECT)
758 * @param buf2 Second buffer (from BUF_RECT)
759 * @param w Width of the usable buffer region
760 * @param h Height of the usable buffer region
761 * @see checkasm_check_rect_padded()
762 */
763#define CHECK_BUF_RECT(buf1, buf2, w, h) \
764 checkasm_check_rect_padded(buf1, buf1##_stride, buf2, buf2##_stride, w, h, \
765 #buf1 " vs " #buf2)
766
767/** @} */ /* bufrect */
768
769#endif /* CHECKASM_UTILS_H */
static double val(void *priv, double ch)
Definition aeval.c:77
int32_t
long long int64_t
Definition coverity.c:34
int high
Definition dovi_rpuenc.c:39
CHECKASM_API int checkasm_float_near_abs_eps_array(const float *a, const float *b, float eps, int len)
Compare float arrays using absolute epsilon tolerance.
Definition utils.c:684
CHECKASM_API int checkasm_float_near_ulp_array(const float *a, const float *b, unsigned max_ulp, int len)
Compare float arrays using ULP tolerance.
Definition utils.c:669
CHECKASM_API int checkasm_float_near_ulp(float a, float b, unsigned max_ulp)
Compare floats using ULP (Units in Last Place) tolerance.
Definition utils.c:651
CHECKASM_API int checkasm_float_near_abs_eps_ulp(float a, float b, float eps, unsigned max_ulp)
Compare floats using both epsilon and ULP tolerances.
Definition utils.c:694
CHECKASM_API int checkasm_double_near_abs_eps_array(const double *a, const double *b, double eps, unsigned len)
Compare double arrays using absolute epsilon tolerance.
Definition utils.c:716
CHECKASM_API int checkasm_float_near_abs_eps(float a, float b, float eps)
Compare floats using absolute epsilon tolerance.
Definition utils.c:679
CHECKASM_API int checkasm_double_near_abs_eps(double a, double b, double eps)
Compare doubles using absolute epsilon tolerance.
Definition utils.c:711
CHECKASM_API int checkasm_float_near_abs_eps_array_ulp(const float *a, const float *b, float eps, unsigned max_ulp, int len)
Compare float arrays using both epsilon and ULP tolerances.
Definition utils.c:700
CHECKASM_API 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.
Definition utils.c:843
#define DECL_CHECKASM_CHECK_FUNC(type)
Definition utils.h:500
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.
CHECKASM_API void checkasm_randomize_normf(float *buf, int width)
Fill a float buffer with values from a standard normal distribution.
Definition utils.c:367
CHECKASM_API void checkasm_randomize_intervalf(float *buf, int width, float low, float high)
Fill a float buffer with random values chosen uniformly from an interval.
Definition utils.c:330
CHECKASM_API void checkasm_randomize_interval(double *buf, int width, double low, double high)
Fill a double buffer with random values chosen uniformly from an interval.
Definition utils.c:323
CHECKASM_API void checkasm_randomize(void *buf, size_t bytes)
Fill a buffer with uniformly chosen random bytes.
Definition utils.c:290
CHECKASM_API void checkasm_clear16(uint16_t *buf, int width, uint16_t val)
Fill a uint16_t buffer with a constant value.
Definition utils.c:382
CHECKASM_API void checkasm_clear(void *buf, size_t bytes)
Clear a buffer to a pre-determined pattern (currently 0xAA)
Definition utils.c:372
CHECKASM_API 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.
Definition utils.c:302
CHECKASM_API void checkasm_randomize_rangef(float *buf, int width, float range)
Fill a float buffer with random values chosen uniformly below a limit.
Definition utils.c:316
CHECKASM_API 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.
Definition utils.c:295
CHECKASM_API void checkasm_randomize_norm(double *buf, int width)
Fill a double buffer with values from a standard normal distribution.
Definition utils.c:362
CHECKASM_API void checkasm_randomize_dist(double *buf, int width, CheckasmDist dist)
Fill a double buffer with normally distributed random values.
Definition utils.c:352
CHECKASM_API void checkasm_randomize_range(double *buf, int width, double range)
Fill a double buffer with random values chosen uniformly below a limit.
Definition utils.c:309
CHECKASM_API void checkasm_randomize_distf(float *buf, int width, CheckasmDist dist)
Fill a float buffer with normally distributed random values.
Definition utils.c:357
CHECKASM_API void checkasm_init(void *buf, size_t bytes)
Initialize a buffer with pathological test patterns.
Definition utils.c:431
CHECKASM_API void checkasm_init_mask16(uint16_t *buf, int width, uint16_t mask)
Initialize a uint16_t buffer with pathological values within a mask.
CHECKASM_API void checkasm_clear8(uint8_t *buf, int width, uint8_t val)
Fill a uint8_t buffer with a constant value.
Definition utils.c:377
CHECKASM_API int16_t checkasm_rand_int16(void)
Generate a random 16-bit signed integer.
CHECKASM_API int32_t checkasm_rand_int32(void)
Generate a random 32-bit signed integer.
CHECKASM_API int64_t checkasm_rand_int64(void)
Generate a random 64-bit signed integer.
CHECKASM_API int checkasm_rand(void)
Generate a random non-negative integer.
Definition utils.c:248
CHECKASM_API uint16_t checkasm_rand_uint16(void)
Generate a random 16-bit unsigned integer.
CHECKASM_API float checkasm_rand_float32(void)
Generate a truly random 32-bit float.
CHECKASM_API uint8_t checkasm_rand_uint8(void)
Generate a random 8-bit unsigned integer.
CHECKASM_API double checkasm_rand_float64(void)
Generate a truly random 64-bit float.
CHECKASM_API double checkasm_randf(void)
Generate a random double-precision floating-point number.
Definition utils.c:254
CHECKASM_API uint32_t checkasm_rand_uint32(void)
Generate a random 32-bit unsigned integer.
CHECKASM_API uint64_t checkasm_rand_uint64(void)
Generate a random 64-bit unsigned integer.
CHECKASM_API int8_t checkasm_rand_int8(void)
Generate a random 8-bit signed integer.
int a
#define b
Definition input.c:43
uint8_t w
Definition llvidencdsp.c:39
static const uint16_t mask[17]
Definition lzw.c:38
enum AVColorRange range
const char * name
Definition qsvenc.c:142
Describes a normal (Gaussian) distribution.
Definition utils.h:147
double stddev
Standard deviation (spread) of the distribution.
Definition utils.h:149
double mean
Mean (center) of the distribution.
Definition utils.h:148
Platform and compiler attribute macros.
#define CHECKASM_API
Symbol visibility attribute for public API functions.
Definition attributes.h:90
CHECKASM_API double checkasm_rand_norm(void)
Generate a random number from the standard normal distribution.
Definition utils.c:274
CHECKASM_API double checkasm_rand_dist(CheckasmDist dist)
Generate a normally distributed random number.
Definition utils.c:285
#define width
Definition dsp.h:89
int len