digitalmars.D.learn - (int << ulong) == int ?
- Dmitry Olshansky (14/14) Aug 07 2011 Just lost the best part of an hour figuring the cause of this small
- Jonathan M Davis (15/29) Aug 07 2011 I would not expect that type of integer being used to give the number of...
- Dmitry Olshansky (5/12) Aug 07 2011 That's right... Somehow it didn't occur to me till the last moment that
- Jonathan M Davis (4/15) Aug 07 2011 Yeah, well. Similar stuff happens to us all upon occasion. The real prob...
- bearophile (9/10) Aug 07 2011 It's not noise, and you don't need to be sorry, in my opinion it's a D/D...
- Dmitry Olshansky (6/14) Aug 07 2011 It's useful but not a panacea. I presented a simple trimmed down example...
- Brad Roberts (4/19) Aug 07 2011 design fault. Clang gives an error on code like that:
- bearophile (22/24) Aug 07 2011 The original code was similar to this C code:
- Don (8/38) Aug 09 2011 Your intuition is wrong!
- Jonathan M Davis (5/52) Aug 09 2011 That's just downright weird. Why would any integral promotions occur wit...
- Don (9/59) Aug 09 2011 I think it must be, some silly idea of 'simplifying' things by applying
- Jonathan M Davis (6/75) Aug 09 2011 Given that fact, wouldn't it be safe to change the behavior so that it
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
Aug 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
Aug 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
Aug 07 2011
On Monday 08 August 2011 01:42:37 Dmitry Olshansky wrote:Yeah, well. Similar stuff happens to us all upon occasion. The real problem is when it happens frequently - Jonathan M DavisYou 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.
Aug 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
Aug 07 2011
On 08.08.2011 2:07, bearophile wrote:Dmitry Olshansky: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 OlshanskySorry 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.
Aug 07 2011
Which has nothing to do with the question about integral promotion. =20 On Aug 7, 2011, at 3:07 PM, bearophile <bearophileHUGS lycos.com> wrote:Dmitry Olshansky: =20design fault. Clang gives an error on code like that:Sorry for the noise.=20 It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD=http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html =20 See the error: example2.cc:12:25: error: shift result (10737418240) requires 35 bits to r=epresent, but 'int' only has 32 bits [-Werror,-Wshift-overflow]long kMaxDiskSpace =3D 10 << 30; =20 In my opinion D has to give a similar error. =20 Bye, bearophile
Aug 07 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
Aug 07 2011
Jonathan M Davis wrote:On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote: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...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.
Aug 09 2011
On Tuesday 09 August 2011 09:32:41 Don wrote:Jonathan M Davis wrote: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 DavisOn Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote: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...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.
Aug 09 2011
Jonathan M Davis wrote:On Tuesday 09 August 2011 09:32:41 Don wrote: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.Jonathan M Davis wrote: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++?On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote: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...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.
Aug 09 2011
On Tuesday 09 August 2011 11:03:11 Don wrote:Jonathan M Davis wrote: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 DavisOn Tuesday 09 August 2011 09:32:41 Don wrote: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.Jonathan M Davis wrote: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++?On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote: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...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.
Aug 09 2011