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