Dealing with wrap-around in unsigned differences

Discussion in 'C Programming' started by Noob, Aug 24, 2011.

  1. Noob

    Noob Guest

    Hello,

    I've come across the following macro:

    /** Get the absolute difference between 2 u32_t values (correcting overflows)
    * 'a' is expected to be 'higher' (without overflow) than 'b'. */
    #define FOO_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1)))

    (u32_t is equivalent to uint32_t)

    In my opinion, the entire macro reduces to ((a)-(b)) since
    ((b) ^ 0xFFFFFFFF) + 1 is always equal to -b (since uint32_t
    arithmetic is carried out modulo 2^32).

    Do you agree that the macro can be simplified, with no loss
    in portability whatsoever?

    I wrote a small program to try to illustrate my point.

    #include <stdio.h>
    int main(void)
    {
    volatile unsigned b = 0;
    do
    {
    unsigned v1 = (b ^ 0xFFFFFFFF) + 1;
    unsigned v2 = -b;
    if (v1 != v2) printf("b=%u v1=%u v2=%u\n", b, v1, v2);
    }
    while (++b != 0);
    return 0;
    }

    My compiler generates the same instruction to compute
    v1 and v2.

    Regards.
    Noob, Aug 24, 2011
    #1
    1. Advertising

  2. On 8/24/11 8:35 AM, Noob wrote:
    > Hello,
    >
    > I've come across the following macro:
    >
    > /** Get the absolute difference between 2 u32_t values (correcting overflows)
    > * 'a' is expected to be 'higher' (without overflow) than 'b'. */
    > #define FOO_U32_DIFF(a, b) (((a)>= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1)))
    >
    > (u32_t is equivalent to uint32_t)
    >
    > In my opinion, the entire macro reduces to ((a)-(b)) since
    > ((b) ^ 0xFFFFFFFF) + 1 is always equal to -b (since uint32_t
    > arithmetic is carried out modulo 2^32).
    >
    > Do you agree that the macro can be simplified, with no loss
    > in portability whatsoever?
    >


    My guess is that this is code to emulate uint32_t on a machine that
    doesn't have a proper uint32_t, or may not be of type uint32_t. (perhaps
    u32 is an 36 or 64 bit unsigned, as that is as close as the platform
    provides, but they needed exact emulation for this result.
    Richard Damon, Aug 24, 2011
    #2
    1. Advertising

  3. Noob <r...@127.0.0.1> wrote:
    > I've come across the following macro:
    >
    > /** Get the absolute difference between 2 u32_t values
    > (correcting overflows) * 'a' is expected to be 'higher'
    > (without overflow) than 'b'. */


    Expected, but not required apparently! Is it really meant
    to get the _absolute_ difference?

    > #define FOO_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b))
    > : (((a) + ((b) ^ 0xFFFFFFFF) + 1)))
    >
    > (u32_t is equivalent to uint32_t)
    >
    > In my opinion, the entire macro reduces to ((a)-(b)) since
    > ((b) ^ 0xFFFFFFFF) + 1 is always equal to -b (since uint32_t
    > arithmetic is carried out modulo 2^32).


    You're assuming uint32_t doesn't promote to int. The macro
    can be written as...

    #define FOO_U32_DIFF(a, b) ( (u32_t) ((a) - (b)) )

    Assuming u32_t is an unsigned type.

    > Do you agree that the macro can be simplified, with no loss
    > in portability whatsoever?


    It all hinges on what exactly u32_t is, or rather could be.
    I'm guessing it's set up with some conditional preprocessing.

    Perhaps it's really more like uint_least32_t, in which case
    the macro may not work when b == 0 anyway. If it is meant to
    mimic uint32_t, but may be wider, then the following may be
    better:

    #define FOO_U32_DIFF(a, b) \
    ( (u32_t) ((0ul + (a) - (b)) & 0xFFFFFFFFul) )

    --
    Peter
    Peter Nilsson, Aug 24, 2011
    #3
  4. Noob

    Jorgen Grahn Guest

    On Wed, 2011-08-24, Richard Damon wrote:
    ....
    > My guess is that this is code to emulate uint32_t on a machine that
    > doesn't have a proper uint32_t, or may not be of type uint32_t. (perhaps
    > u32 is an 36 or 64 bit unsigned, as that is as close as the platform
    > provides, but they needed exact emulation for this result.


    What do you mean by "may not be of type uint32_t"?

    Surely, uint32_t has to be exactly 32 bits if your environment
    provides it? There's uint_least32_t for the other cases.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Aug 27, 2011
    #4
  5. Noob

    Jorgen Grahn Guest

    On Wed, 2011-08-24, Noob wrote:
    > Hello,
    >
    > I've come across the following macro:
    >
    > /** Get the absolute difference between 2 u32_t values (correcting overflows)
    > * 'a' is expected to be 'higher' (without overflow) than 'b'. */
    > #define FOO_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1)))
    >
    > (u32_t is equivalent to uint32_t)
    >
    > In my opinion, the entire macro reduces to ((a)-(b)) since
    > ((b) ^ 0xFFFFFFFF) + 1 is always equal to -b (since uint32_t
    > arithmetic is carried out modulo 2^32).
    >
    > Do you agree that the macro can be simplified, with no loss
    > in portability whatsoever?


    I don't know, but I'd definitely make it an (inline) function, to avoid
    driving people crazy. This isn't the 1980s.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Aug 27, 2011
    #5
  6. On 8/27/11 2:14 PM, Jorgen Grahn wrote:
    > On Wed, 2011-08-24, Richard Damon wrote:
    > ...
    >> My guess is that this is code to emulate uint32_t on a machine that
    >> doesn't have a proper uint32_t, or may not be of type uint32_t. (perhaps
    >> u32 is an 36 or 64 bit unsigned, as that is as close as the platform
    >> provides, but they needed exact emulation for this result.

    >
    > What do you mean by "may not be of type uint32_t"?
    >
    > Surely, uint32_t has to be exactly 32 bits if your environment
    > provides it? There's uint_least32_t for the other cases.
    >
    > /Jorgen
    >


    The code calls the type U32, not uint32_t. It also is a macro so we
    don't really know what type the parameters are.

    If the type IS uint32_t, the extra complication should not be needed, so
    my assumption is that the programmer didn't want to assume that this is
    what he had, but did want the results as if he had them.
    Richard Damon, Aug 28, 2011
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Aaron Fude

    To wrap or not to wrap?

    Aaron Fude, May 8, 2008, in forum: Java
    Replies:
    12
    Views:
    686
    Chronic Philharmonic
    May 10, 2008
  2. Home_Job_opportunity
    Replies:
    0
    Views:
    483
    Home_Job_opportunity
    Jan 8, 2009
  3. pozz
    Replies:
    12
    Views:
    722
    Tim Rentsch
    Mar 20, 2011
  4. Art Werschulz

    Text::Wrap::wrap difference

    Art Werschulz, Sep 22, 2003, in forum: Perl Misc
    Replies:
    0
    Views:
    220
    Art Werschulz
    Sep 22, 2003
  5. Art Werschulz

    Text::Wrap::wrap difference

    Art Werschulz, Sep 24, 2003, in forum: Perl Misc
    Replies:
    1
    Views:
    233
    Anno Siegel
    Sep 25, 2003
Loading...

Share This Page