Re: bitwise absolute value

Discussion in 'C Programming' started by Derk Gwen, Sep 10, 2003.

  1. Derk Gwen

    Derk Gwen Guest

    # That works, but it assumes 32 bit integers. Is there a
    # portable/standard way to do this? Or are ANSI integers

    assert(-1==~0); /*twos complement*/

    signx = x>>(sizeof x*CHAR_BIT)
    absx = (x ^ signx)-signx;

    --
    Derk Gwen http://derkgwen.250free.com/html/index.html
    Death is the worry of the living. The dead, like myself,
    only worry about decay and necrophiliacs.
     
    Derk Gwen, Sep 10, 2003
    #1
    1. Advertising

  2. Derk Gwen

    Kevin Easton Guest

    Derk Gwen <> wrote:
    > # That works, but it assumes 32 bit integers. Is there a
    > # portable/standard way to do this? Or are ANSI integers
    >
    > assert(-1==~0); /*twos complement*/
    >
    > signx = x>>(sizeof x*CHAR_BIT)
    > absx = (x ^ signx)-signx;


    That makes two assumptions, only one of which your assert() checks (the
    other is that >> fills using the sign bit).

    - Kevin.
     
    Kevin Easton, Sep 10, 2003
    #2
    1. Advertising

  3. Derk Gwen

    pete Guest

    Kevin Easton wrote:
    >
    > Derk Gwen <> wrote:
    > > # That works, but it assumes 32 bit integers. Is there a
    > > # portable/standard way to do this? Or are ANSI integers
    > >
    > > assert(-1==~0); /*twos complement*/
    > >
    > > signx = x>>(sizeof x*CHAR_BIT)
    > > absx = (x ^ signx)-signx;

    >
    > That makes two assumptions,
    > only one of which your assert() checks (the
    > other is that >> fills using the sign bit).


    It's not as good as that.
    x>>(sizeof x*CHAR_BIT) is shifted too far, and undefined behavior.
    No padding bits is also assumed.

    --
    pete
     
    pete, Sep 10, 2003
    #3
  4. On Wed, 10 Sep 2003, pete wrote:

    > > > assert(-1==~0); /*twos complement*/
    > > >
    > > > signx = x>>(sizeof x*CHAR_BIT)
    > > > absx = (x ^ signx)-signx;

    > >
    > > That makes two assumptions,
    > > only one of which your assert() checks (the
    > > other is that >> fills using the sign bit).

    >
    > It's not as good as that.
    > x>>(sizeof x*CHAR_BIT) is shifted too far, and undefined behavior.
    > No padding bits is also assumed.


    unsigned x_is_neg = (unsigned)x/(1u+-1u/2u);
    absx = ((unsigned)x ^ -x_is_neg)+x_is_neg;
     
    Jarno A Wuolijoki, Sep 10, 2003
    #4
  5. Derk Gwen

    Kevin Easton Guest

    pete <> wrote:
    > Kevin Easton wrote:
    >>
    >> Derk Gwen <> wrote:
    >> > # That works, but it assumes 32 bit integers. Is there a
    >> > # portable/standard way to do this? Or are ANSI integers
    >> >
    >> > assert(-1==~0); /*twos complement*/
    >> >
    >> > signx = x>>(sizeof x*CHAR_BIT)
    >> > absx = (x ^ signx)-signx;

    >>
    >> That makes two assumptions,
    >> only one of which your assert() checks (the
    >> other is that >> fills using the sign bit).

    >
    > It's not as good as that.
    > x>>(sizeof x*CHAR_BIT) is shifted too far, and undefined behavior.


    True.

    > No padding bits is also assumed.


    Padding bits are invisible to shifts (x >> 1 is always x / 2 for +ve x,
    regardless of padding bits). In general padding bits are only a concern
    when type punning is taking place.

    - Kevin.
     
    Kevin Easton, Sep 10, 2003
    #5
  6. On Wed, 10 Sep 2003, Kevin Easton wrote:
    >
    > pete <> wrote:
    > > Kevin Easton wrote:
    > >>
    > >> Derk Gwen <> wrote:
    > >> > # That works, but it assumes 32 bit integers. Is there a
    > >> > # portable/standard way to do this? Or are ANSI integers
    > >> >
    > >> > assert(-1==~0); /*twos complement*/
    > >> >
    > >> > signx = x>>(sizeof x*CHAR_BIT)
    > >> > absx = (x ^ signx)-signx;
    > >>
    > >> That makes two assumptions,
    > >> only one of which your assert() checks (the
    > >> other is that >> fills using the sign bit).

    > >
    > > It's not as good as that.
    > > x>>(sizeof x*CHAR_BIT) is shifted too far, and undefined behavior.
    > > No padding bits is also assumed.

    >
    > Padding bits are invisible to shifts (x >> 1 is always x / 2 for +ve x,
    > regardless of padding bits). In general padding bits are only a concern
    > when type punning is taking place.


    Yes, but in this case the number of padding bits affects *how far*
    we need to right-shift the value. If there are no padding bits,
    then the value of (sizeof x*CHAR_BIT) is correct. If there is one
    padding bit per byte, then we really need to shift by
    (sizeof x * (CHAR_BIT-1)); if there is one padding bit per integer,
    maybe as a parity bit, then we mean (sizeof x * CHAR_BIT - 1); and
    so on.

    (N869 sections 6.5.7#3, 6.2.6.2#4)

    -Arthur
     
    Arthur J. O'Dwyer, Sep 10, 2003
    #6
  7. Derk Gwen

    pete Guest

    Arthur J. O'Dwyer wrote:
    >
    > On Wed, 10 Sep 2003, Kevin Easton wrote:
    > >
    > > pete <> wrote:


    > > > x>>(sizeof x*CHAR_BIT) is shifted too far, and undefined behavior.


    > If there are no padding bits,
    > then the value of (sizeof x*CHAR_BIT) is correct.


    N869
    6.5.7 Bitwise shift operators
    [#3]

    The integer promotions are performed on each of the
    operands. The type of the result is that of the promoted
    left operand. If the value of the right operand is negative
    or is greater than or

    equal to the width of the promoted left operand,
    ^^^^^

    the behavior is undefined.

    --
    pete
     
    pete, Sep 11, 2003
    #7
  8. On Thu, 11 Sep 2003, pete wrote:
    >
    > Arthur J. O'Dwyer wrote:
    > > On Wed, 10 Sep 2003, Kevin Easton wrote:
    > > > pete <> wrote:

    >
    > > > > x>>(sizeof x*CHAR_BIT) is shifted too far, and undefined behavior.

    >
    > > If there are no padding bits,
    > > then the value of (sizeof x*CHAR_BIT) is correct.

    >
    > N869
    > 6.5.7 Bitwise shift operators
    > [#3]

    [re: sizeof x*CHAR_BIT is undefined behavior]

    Oh -- of course. Sorry. Subtract one from each of my examples;
    e.g., if there are no padding bits, then (sizeof x*CHAR_BIT)-1 is
    correct; if there's one padding bit per byte, then
    (sizeof x*(CHAR_BIT-1)-1 is correct; et cetera.

    -Arthur
     
    Arthur J. O'Dwyer, Sep 11, 2003
    #8
    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. Christopher Benson-Manica

    bitwise absolute value

    Christopher Benson-Manica, Sep 7, 2003, in forum: C Programming
    Replies:
    34
    Views:
    8,897
    Dan Pop
    Sep 11, 2003
  2. Chad
    Replies:
    9
    Views:
    352
    Coos Haak
    Jan 22, 2008
  3. John B. Matthews
    Replies:
    73
    Views:
    4,463
    John B. Matthews
    Nov 9, 2009
  4. Moe Sisko
    Replies:
    2
    Views:
    215
    Moe Sisko
    Jan 7, 2008
  5. James Byrne
    Replies:
    3
    Views:
    565
    James Byrne
    Sep 14, 2010
Loading...

Share This Page