Date: Fri, 25 Oct 2013 17:57:04 -0700

On 10/25/13, Richard Smith <richardsmith_at_[hidden]> wrote:

> On Oct 25, 2013, Gabriel Dos Reis <gdr_at_[hidden]>wrote:

> > Matt Austern <austern_at_[hidden]> writes:

> > > On Oct 25, 2013, Jeffrey Yasskin <jyasskin_at_[hidden]> wrote:

> > > > Richard explicitly asked whether any such C++ users exist or

> > > > are likely to exist in the future, and nobody's come up with

> > > > any examples. So we appear to have a choice between helping

> > > > some theoretical people or helping some actual people. (We

> > > > help the actual people by telling them what to expect in the

> > > > standard, while now they have to test and hope they find the

> > > > right subset of undefined or implementation-defined behavior

> > > > that's actually guaranteed to work.)

> > >

> > > It's actually a little worse than that. Testing can reveal

> > > what your implementation does today, with your particular

> > > input, with one set of compiler flags. No amount of testing

> > > can reveal what guarantees your implementation makes.

> >

> > There are two separate issues here:

> >

> > (1) whether we want C++ to continue to support non-two's

> > complement binary representation

> > (2) what we want to say about overflowing shift arithmetic

> >

> > Requirint two's complement does not necessarily solve (2). And

> > solving (2) does not necessarily imply "no" to (1).

>

> Agreed. It would definitely be interesting to complete Jeffrey's

> list of the things we could define if we standardized 2s

> complement, and then investigate how many of these we are

> comfortable defining without specifying 2s complement. So far, we

> have:

>

> 1) overflowing unsigned->signed conversions

> 2) right-shifts on negative operands

> 3) bitwise operators

>

> Are there others?

While we are on this topic, we should list that defining a

two's complement representation will exclude using 1000... as

a trap value. I think that is the right decision once you have

bitwise operators, because -1^INT_MAX yields the bit pattern.

> (1) and (2) are currently implementation-defined;

(1) is almost always the inverse of signed->unsigned conversion.

However, I am not excited about either. I want a run-time

diagnosis when I convert a negative number to unsigned or when

I overflow a signed number when converting from unsigned. This

diagnosis could happen from a new conversion operator, e.g.

checked_cast<unsigned int>(-3).

> (3) seems underspecified in the current standard.

I have yet to use a machine in which s>>n was not implemented

as floor(s/pow(2,n)), but then I've been using two's complement

machines.

> [I think for consistency we should at least make (3) say that

> bitwise operators on positive operands act as "expected" (that

> is, they give the result that a 2s complement, 1s complement

> or sign-magnitude machine would), and we should make these

> operations on other machines implementation-defined.

I think we need a definition more specific than "expected". :)

> More generally, we should at least say that each integral type

> must be one of 1s complement, 2s complement or sign-magnitude.

> C currently requires this (C99/C11 6.2.6.2/2), but C++ does not

> (3.9.1/7's list of representations is not normative and not

> restrictive). 7.2/8 implies that we don't support other

> representations, but there's no normative justification for this

> assumption.]

>

> If we require that either (1) or (3) acts as-if 2s complement,

> that actually rules out 1s complement and sign-magnitude

> representations, because these expressions compute a value that

> does not exist in the other representations (-2147483648 for a

> 32-bit integer):

>

> int(unsigned(INT_MAX) + 1) // for (1)

> int(-1 ^ INT_MAX) // for (3)

>

> We could define that (2) acts as-if 2s complement (divide by 2^N

> and round down). I think that's the least valuable operation to

> define of the three, though.

> On Oct 25, 2013, Gabriel Dos Reis <gdr_at_[hidden]>wrote:

> > Matt Austern <austern_at_[hidden]> writes:

> > > On Oct 25, 2013, Jeffrey Yasskin <jyasskin_at_[hidden]> wrote:

> > > > Richard explicitly asked whether any such C++ users exist or

> > > > are likely to exist in the future, and nobody's come up with

> > > > any examples. So we appear to have a choice between helping

> > > > some theoretical people or helping some actual people. (We

> > > > help the actual people by telling them what to expect in the

> > > > standard, while now they have to test and hope they find the

> > > > right subset of undefined or implementation-defined behavior

> > > > that's actually guaranteed to work.)

> > >

> > > It's actually a little worse than that. Testing can reveal

> > > what your implementation does today, with your particular

> > > input, with one set of compiler flags. No amount of testing

> > > can reveal what guarantees your implementation makes.

> >

> > There are two separate issues here:

> >

> > (1) whether we want C++ to continue to support non-two's

> > complement binary representation

> > (2) what we want to say about overflowing shift arithmetic

> >

> > Requirint two's complement does not necessarily solve (2). And

> > solving (2) does not necessarily imply "no" to (1).

>

> Agreed. It would definitely be interesting to complete Jeffrey's

> list of the things we could define if we standardized 2s

> complement, and then investigate how many of these we are

> comfortable defining without specifying 2s complement. So far, we

> have:

>

> 1) overflowing unsigned->signed conversions

> 2) right-shifts on negative operands

> 3) bitwise operators

>

> Are there others?

While we are on this topic, we should list that defining a

two's complement representation will exclude using 1000... as

a trap value. I think that is the right decision once you have

bitwise operators, because -1^INT_MAX yields the bit pattern.

> (1) and (2) are currently implementation-defined;

(1) is almost always the inverse of signed->unsigned conversion.

However, I am not excited about either. I want a run-time

diagnosis when I convert a negative number to unsigned or when

I overflow a signed number when converting from unsigned. This

diagnosis could happen from a new conversion operator, e.g.

checked_cast<unsigned int>(-3).

> (3) seems underspecified in the current standard.

I have yet to use a machine in which s>>n was not implemented

as floor(s/pow(2,n)), but then I've been using two's complement

machines.

> [I think for consistency we should at least make (3) say that

> bitwise operators on positive operands act as "expected" (that

> is, they give the result that a 2s complement, 1s complement

> or sign-magnitude machine would), and we should make these

> operations on other machines implementation-defined.

I think we need a definition more specific than "expected". :)

> More generally, we should at least say that each integral type

> must be one of 1s complement, 2s complement or sign-magnitude.

> C currently requires this (C99/C11 6.2.6.2/2), but C++ does not

> (3.9.1/7's list of representations is not normative and not

> restrictive). 7.2/8 implies that we don't support other

> representations, but there's no normative justification for this

> assumption.]

>

> If we require that either (1) or (3) acts as-if 2s complement,

> that actually rules out 1s complement and sign-magnitude

> representations, because these expressions compute a value that

> does not exist in the other representations (-2147483648 for a

> 32-bit integer):

>

> int(unsigned(INT_MAX) + 1) // for (1)

> int(-1 ^ INT_MAX) // for (3)

>

> We could define that (2) acts as-if 2s complement (divide by 2^N

> and round down). I think that's the least valuable operation to

> define of the three, though.

-- Lawrence Crowl

Received on 2013-10-26 02:57:07