RE: [PATCH v3 1/5] math64: New DIV_U64_ROUND_CLOSEST helper

From: David Laight
Date: Sat Jul 24 2021 - 07:38:21 EST


From: Pali Rohár
> Sent: 22 July 2021 22:58
>
> On Monday 19 July 2021 15:47:07 Andy Shevchenko wrote:
> > On Sat, Jul 17, 2021 at 3:39 PM Pali Rohár <pali@xxxxxxxxxx> wrote:
> > >
> > > Provide DIV_U64_ROUND_CLOSEST helper which uses div_u64 to perform
> > > division rounded to the closest integer using unsigned 64bit
> > > dividend and unsigned 32bit divisor.
> >
> > ...
> >
> > > +/*
> > > + * DIV_U64_ROUND_CLOSEST - unsigned 64bit divide with 32bit divisor rounded to nearest integer
> >
> > > + * @dividend: unsigned 64bit dividend
> >
> > Here you insist users to provide a u64 (or compatible) type.
> >
> > > + * @divisor: unsigned 32bit divisor
> > > + *
> > > + * Divide unsigned 64bit dividend by unsigned 32bit divisor
> > > + * and round to closest integer.
> > > + *
> > > + * Return: dividend / divisor rounded to nearest integer
> > > + */
> > > +#define DIV_U64_ROUND_CLOSEST(dividend, divisor) \
> >
> > > + ({ u32 _tmp = (divisor); div_u64((u64)(dividend) + _tmp / 2, _tmp); })
> >
> > Here is the casting to u64. Why? (Yes, I have read v1 discussion and I
> > just want to continue it here).
>
> See also Willy's response: https://lore.kernel.org/lkml/20210625155008.GB16901@xxxxxx/
>
> Macro does not enforce type as opposite to function.
>
> There is no compile time check for correct type and neither compile time
> warning if smaller typed value is passed.
>
> And e.g. passing constant with explicit ULL suffix or casting external
> constant to 64bit type is impractical.

What is wrong with:
({ u32 _tmp = (divisor); div_u64((dividend) + (u64)0 + _tmp / 2, _tmp); })
Or:
({ u32 _tmp = (divisor); div_u64((dividend) + (u64)(_tmp / 2), _tmp); })
Both will ensure a 32bit 'dividend' is promoted to 64 bits before the '+'.
Both will fail if 'dividend' isn't an integer type.
On 32bit systems the compiler will also know when the high bits van be ignored.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)