1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_HELPER_MACROS_H_ 3 #define _LINUX_HELPER_MACROS_H_ 4 5 #include <linux/math.h> 6 7 #define __find_closest(x, a, as, op) \ 8 ({ \ 9 typeof(as) __fc_i, __fc_as = (as) - 1; \ 10 typeof(x) __fc_x = (x); \ 11 typeof(*a) const *__fc_a = (a); \ 12 for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ 13 if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \ 14 __fc_a[__fc_i + 1], 2)) \ 15 break; \ 16 } \ 17 (__fc_i); \ 18 }) 19 20 /** 21 * find_closest - locate the closest element in a sorted array 22 * @x: The reference value. 23 * @a: The array in which to look for the closest element. Must be sorted 24 * in ascending order. 25 * @as: Size of 'a'. 26 * 27 * Returns the index of the element closest to 'x'. 28 */ 29 #define find_closest(x, a, as) __find_closest(x, a, as, <=) 30 31 /** 32 * find_closest_descending - locate the closest element in a sorted array 33 * @x: The reference value. 34 * @a: The array in which to look for the closest element. Must be sorted 35 * in descending order. 36 * @as: Size of 'a'. 37 * 38 * Similar to find_closest() but 'a' is expected to be sorted in descending 39 * order. 40 */ 41 #define find_closest_descending(x, a, as) __find_closest(x, a, as, >=) 42 43 /** 44 * is_insidevar - check if the @ptr points inside the @var memory range. 45 * @ptr: the pointer to a memory address. 46 * @var: the variable which address and size identify the memory range. 47 * 48 * Evaluates to true if the address in @ptr lies within the memory 49 * range allocated to @var. 50 */ 51 #define is_insidevar(ptr, var) \ 52 ((uintptr_t)(ptr) >= (uintptr_t)(var) && \ 53 (uintptr_t)(ptr) < (uintptr_t)(var) + sizeof(var)) 54 55 #endif 56