Shift right is broken for negative numbers


int x = -5;
Console.WriteLine(x >> 1); // -3
IntX y = -5;
Console.WriteLine(y >> 1); // -2 
BigInteger z = -5;
Console.WriteLine(z >> 1); // -3
Closed Sep 8, 2013 at 5:17 PM by Oyster


leppie wrote Sep 7, 2013 at 8:31 PM

The slow fix is to add the following just before the return in OpHelper.Sh:
if (!toLeft && intX.Negative)
  return ~-newInt;

leppie wrote Sep 7, 2013 at 9:23 PM

Above fix still fails... :(

Oyster wrote Sep 8, 2013 at 3:49 PM

Yes, it's reproducible, but not a bug :)

The reason why IntX behaves this way is because it doesn't store negative integers in two's complement form, mostly because it's not obvious for an arbitrary precision number which power of 2 it must be complement to. Instead, numbers are stored as unsigned part + sign.

So, the following condition can be false for Int16/Int32/Int64 but is always true for IntX:
-(x >> y) == (-x) >> y
As a conclusion, it's not going to be fixed. It's not a bug, and IntX wasn't initially designed to fully mimic .NET numeric types behavior (for instance, it doesn't have bitwise operations at all)

leppie wrote Sep 8, 2013 at 4:24 PM

Thanks for the clarification.

I managed to work around the issue in IronScheme :)

leppie wrote Sep 8, 2013 at 4:28 PM

It seems I (or someone) did in fact implement bitwise ops for the version I use in IronScheme O_o.

wrote Sep 8, 2013 at 5:17 PM