Velocity Reviews > Unary minus and bitwise complement

# Unary minus and bitwise complement

James Kuyper
Guest
Posts: n/a

 03-21-2013
On 03/21/2013 08:13 AM, China Blue Clay wrote:
> In article <kiesa8\$mis\$(E-Mail Removed)>, Noob <root@127.0.0.1> wrote:
>
>> The "signedness" of the variable does matter. The standard fully
>> specifies the behavior of the ~ operator for unsigned types:

>
> Deal with reality. A ones complement/signed magnitude machine is only going to
> have ones complement/signed magnitude adders, not that and twos complement
> adders. If C is intended to be implemented is twos complement only, that should
> be mentionned somewhere.

Two's complement is just as irrelevant to this issue as one's
complement. Unsigned math is required to be implemented without a sign
bit, as might be inferred from the name "unsigned", and that is, indeed
"mentioned somewhere" - specifically, 6.2.6.2p1. The distinction between
one's complement, two's complement, and sign-magnitude only applies only
to signed types, as described in 6.2.6.2p2. It's a useful coincidence
that adding 2's complement integers and an unsigned integers of the same
size can be done using the same adder, and that's part of the reason for
the popularity of 2's complement, but it's irrelevant to the question at
hand.

That's because, even on a platform with no native capability for
carrying out unsigned arithmetic, a conforming implementation of C is
required to emulate it. Any platform that allows implementation of C's
bit-wise operators has an instruction set powerful enough to permit such
emulation, though doing so would make unsigned types far slower than
signed ones. If emulated correctly, unsigned arithmetic will produce the
result specified in the OP's message, regardless of what representation
is used for signed integers.
--
James Kuyper

Noob
Guest
Posts: n/a

 03-21-2013
China Blue Clay wrote:

> Noob wrote:
>
>> The "signedness" of the variable does matter. The standard fully
>> specifies the behavior of the ~ operator for unsigned types:

>
> Deal with reality. A ones complement/signed magnitude machine is
> only going to have ones complement/signed magnitude adders, not
> that and twos complement adders.

All the architectures I am familiar with implement two's complement
arithmetic. Can you name a few (modern) architectures that implement
something different?

> If C is intended to be implemented is twos complement only,
> that should be mentioned somewhere.

As James mentioned, C99 "6.2.6.2 Integer types" seems relevant.

Regards.

James Kuyper
Guest
Posts: n/a

 03-21-2013
On 03/21/2013 08:39 AM, James Kuyper wrote:
....
> ... It's a useful coincidence
> that adding 2's complement integers and an unsigned integers of the same
> size can be done using the same adder, ...

It would be more accurate to say that 2's complement representation was
designed specifically to make that relationship work.

glen herrmannsfeldt
Guest
Posts: n/a

 03-21-2013
James Kuyper <(E-Mail Removed)> wrote:
> On 03/21/2013 08:13 AM, China Blue Clay wrote:

(snip)
>> Deal with reality. A ones complement/signed magnitude machine is only going to
>> have ones complement/signed magnitude adders, not that and twos complement
>> adders. If C is intended to be implemented is twos complement only, that should
>> be mentionned somewhere.

> Two's complement is just as irrelevant to this issue as one's
> complement. Unsigned math is required to be implemented without a sign
> bit, as might be inferred from the name "unsigned", and that is, indeed
> "mentioned somewhere" - specifically, 6.2.6.2p1. The distinction between
> one's complement, two's complement, and sign-magnitude only applies only
> to signed types, as described in 6.2.6.2p2. It's a useful coincidence
> that adding 2's complement integers and an unsigned integers of the same
> size can be done using the same adder, and that's part of the reason for
> the popularity of 2's complement, but it's irrelevant to the question at
> hand.

Note, though, that as someone mentioned, in the case of integer
promotion of smaller types, signed is still relevant.

> That's because, even on a platform with no native capability for
> carrying out unsigned arithmetic, a conforming implementation of C is
> required to emulate it. Any platform that allows implementation of C's
> bit-wise operators has an instruction set powerful enough to permit such
> emulation, though doing so would make unsigned types far slower than
> signed ones.

Maybe we really need a C implementation (probably C89) for the 7090.
At least in Fortran, the 7090 does 16 bit sign magnitude arithmetic
in 36 bit registers. I presume a C implementation would do the same.

The full 36 bits are used for floating point operations.

> If emulated correctly, unsigned arithmetic will produce the
> result specified in the OP's message, regardless of what
> representation is used for signed integers.

Again, except for promotion from smaller sizes.

-- glen

James Kuyper
Guest
Posts: n/a

 03-21-2013
On 03/21/2013 03:59 PM, glen herrmannsfeldt wrote:
> James Kuyper <(E-Mail Removed)> wrote:

....
>> Two's complement is just as irrelevant to this issue as one's
>> complement. Unsigned math is required to be implemented without a sign
>> bit, as might be inferred from the name "unsigned", and that is, indeed
>> "mentioned somewhere" - specifically, 6.2.6.2p1. The distinction between
>> one's complement, two's complement, and sign-magnitude only applies only
>> to signed types, as described in 6.2.6.2p2. It's a useful coincidence
>> that adding 2's complement integers and an unsigned integers of the same
>> size can be done using the same adder, and that's part of the reason for
>> the popularity of 2's complement, but it's irrelevant to the question at
>> hand.

>
> Note, though, that as someone mentioned, in the case of integer
> promotion of smaller types, signed is still relevant.

That was me, in the message I posted with the header
Date: Tue, 19 Mar 2013 12:10:49 -0400

....
>> If emulated correctly, unsigned arithmetic will produce the
>> result specified in the OP's message, regardless of what
>> representation is used for signed integers.

>
> Again, except for promotion from smaller sizes.

I pointed out that the result would be different (and representation
dependent) if an unsigned type with TYPE_MAX < INT_MAX were used, but
that wasn't a exception to OP's comments, since he was explicitly
limiting them to unsigned int, where that's not a possibility. I was
merely showing him the limits to the validity of his argument; it was a
valid argument, in the actual context where he used it.

glen herrmannsfeldt
Guest
Posts: n/a

 03-21-2013
James Kuyper <(E-Mail Removed)> wrote:

(snip, I wrote)
>> Again, except for promotion from smaller sizes.

> I pointed out that the result would be different (and representation
> dependent) if an unsigned type with TYPE_MAX < INT_MAX were used, but
> that wasn't a exception to OP's comments, since he was explicitly
> limiting them to unsigned int, where that's not a possibility. I was
> merely showing him the limits to the validity of his argument; it was a
> valid argument, in the actual context where he used it.

Still, someone could write it with int, someone comes along later
and changes it to short, then it fails.

OK, what are sizeof(short) and sizeof(int) on the Unisys machines?

The CDC ones complement machines are a little out of date now, but
it might be that someone still has one running. (There was a time where
someone would run some old machines one day a week to save on power
costs.)

As I noted, the 7090 likely would have a 16 bit C int type, and maybe
even a 16 bit C char. (As six isn't enough.) In that case, your comment
wouldn't apply.

-- glen

Phil Carmody
Guest
Posts: n/a

 03-21-2013
Lew Pitcher <(E-Mail Removed)> writes:
> On Tuesday 19 March 2013 10:49, in comp.lang.c, root@127.0.0.1 wrote:
>
> > Hello,
> >
> > Considering a properly initialized unsigned int variable v,
> > are -v and ~(v-1) equivalent for any value of v, even on
> > the DS9k?
> >
> > (let <-> mean "are equivalent for any value of v")
> >
> > According to C89 3.3.3.3
> > ~v <-> UINT_MAX - v
> >
> > Thus
> > ~(v-1) <-> UINT_MAX - (v-1)
> > ~(v-1) <-> UINT_MAX - v + 1
> > ~(v-1) <-> (UINT_MAX + 1) - v
> >
> > Adding (UINT_MAX + 1) to an unsigned int variable is a NOP,
> > thus ~(v-1) <-> -v

>
>
> First off, ~(v-1) is the canonical definition of 2's complement negation of
> a value v. Your analysis seems to preclude the C standard's requirement
> for "pure binary" representation of unsigned integers, and sign&magnitude
> and ones-complement representation for signed integers, by defining
> negation as a two's-complement operation. I'll have to spend some time
>
> ~(v-1) <-> -v
> no longer fits within the given parameters of unsigned integers, as there is
> no viable representation /as an unsigned integer/ of a negative value. If
> ~(v-1) <-> (UINT_MAX + 1) - v
> this would not be a problem, as neither side of this equation results in a
> negative value.

I'm not familiar with any architecture where for unsigned int v, -v results
in a negative value.

Phil
--
"In a world of magnets and miracles"
-- Insane Clown Posse, Miracles, 2009. Much derided.
"Magnets, how do they work"
-- Pink Floyd, High Hopes, 1994. Lauded as lyrical geniuses.

James Kuyper
Guest
Posts: n/a

 03-21-2013
On 03/21/2013 05:34 PM, glen herrmannsfeldt wrote:
....
> As I noted, the 7090 likely would have a 16 bit C int type, and maybe
> even a 16 bit C char. (As six isn't enough.) In that case, your comment
> wouldn't apply.

You're right - in that case there couldn't be any unsigned type with
TYPE_MAX < INT_MAX, which I explicitly noted as a precondition for the
applicability of my comment.

Phil Carmody
Guest
Posts: n/a

 03-21-2013
James Kuyper <(E-Mail Removed)> writes:
> On 03/21/2013 03:59 PM, glen herrmannsfeldt wrote:
> > James Kuyper <(E-Mail Removed)> wrote:

> ...
> >> Two's complement is just as irrelevant to this issue as one's
> >> complement. Unsigned math is required to be implemented without a sign
> >> bit, as might be inferred from the name "unsigned", and that is, indeed
> >> "mentioned somewhere" - specifically, 6.2.6.2p1. The distinction between
> >> one's complement, two's complement, and sign-magnitude only applies only
> >> to signed types, as described in 6.2.6.2p2. It's a useful coincidence
> >> that adding 2's complement integers and an unsigned integers of the same
> >> size can be done using the same adder, and that's part of the reason for
> >> the popularity of 2's complement, but it's irrelevant to the question at
> >> hand.

> >
> > Note, though, that as someone mentioned, in the case of integer
> > promotion of smaller types, signed is still relevant.

>
> That was me, in the message I posted with the header
> Date: Tue, 19 Mar 2013 12:10:49 -0400

Indeed, good catch for the generalisation of the question.
However, wouldn't a simple '1u' rather than '1' fix that case?

Phil
--
"In a world of magnets and miracles"
-- Insane Clown Posse, Miracles, 2009. Much derided.
"Magnets, how do they work"
-- Pink Floyd, High Hopes, 1994. Lauded as lyrical geniuses.

glen herrmannsfeldt
Guest
Posts: n/a

 03-21-2013
James Kuyper <(E-Mail Removed)> wrote:
> On 03/21/2013 05:34 PM, glen herrmannsfeldt wrote:
> ...
>> As I noted, the 7090 likely would have a 16 bit C int type, and maybe
>> even a 16 bit C char. (As six isn't enough.) In that case, your comment
>> wouldn't apply.

> You're right - in that case there couldn't be any unsigned type with
> TYPE_MAX < INT_MAX, which I explicitly noted as a precondition for the
> applicability of my comment.

As far as I know, there weren't any sign magnitude binary machines since
the 7094.

The S/360 fixed decimal form is sign magnitude, still supported in
current generation z/ machines. Not so useful for C, though.

There have been some machines using the same representation for integer
and floating point, the B5500 for example. With the appropriate
normalization and exponent representation it works.

Probably also no C compilers for them.

-- glen