1 /* Copyright (c) 2023 Google LLC
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #ifndef ZEPHYR_INCLUDE_DSP_PRINT_FORMAT_H_
6 #define ZEPHYR_INCLUDE_DSP_PRINT_FORMAT_H_
7 
8 #include <inttypes.h>
9 #include <stdlib.h>
10 #include <zephyr/dsp/types.h>
11 
12 /**
13  * @ingroup math_dsp
14  * @defgroup math_printing Helper macros for printing Q values.
15  *
16  * Extends the existing inttypes headers for print formatting. Usage:
17  * @code{c}
18  * printk("Value=%" PRIq "\n", PRIq_arg(value, 6, 2));
19  * @endcode
20  *
21  * For a Q value representing 0.5, the expected output will be:
22  *   "Value=2.000000"
23  *
24  * @{
25  */
26 
27 /**
28  * @brief Insert Q value format string
29  */
30 #define PRIq(precision) "s%" PRIu32 ".%0" STRINGIFY(precision) PRIu32
31 
___PRIq_arg_shift(int64_t q,int shift)32 static inline int64_t ___PRIq_arg_shift(int64_t q, int shift)
33 {
34 	if (shift < 0) {
35 		return llabs(q) >> -shift;
36 	} else {
37 		return llabs(q) << shift;
38 	}
39 }
40 
41 #define __EXP2(a, b) a ## b
42 #define __EXP(a, b) __EXP2(a ## e, b)
43 #define __CONSTPOW(C, x) __EXP(C, x)
44 
45 #define __PRIq_arg_shift(q, shift)     ___PRIq_arg_shift(q, ((shift) + (8 * (4 - (int)sizeof(q)))))
46 #define __PRIq_arg_get(q, shift, h, l) FIELD_GET(GENMASK64(h, l), __PRIq_arg_shift(q, shift))
47 #define __PRIq_arg_get_int(q, shift)   __PRIq_arg_get(q, shift, 63, 31)
48 #define __PRIq_arg_get_frac(q, precision, shift)                                                   \
49 	((__PRIq_arg_get(q, shift, 30, 0) * __CONSTPOW(1, precision)) / INT32_MAX)
50 
51 /**
52  * @brief Insert Q value arguments to print format
53  *
54  * @param[in] q The q value
55  * @param[in] precision Number of decimal points to print
56  * @param[in] shift The "scale" to shift @p q by
57  */
58 #define PRIq_arg(q, precision, shift)                                                              \
59 	((q) < 0 ? "-" : ""), (uint32_t)__PRIq_arg_get_int(q, shift),                              \
60 		(uint32_t)__PRIq_arg_get_frac(q, precision, shift)
61 
62 /**
63  * @}
64  */
65 
66 #endif /* ZEPHYR_INCLUDE_DSP_PRINT_FORMAT_H_ */
67