ABS_CAST

Marc Glisse marc.glisse at inria.fr
Tue Mar 27 12:27:08 CEST 2012


On Tue, 27 Mar 2012, Niels Möller wrote:

> I had a look at the ABS_CAST macro introduced a while ago,
>
>  #define ABS_CAST(T,x) ((x) >= 0 ? (T)(x) : -((T)((x) + 1) - 1))
>
> As I understand it, the point is that, e.g.,
>
>  int x;
>  unsigned absx;
>  ...
>  absx =  ABS_CAST (unsigned, x);
>
> should give the right result for x = INT_MIN (where plain ABS would give
> the result INT_MIN). And be more portable than the simpler definition
>
>  #define ABS_CAST(T, x) ((T) ABS(x))

This would usually give the right result for INT_MIN, but some gcc-4.7 
optimizations manage to break it.

> But the current definition seems strange. When x < 0, it will cast the
> negative value to an unsigned type (which I suspect is not portable
> according to the C89 spec (maybe it's more well defined in C99?)), and
> I'm not sure what is gained by the extra +1 and -1 when doing that. I'd
> suggest using instead
>
>  #define ABS_CAST(T,x) ((x) >= 0 ? (T)(x) : (((T)(-((x) + 1))) + 1))
>
> Then in the case x < 0, first add 1, and note that both (x+1) and -(x+1)
> always fit in a signed int. Then negate, cast the resulting
> *non-negative* number to unsigned, and then an unsigned add of 1 to get
> the correct absolute value.
>
> Am I misunderstanding anything here?

Writing just -(T)(x) is safe, is what mpfr uses, and is what I had 
written. Torbjorn added the +1-1 for extra safety. I agree that your 
version is even safer.

-- 
Marc Glisse


More information about the gmp-devel mailing list