new file mode 100644
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Find closest element functions
+ */
+#ifndef _LINUX_FIND_CLOSEST_H_
+#define _LINUX_FIND_CLOSEST_H_
+
+#include <linux/types.h>
+
+unsigned int find_closest(int x, const int *a, unsigned int as);
+unsigned int find_closest_descending(int x, const int *a, unsigned int as);
+
+#endif /* _LINUX_FIND_CLOSEST_H_ */
@@ -3,66 +3,7 @@
#define _LINUX_HELPER_MACROS_H_
#include <linux/math.h>
-
-/**
- * find_closest - locate the closest element in a sorted array
- * @x: The reference value.
- * @a: The array in which to look for the closest element. Must be sorted
- * in ascending order.
- * @as: Size of 'a'.
- *
- * Returns the index of the element closest to 'x'.
- * Note: If using an array of negative numbers (or mixed positive numbers),
- * then be sure that 'x' is of a signed-type to get good results.
- */
-#define find_closest(x, a, as) \
-({ \
- typeof(as) __fc_i, __fc_as = (as) - 1; \
- long __fc_mid_x, __fc_x = (x); \
- long __fc_left, __fc_right; \
- typeof(*a) const *__fc_a = (a); \
- for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \
- __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i + 1]) / 2; \
- if (__fc_x <= __fc_mid_x) { \
- __fc_left = __fc_x - __fc_a[__fc_i]; \
- __fc_right = __fc_a[__fc_i + 1] - __fc_x; \
- if (__fc_right < __fc_left) \
- __fc_i++; \
- break; \
- } \
- } \
- (__fc_i); \
-})
-
-/**
- * find_closest_descending - locate the closest element in a sorted array
- * @x: The reference value.
- * @a: The array in which to look for the closest element. Must be sorted
- * in descending order.
- * @as: Size of 'a'.
- *
- * Similar to find_closest() but 'a' is expected to be sorted in descending
- * order. The iteration is done in reverse order, so that the comparison
- * of '__fc_right' & '__fc_left' also works for unsigned numbers.
- */
-#define find_closest_descending(x, a, as) \
-({ \
- typeof(as) __fc_i, __fc_as = (as) - 1; \
- long __fc_mid_x, __fc_x = (x); \
- long __fc_left, __fc_right; \
- typeof(*a) const *__fc_a = (a); \
- for (__fc_i = __fc_as; __fc_i >= 1; __fc_i--) { \
- __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i - 1]) / 2; \
- if (__fc_x <= __fc_mid_x) { \
- __fc_left = __fc_x - __fc_a[__fc_i]; \
- __fc_right = __fc_a[__fc_i - 1] - __fc_x; \
- if (__fc_right < __fc_left) \
- __fc_i--; \
- break; \
- } \
- } \
- (__fc_i); \
-})
+#include <linux/find_closest.h>
/**
* is_insidevar - check if the @ptr points inside the @var memory range.
@@ -35,7 +35,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
nmi_backtrace.o win_minmax.o memcat_p.o \
- buildid.o objpool.o iomem_copy.o
+ buildid.o objpool.o iomem_copy.o find_closest.o
lib-$(CONFIG_UNION_FIND) += union_find.o
lib-$(CONFIG_PRINTK) += dump_stack.o
new file mode 100644
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Find closest element functions
+ *
+ * Based on previous util_macros.h implementation
+ */
+
+#include <linux/find_closest.h>
+#include <linux/module.h>
+
+/**
+ * find_closest - locate the closest element in a sorted array
+ * @x: The reference value.
+ * @a: The array in which to look for the closest element. Must be sorted
+ * in ascending order.
+ * @as: Size of 'a'.
+ *
+ * Returns the index of the element closest to 'x'.
+ */
+unsigned int find_closest(int x, const int *a, unsigned int as)
+{
+ unsigned int array_size = as - 1;
+ int mid_x, left, right;
+ unsigned int i;
+
+ for (i = 0; i < array_size; i++) {
+ mid_x = (a[i] + a[i + 1]) / 2;
+ if (x <= mid_x) {
+ left = x - a[i];
+ right = a[i + 1] - x;
+ if (right < left)
+ i++;
+ break;
+ }
+ }
+
+ return i;
+}
+EXPORT_SYMBOL_GPL(find_closest);
+
+/**
+ * find_closest_descending - locate the closest element in a sorted array
+ * @x: The reference value.
+ * @a: The array in which to look for the closest element. Must be sorted
+ * in descending order.
+ * @as: Size of 'a'.
+ *
+ * Similar to find_closest() but 'a' is expected to be sorted in descending
+ * order. The iteration is done in reverse order, so that the comparison
+ * of 'right' & 'left' also works for unsigned numbers.
+ */
+unsigned int find_closest_descending(int x, const int *a, unsigned int as)
+{
+ unsigned int array_size = as - 1;
+ int mid_x, left, right;
+ unsigned int i;
+
+ for (i = array_size; i >= 1; i--) {
+ mid_x = (a[i] + a[i - 1]) / 2;
+ if (x <= mid_x) {
+ left = x - a[i];
+ right = a[i - 1] - x;
+ if (right < left)
+ i--;
+ break;
+ }
+ }
+
+ return i;
+}
+EXPORT_SYMBOL_GPL(find_closest_descending);
Move the utility macros find_closest() and find_closest_descending() from inline macros to proper library functions in lib/. Signed-off-by: Alexandru Soponar <asoponar@taladin.ro> --- include/linux/find_closest.h | 13 +++++++ include/linux/util_macros.h | 61 +------------------------------ lib/Makefile | 2 +- lib/find_closest.c | 71 ++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 61 deletions(-) create mode 100644 include/linux/find_closest.h create mode 100644 lib/find_closest.c