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.
More information about the gmp-devel