Re: [PATCH v4 07/13] minmax: Introduce {min,max}_array()

From: Andy Shevchenko
Date: Wed Jun 14 2023 - 18:06:23 EST


On Wed, Jun 14, 2023 at 11:34 PM Herve Codina <herve.codina@xxxxxxxxxxx> wrote:
> On Wed, 14 Jun 2023 14:51:43 +0300
> Andy Shevchenko <andy.shevchenko@xxxxxxxxx> wrote:
> > On Wed, Jun 14, 2023 at 12:42 PM Herve Codina <herve.codina@xxxxxxxxxxx> wrote:
> > > On Wed, 14 Jun 2023 12:02:57 +0300
> > > Andy Shevchenko <andy.shevchenko@xxxxxxxxx> wrote:
> > > > On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@xxxxxxxxxxx> wrote:

...

> > > > > + typeof(__array[0] + 0) __element = __array[--__len]; \
> > > >
> > > > Do we need the ' + 0' part?
> > >
> > > Yes.
> > >
> > > __array can be an array of const items and it is legitimate to get the
> > > minimum value from const items.
> > >
> > > typeof(__array[0]) keeps the const qualifier but we need to assign __element
> > > in the loop.
> > > One way to drop the const qualifier is to get the type from a rvalue computed
> > > from __array[0]. This rvalue has to have the exact same type with only the const
> > > dropped.
> > > '__array[0] + 0' was a perfect canditate.
> >
> > Seems like this also deserves a comment. But if the series is accepted
> > as is, it may be done as a follow up.
> >
>
> Finally not so simple ...
> I did some deeper tests and the macros need to be fixed.
>
> I hope this one (with comments added) is correct:
> --- 8 ---
> /*
> * Do not check the array parameter using __must_be_array().
> * In the following legit use-case where the "array" passed is a simple pointer,
> * __must_be_array() will return a failure.
> * --- 8< ---
> * int *buff
> * ...
> * min = min_array(buff, nb_items);
> * --- 8< ---
> *
> * The first typeof(&(array)[0]) is needed in order to support arrays of both
> * 'int *buff' and 'int buf[N]' types.
> *
> * typeof(__array[0] + 0) used for __element is needed as the array can be an
> * array of const items.
> * In order to discard the const qualifier use an arithmetic operation (rvalue).


> * This arithmetic operation discard the const but also can lead to an integer

discards

> * promotion. For instance, a const s8 __array[0] lead to an int __element due

leads

> * to the promotion.
> * In this case, simple min() or max() operation fails (type mismatch).
> * Use min_t() or max_t() (op_t parameter) enforcing the type in order to avoid
> * the min() or max() failure.

This part perhaps can be avoided. See below.

> */
> #define __minmax_array(op_t, array, len) ({ \
> typeof(&(array)[0]) __array = (array); \
> typeof(len) __len = (len); \
> typeof(__array[0] + 0) __element = __array[--__len]; \
> while (__len--) \
> __element = op_t(typeof(__array[0]), __element, __array[__len]); \

But can't we instead have typeof(+(array[0])) in the definition of __element?
There are also other possible solutions: a) _Generic() with listed
const types to move them to non-const, and b) __auto_type (which is
supported by GCC 4.9 and clang, but not in the C11 standard).

> __element; })

...

> Can you give me your feedback on this last version ?

Sure!

> If you are ok, it will be present in the next iteration of the series.
> Otherwise, as a last ressort, I will drop the {min,max}_array() and switch
> back to the specific min/max computation in IIO inkern.c
>
> Sorry for this back and forth and this last minute detected bug.

It's good that we have some tests (perhaps you can add something to
unit test these)? Perhaps move your code to lib/test_minmax.c as KUnit
module?

--
With Best Regards,
Andy Shevchenko