bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Fwd: [PATCH] arithmetic -> logical shift]


From: Pádraig Brady
Subject: [Fwd: [PATCH] arithmetic -> logical shift]
Date: Fri, 17 Oct 2008 00:10:26 +0100
User-agent: Thunderbird 2.0.0.6 (X11/20071008)

-------- Original Message --------
Date: Tue, 07 Oct 2008 11:55:51 +0100
From: Pádraig Brady <address@hidden>
To: Chet Ramey <address@hidden>
CC: address@hidden

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);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]