xref: /linux-6.15/include/linux/util_macros.h (revision b2108fc8)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
295d11952SBartosz Golaszewski #ifndef _LINUX_HELPER_MACROS_H_
395d11952SBartosz Golaszewski #define _LINUX_HELPER_MACROS_H_
495d11952SBartosz Golaszewski 
59456d539SAndy Shevchenko #include <linux/math.h>
69456d539SAndy Shevchenko 
795d11952SBartosz Golaszewski /**
8*b2108fc8SAndy Shevchenko  * for_each_if - helper for handling conditionals in various for_each macros
9*b2108fc8SAndy Shevchenko  * @condition: The condition to check
10*b2108fc8SAndy Shevchenko  *
11*b2108fc8SAndy Shevchenko  * Typical use::
12*b2108fc8SAndy Shevchenko  *
13*b2108fc8SAndy Shevchenko  *	#define for_each_foo_bar(x, y) \'
14*b2108fc8SAndy Shevchenko  *		list_for_each_entry(x, y->list, head) \'
15*b2108fc8SAndy Shevchenko  *			for_each_if(x->something == SOMETHING)
16*b2108fc8SAndy Shevchenko  *
17*b2108fc8SAndy Shevchenko  * The for_each_if() macro makes the use of for_each_foo_bar() less error
18*b2108fc8SAndy Shevchenko  * prone.
19*b2108fc8SAndy Shevchenko  */
20*b2108fc8SAndy Shevchenko #define for_each_if(condition) if (!(condition)) {} else
21*b2108fc8SAndy Shevchenko 
22*b2108fc8SAndy Shevchenko /**
2395d11952SBartosz Golaszewski  * find_closest - locate the closest element in a sorted array
2495d11952SBartosz Golaszewski  * @x: The reference value.
2595d11952SBartosz Golaszewski  * @a: The array in which to look for the closest element. Must be sorted
2695d11952SBartosz Golaszewski  *  in ascending order.
2795d11952SBartosz Golaszewski  * @as: Size of 'a'.
2895d11952SBartosz Golaszewski  *
2995d11952SBartosz Golaszewski  * Returns the index of the element closest to 'x'.
30bc73b418SAlexandru Ardelean  * Note: If using an array of negative numbers (or mixed positive numbers),
31bc73b418SAlexandru Ardelean  *       then be sure that 'x' is of a signed-type to get good results.
3295d11952SBartosz Golaszewski  */
33bc73b418SAlexandru Ardelean #define find_closest(x, a, as)						\
34bc73b418SAlexandru Ardelean ({									\
35bc73b418SAlexandru Ardelean 	typeof(as) __fc_i, __fc_as = (as) - 1;				\
36bc73b418SAlexandru Ardelean 	long __fc_mid_x, __fc_x = (x);					\
37bc73b418SAlexandru Ardelean 	long __fc_left, __fc_right;					\
38bc73b418SAlexandru Ardelean 	typeof(*a) const *__fc_a = (a);					\
39bc73b418SAlexandru Ardelean 	for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) {			\
40bc73b418SAlexandru Ardelean 		__fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i + 1]) / 2;	\
41bc73b418SAlexandru Ardelean 		if (__fc_x <= __fc_mid_x) {				\
42bc73b418SAlexandru Ardelean 			__fc_left = __fc_x - __fc_a[__fc_i];		\
43bc73b418SAlexandru Ardelean 			__fc_right = __fc_a[__fc_i + 1] - __fc_x;	\
44bc73b418SAlexandru Ardelean 			if (__fc_right < __fc_left)			\
45bc73b418SAlexandru Ardelean 				__fc_i++;				\
46bc73b418SAlexandru Ardelean 			break;						\
47bc73b418SAlexandru Ardelean 		}							\
48bc73b418SAlexandru Ardelean 	}								\
49bc73b418SAlexandru Ardelean 	(__fc_i);							\
50bc73b418SAlexandru Ardelean })
5195d11952SBartosz Golaszewski 
5295d11952SBartosz Golaszewski /**
5395d11952SBartosz Golaszewski  * find_closest_descending - locate the closest element in a sorted array
5495d11952SBartosz Golaszewski  * @x: The reference value.
5595d11952SBartosz Golaszewski  * @a: The array in which to look for the closest element. Must be sorted
5695d11952SBartosz Golaszewski  *  in descending order.
5795d11952SBartosz Golaszewski  * @as: Size of 'a'.
5895d11952SBartosz Golaszewski  *
5995d11952SBartosz Golaszewski  * Similar to find_closest() but 'a' is expected to be sorted in descending
60bc73b418SAlexandru Ardelean  * order. The iteration is done in reverse order, so that the comparison
61bc73b418SAlexandru Ardelean  * of '__fc_right' & '__fc_left' also works for unsigned numbers.
6295d11952SBartosz Golaszewski  */
63bc73b418SAlexandru Ardelean #define find_closest_descending(x, a, as)				\
64bc73b418SAlexandru Ardelean ({									\
65bc73b418SAlexandru Ardelean 	typeof(as) __fc_i, __fc_as = (as) - 1;				\
66bc73b418SAlexandru Ardelean 	long __fc_mid_x, __fc_x = (x);					\
67bc73b418SAlexandru Ardelean 	long __fc_left, __fc_right;					\
68bc73b418SAlexandru Ardelean 	typeof(*a) const *__fc_a = (a);					\
69bc73b418SAlexandru Ardelean 	for (__fc_i = __fc_as; __fc_i >= 1; __fc_i--) {			\
70bc73b418SAlexandru Ardelean 		__fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i - 1]) / 2;	\
71bc73b418SAlexandru Ardelean 		if (__fc_x <= __fc_mid_x) {				\
72bc73b418SAlexandru Ardelean 			__fc_left = __fc_x - __fc_a[__fc_i];		\
73bc73b418SAlexandru Ardelean 			__fc_right = __fc_a[__fc_i - 1] - __fc_x;	\
74bc73b418SAlexandru Ardelean 			if (__fc_right < __fc_left)			\
75bc73b418SAlexandru Ardelean 				__fc_i--;				\
76bc73b418SAlexandru Ardelean 			break;						\
77bc73b418SAlexandru Ardelean 		}							\
78bc73b418SAlexandru Ardelean 	}								\
79bc73b418SAlexandru Ardelean 	(__fc_i);							\
80bc73b418SAlexandru Ardelean })
8195d11952SBartosz Golaszewski 
82ddce1e09SJakub Sitnicki /**
83ddce1e09SJakub Sitnicki  * is_insidevar - check if the @ptr points inside the @var memory range.
84ddce1e09SJakub Sitnicki  * @ptr:	the pointer to a memory address.
85ddce1e09SJakub Sitnicki  * @var:	the variable which address and size identify the memory range.
86ddce1e09SJakub Sitnicki  *
87ddce1e09SJakub Sitnicki  * Evaluates to true if the address in @ptr lies within the memory
88ddce1e09SJakub Sitnicki  * range allocated to @var.
89ddce1e09SJakub Sitnicki  */
90ddce1e09SJakub Sitnicki #define is_insidevar(ptr, var)						\
91ddce1e09SJakub Sitnicki 	((uintptr_t)(ptr) >= (uintptr_t)(var) &&			\
92ddce1e09SJakub Sitnicki 	 (uintptr_t)(ptr) <  (uintptr_t)(var) + sizeof(var))
93ddce1e09SJakub Sitnicki 
9495d11952SBartosz Golaszewski #endif
95