-------- Original Message -------- Date: Tue, 07 Oct 2008 11:55:51 +0100 From: Pádraig Brady <[EMAIL PROTECTED]> To: Chet Ramey <[EMAIL PROTECTED]> CC: [EMAIL PROTECTED]
I was just discussing bit shifting with Tim Hockin using shell arithmetic expansion, and he pointed out that bash and ksh use arithmetic rather than logical shift for the >> operator. Now arithmetic shift is not useful on 2's compliment machines, and moreover it's compiler dependent as to whether arithmetic or logical shift is done for >>. Therefore to increase usefulness and decrease ambiguity I suggest applying something like the attached simple patch. I know the opengroup spec says to use signed ints, but I think that is intended to disambiguate input and output, rather than defining internal operations. Some sample output from the patched version: $ printf "%x\n" $((0x8000000000000000>>1)) 4000000000000000 $ smax=$((-1>>1)); echo $smax 9223372036854775807 $ echo $((-0x4000000000000000/2)) $((-0x4000000000000000>>1)) -2305843009213693952 6917529027641081856 And corresponding output from unpatched bash: $ printf "%x\n" $((0x8000000000000000>>1)) c000000000000000 $ smax=$((-1>>1)); echo $smax -1 $ echo $((-0x4000000000000000/2)) $((-0x4000000000000000>>1)) -2305843009213693952 -2305843009213693952 cheers, Pádraig.
--- expr.arithmetic_shift.c 2008-10-06 07:35:09.000000000 +0000 +++ expr.c 2008-10-06 07:11:44.000000000 +0000 @@ -452,7 +452,7 @@ lvalue <<= value; break; case RSH: - lvalue >>= value; + lvalue = ((uintmax_t)lvalue) >> value; break; case BAND: lvalue &= value; @@ -703,7 +703,7 @@ if (op == LSH) val1 = val1 << val2; else - val1 = val1 >> val2; + val1 = ((uintmax_t)val1) >> val2; } return (val1);