diff mbox series

[v2,01/10] utils_macro: introduce find_closest_unsorted()

Message ID 20211028101840.24632-2-andrea.merello@gmail.com (mailing list archive)
State Changes Requested
Headers show
Series Add support for Bosch BNO055 IMU | expand

Commit Message

Andrea Merello Oct. 28, 2021, 10:18 a.m. UTC
This is similar to find_closest() and find_closest_descending(), but, it
doesn't make any assumption about the array being ordered.

Signed-off-by: Andrea Merello <andrea.merello@iit.it>
---
 include/linux/util_macros.h | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

Comments

Andy Shevchenko Oct. 28, 2021, 10:25 a.m. UTC | #1
On Thu, Oct 28, 2021 at 1:18 PM Andrea Merello <andrea.merello@gmail.com> wrote:
>
> This is similar to find_closest() and find_closest_descending(), but, it
> doesn't make any assumption about the array being ordered.

Macros in general are not so welcoming.
Why do you do it as a macro?

...

> +#include <linux/math.h>

Wondering if the current header misses other inclusions it's a direct user of.

...

> +/**
> + * find_closest_unsorted - locate the closest element in a unsorted array

an

> + * @x: The reference value.
> + * @a: The array in which to look for the closest element.
> + * @as: Size of 'a'.
> + *
> + * Similar to find_closest() but 'a' has no requirement to being sorted
> + */
Andrea Merello Nov. 8, 2021, 11:05 a.m. UTC | #2
Il giorno gio 28 ott 2021 alle ore 12:26 Andy Shevchenko
<andy.shevchenko@gmail.com> ha scritto:
>
> On Thu, Oct 28, 2021 at 1:18 PM Andrea Merello <andrea.merello@gmail.com> wrote:
> >
> > This is similar to find_closest() and find_closest_descending(), but, it
> > doesn't make any assumption about the array being ordered.
>
> Macros in general are not so welcoming.
> Why do you do it as a macro?

Honestly, I did that just because find_closest() and
find_closest_descending() are macros (i.e. to be consistent wrt them).
I see no drawbacks in making this a regular function indeed; just, do
you have any advice about where should it live?

> ...
>
> > +#include <linux/math.h>
>
> Wondering if the current header misses other inclusions it's a direct user of.

Looking at it, it seems that also __find_closest() actually needs
math.h because it (apparently incorrectly[*]) uses
DIV_ROUND_CLOSEST()..

[*]Indeed it seems there is another issue here about find_closest():
for example it picks the 1st element while searching for "2" in an
array like this: {1,2,..} ..This needs to be reported/fixed..



> ...
>
> > +/**
> > + * find_closest_unsorted - locate the closest element in a unsorted array
>
> an
>
> > + * @x: The reference value.
> > + * @a: The array in which to look for the closest element.
> > + * @as: Size of 'a'.
> > + *
> > + * Similar to find_closest() but 'a' has no requirement to being sorted
> > + */
>
> --
> With Best Regards,
> Andy Shevchenko
diff mbox series

Patch

diff --git a/include/linux/util_macros.h b/include/linux/util_macros.h
index 72299f261b25..b48f80ceb380 100644
--- a/include/linux/util_macros.h
+++ b/include/linux/util_macros.h
@@ -2,6 +2,8 @@ 
 #ifndef _LINUX_HELPER_MACROS_H_
 #define _LINUX_HELPER_MACROS_H_
 
+#include <linux/math.h>
+
 #define __find_closest(x, a, as, op)					\
 ({									\
 	typeof(as) __fc_i, __fc_as = (as) - 1;				\
@@ -38,4 +40,28 @@ 
  */
 #define find_closest_descending(x, a, as) __find_closest(x, a, as, >=)
 
+/**
+ * find_closest_unsorted - locate the closest element in a unsorted array
+ * @x: The reference value.
+ * @a: The array in which to look for the closest element.
+ * @as: Size of 'a'.
+ *
+ * Similar to find_closest() but 'a' has no requirement to being sorted
+ */
+#define find_closest_unsorted(x, a, as)					\
+({									\
+	typeof(x) __fc_best_delta, __fc_delta;				\
+	typeof(as) __fc_i, __fc_best_idx;				\
+	bool __fc_first = true;						\
+	for (__fc_i = 0; __fc_i < (as); __fc_i++) {			\
+		__fc_delta = abs(a[__fc_i] - (x));			\
+		if (__fc_first || __fc_delta < __fc_best_delta) {	\
+			__fc_best_delta = __fc_delta;			\
+			__fc_best_idx = __fc_i;				\
+		}							\
+		__fc_first = false;					\
+	}								\
+	(__fc_best_idx);						\
+})
+
 #endif