Jump to page: 1 2
Thread overview
(int << ulong) == int ?
Aug 07, 2011
Dmitry Olshansky
Aug 07, 2011
Jonathan M Davis
Aug 07, 2011
Dmitry Olshansky
Aug 07, 2011
Jonathan M Davis
Aug 07, 2011
bearophile
Aug 07, 2011
Dmitry Olshansky
Aug 07, 2011
Brad Roberts
Aug 08, 2011
bearophile
Aug 09, 2011
Don
Aug 09, 2011
Jonathan M Davis
Aug 09, 2011
Don
Aug 09, 2011
Jonathan M Davis
August 07, 2011
Just lost the best part of an hour figuring the cause of this small problem, consider:

void main()
{
        uint j = 42;
        ulong k = 1<<cast(ulong)j;
        ulong m = 1UL<<j;
        assert(k == 1024);//both asserts do pass
        assert(m == (1UL<<42));
}

I though left operand should be promoted to the largest integer in shift expression, isn't it?

-- 
Dmitry Olshansky

August 07, 2011
On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote:
> Just lost the best part of an hour figuring the cause of this small problem, consider:
> 
> void main()
> {
>          uint j = 42;
>          ulong k = 1<<cast(ulong)j;
>          ulong m = 1UL<<j;
>          assert(k == 1024);//both asserts do pass
>          assert(m == (1UL<<42));
> }
> 
> I though left operand should be promoted to the largest integer in shift expression, isn't it?

I would not expect that type of integer being used to give the number of bits to shift to affect thet type of integer being shifted. It doesn't generally make much sense to shift more than the size of the integer type being shifted, and that can always fit in a byte. So, why would the type of the integer being used to give the number of bits to shift matter? It's like an index. The index doesn't affect the type of what's being indexed. It just gives you an index.

You have to deal with integer promotions and all that when doing arithmetic, because arithmetic needs to be done with a like number of bits on both sides of the operation. But with shifting, all your doing is asking it to shift some number of bits. The type which holds the number of bits shouldn't really matter. I wouldn't expect _any_ integer promotions to occur in a shift expression. If you want to affect what's being shifted, then cast what's being shifted.

- Jonathan M Davis
August 07, 2011
>
> You have to deal with integer promotions and all that when doing arithmetic,
> because arithmetic needs to be done with a like number of bits on both sides
> of the operation. But with shifting, all your doing is asking it to shift some
> number of bits. The type which holds the number of bits shouldn't really
> matter. I wouldn't expect _any_ integer promotions to occur in a shift
> expression. If you want to affect what's being shifted, then cast what's being
> shifted.
>

That's right... Somehow it didn't occur to me till the last moment that bit shift is asymmetric in nature so it really shouldn't do any promotions.
Sorry for the noise.

-- 
Dmitry Olshansky

August 07, 2011
On Monday 08 August 2011 01:42:37 Dmitry Olshansky wrote:
> > You have to deal with integer promotions and all that when doing arithmetic, because arithmetic needs to be done with a like number of bits on both sides of the operation. But with shifting, all your doing is asking it to shift some number of bits. The type which holds the number of bits shouldn't really matter. I wouldn't expect _any_ integer promotions to occur in a shift expression. If you want to affect what's being shifted, then cast what's being shifted.
> 
> That's right... Somehow it didn't occur to me till the last moment that bit shift is asymmetric in nature so it really shouldn't do any promotions. Sorry for the noise.

Yeah, well. Similar stuff happens to us all upon occasion. The real problem is when it happens frequently

- Jonathan M Davis
August 07, 2011
Dmitry Olshansky:

> Sorry for the noise.

It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD design fault. Clang gives an error on code like that:
http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html

See the error:
example2.cc:12:25: error: shift result (10737418240) requires 35 bits to represent, but 'int' only has 32 bits [-Werror,-Wshift-overflow]
long kMaxDiskSpace = 10 << 30;

In my opinion D has to give a similar error.

Bye,
bearophile
August 07, 2011
On 08.08.2011 2:07, bearophile wrote:
> Dmitry Olshansky:
>
>> Sorry for the noise.
> It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD design fault. Clang gives an error on code like that:
> http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html
>
> See the error:
> example2.cc:12:25: error: shift result (10737418240) requires 35 bits to represent, but 'int' only has 32 bits [-Werror,-Wshift-overflow]
> long kMaxDiskSpace = 10<<  30;
>
> In my opinion D has to give a similar error.
>

It's useful but not a panacea. I presented a simple trimmed down example with consts, I don't think compiler can reliably identify the problem in my actual code.

-- 
Dmitry Olshansky

August 07, 2011
Which has nothing to do with the question about integral promotion.

On Aug 7, 2011, at 3:07 PM, bearophile <bearophileHUGS@lycos.com> wrote:

> Dmitry Olshansky:
> 
>> Sorry for the noise.
> 
> It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD design fault. Clang gives an error on code like that:
> http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html
> 
> See the error:
> example2.cc:12:25: error: shift result (10737418240) requires 35 bits to represent, but 'int' only has 32 bits [-Werror,-Wshift-overflow]
> long kMaxDiskSpace = 10 << 30;
> 
> In my opinion D has to give a similar error.
> 
> Bye,
> bearophile
August 08, 2011
Brad Roberts:

> Which has nothing to do with the question about integral promotion.

The original code was similar to this C code:

int main() {
    unsigned int j = 42;
    unsigned long long k = 1 << (unsigned long long)j;
    return k;
}


If you process it with a simple C lint you get a warning 647:

1  int main() {
2      unsigned int j = 42;
3      unsigned long long k = 1 << (unsigned long long)j;
3  Info 701:  Shift left of signed quantity (int)
3  Warning 647:  Suspicious truncation
4      return k;
4  Info 712:  Loss of precision (return) (unsigned long long to int)
5  }

I think a compiler able to detect similar cases helps the OP avoid asking the question "I though left operand should be promoted to the largest integer in shift expression, isn't it?".

--------------

Dmitry Olshansky:

> It's useful but not a panacea.

I agree, you need something more/better to improve the situation a lot.

Bye,
bearophile
August 09, 2011
Jonathan M Davis wrote:
> On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote:
>> Just lost the best part of an hour figuring the cause of this small
>> problem, consider:
>>
>> void main()
>> {
>>          uint j = 42;
>>          ulong k = 1<<cast(ulong)j;
>>          ulong m = 1UL<<j;
>>          assert(k == 1024);//both asserts do pass
>>          assert(m == (1UL<<42));
>> }
>>
>> I though left operand should be promoted to the largest integer in shift
>> expression, isn't it?
> 
> I would not expect that type of integer being used to give the number of bits to shift to affect thet type of integer being shifted. It doesn't generally make much sense to shift more than the size of the integer type being shifted, and that can always fit in a byte. So, why would the type of the integer being used to give the number of bits to shift matter? It's like an index. The index doesn't affect the type of what's being indexed. It just gives you an index.
> 
> You have to deal with integer promotions and all that when doing arithmetic, because arithmetic needs to be done with a like number of bits on both sides of the operation. But with shifting, all your doing is asking it to shift some number of bits. The type which holds the number of bits shouldn't really matter. I wouldn't expect _any_ integer promotions to occur in a shift expression. If you want to affect what's being shifted, then cast what's being shifted.

Your intuition is wrong!

expression.html explicitly states the operands to shifts undergo integral promotions. But they don't get arithmetic conversions.

I think this is terrible.

short x = -1;
x >>>= 1;

Guess what x is...

August 09, 2011
On Tuesday 09 August 2011 09:32:41 Don wrote:
> Jonathan M Davis wrote:
> > On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote:
> >> Just lost the best part of an hour figuring the cause of this small problem, consider:
> >> 
> >> void main()
> >> {
> >> 
> >>          uint j = 42;
> >>          ulong k = 1<<cast(ulong)j;
> >>          ulong m = 1UL<<j;
> >>          assert(k == 1024);//both asserts do pass
> >>          assert(m == (1UL<<42));
> >> 
> >> }
> >> 
> >> I though left operand should be promoted to the largest integer in
> >> shift
> >> expression, isn't it?
> > 
> > I would not expect that type of integer being used to give the number of bits to shift to affect thet type of integer being shifted. It doesn't generally make much sense to shift more than the size of the integer type being shifted, and that can always fit in a byte. So, why would the type of the integer being used to give the number of bits to shift matter? It's like an index. The index doesn't affect the type of what's being indexed. It just gives you an index.
> > 
> > You have to deal with integer promotions and all that when doing arithmetic, because arithmetic needs to be done with a like number of bits on both sides of the operation. But with shifting, all your doing is asking it to shift some number of bits. The type which holds the number of bits shouldn't really matter. I wouldn't expect _any_ integer promotions to occur in a shift expression. If you want to affect what's being shifted, then cast what's being shifted.
> 
> Your intuition is wrong!
> 
> expression.html explicitly states the operands to shifts undergo integral promotions. But they don't get arithmetic conversions.
> 
> I think this is terrible.
> 
> short x = -1;
> x >>>= 1;
> 
> Guess what x is...

That's just downright weird. Why would any integral promotions occur with a shift? And given your example, the current behavior seems like a bad design. Is this some weird hold-over from C/C++?

- Jonathan M Davis
« First   ‹ Prev
1 2