August 09, 2011
Jonathan M Davis wrote:
> 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++?

I think it must be, some silly idea of 'simplifying' things by applying the same promotion rules to all binary operators. Given that 256-bit integers still don't seem to be coming any time soon, even shifts by a signed byte shouldn't require promotion.
Incidentally, the x86 instruction set doesn't use integers, you can only shift a 64-bit number by an 8-bit value. So x << y always compiles to
x << cast(ubyte)y. Shift should not need a common type.

This is one of those things that can cause problems, but never helps.

August 09, 2011
On Tuesday 09 August 2011 11:03:11 Don wrote:
> Jonathan M Davis wrote:
> > 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++?
> 
> I think it must be, some silly idea of 'simplifying' things by applying
> the same promotion rules to all binary operators. Given that 256-bit
> integers still don't seem to be coming any time soon, even shifts by a
> signed byte shouldn't require promotion.
> Incidentally, the x86 instruction set doesn't use integers, you can only
> shift a 64-bit number by an 8-bit value. So x << y always compiles to
> x << cast(ubyte)y. Shift should not need a common type.
> 
> This is one of those things that can cause problems, but never helps.

Given that fact, wouldn't it be safe to change the behavior so that it _doesn't_ do promotions? It sounds like the only case where it would change behavior (either for code ported from C/C++ or for existing D code) is if it's doing something wrong.

- Jonathan M Davis
1 2
Next ›   Last »