On Fri, May 17, 2024 at 3:06 PM Chet Ramey <chet.ra...@case.edu> wrote:
>
> On 5/17/24 12:57 PM, Grisha Levit wrote:
> > The current cmp implementation for size and blocks subtracts the two
> > values and returns the difference as an int. This subtraction can
> > overflow, and the returned int can end up having the wrong sign.
> >
> > This also makes the qsort comparison function non-transitive. (Some
> > interesting discussion on that at [1]).
>
> Thanks for the report. If overflow is a concern, then a guaranteed
> transitive comparison function is the right thing. Your solution is clever,
> but a little obscure; I think I'll make it look more like the other
> comparison functions.

FWIW, I was copying the approach from coreutils[1] and gnulib[2]:

/* _GL_CMP (n1, n2) performs a three-valued comparison on n1 vs. n2, where
   n1 and n2 are expressions without side effects, that evaluate to real
   numbers (excluding NaN).
   It returns
     1  if n1 > n2
     0  if n1 == n2
     -1 if n1 < n2
   The naïve code   (n1 > n2 ? 1 : n1 < n2 ? -1 : 0)  produces a conditional
   jump with nearly all GCC versions up to GCC 10.
   This variant     (n1 < n2 ? -1 : n1 > n2)  produces a conditional with many
   GCC versions up to GCC 9.
   The better code  (n1 > n2) - (n1 < n2)  from Hacker's Delight § 2-9
   avoids conditional jumps in all GCC versions >= 3.4.  */
#define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2)))


[1]: https://git.gnu.org/cgit/coreutils.git/tree/src/ls.c?h=v9.5#n3899
[2]: https://git.gnu.org/cgit/gnulib.git/tree/m4/gnulib-common.m4?h=v1.0#n622

Reply via email to