diff mbox series

[16/16] lib: move find_closest() and find_closest_descending() to lib functions

Message ID 20250515081332.151250-17-asoponar@taladin.ro
State New
Headers show
Series [01/16] hwmon: w83795: Fix type incompatibility with non-macro find_closest | expand

Commit Message

Alexandru Soponar May 15, 2025, 8:13 a.m. UTC
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
diff mbox series

Patch

diff --git a/include/linux/find_closest.h b/include/linux/find_closest.h
new file mode 100644
index 000000000000..28a5c4d0c768
--- /dev/null
+++ b/include/linux/find_closest.h
@@ -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_ */
diff --git a/include/linux/util_macros.h b/include/linux/util_macros.h
index 825487fb66fa..478d4821f2d1 100644
--- a/include/linux/util_macros.h
+++ b/include/linux/util_macros.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.
diff --git a/lib/Makefile b/lib/Makefile
index f1c6e9d76a7c..e8e738c9ced8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
diff --git a/lib/find_closest.c b/lib/find_closest.c
new file mode 100644
index 000000000000..d481625cae9d
--- /dev/null
+++ b/lib/find_closest.c
@@ -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);