Forgive me if this has been previously noted:
The 5.3 manual says > All bitwise operations convert its operands to integers (see §3.4.3), operate on all bits of those integers, and result in an integer. > Both right and left shifts fill the vacant bits with zeros. In other words an "unsigned" shift or logical shift. No sign extension. Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio > string.format("0x%016x",(1<<63)>>8) 0x0080000000000000 Bash # printf '0x%016x\n' $(( (1<<63)>>8 )) 0xff80000000000000 PHP printf '0x%016x\n' $(( (1<<63)>>8 )) 0xff80000000000000 Perl # perl -e 'printf "0x%016x\n",(1<<63)>>8' 0x0080000000000000 SQLite 3.29.0 sqlite> select printf('0x%016x',(1<<63)>>8); 0xff80000000000000 *I wish this was highlighted in the manual.* What was the reasoning in choosing logical shift for >> rather than arithmetic? It seems strange given that >> only operates on lua_integer and lua_integer is by default a signed entity. also note: > string.format("%d , %d",(1<<63),(1<<63)//256) -9223372036854775808 , -36028797018963968 > string.format("%d , %d",(1<<63),(1<<63)//(2^8)) -9223372036854775808 , -36028797018963968 > string.format("%d , %d",(1<<63),(1<<63)>>8) -9223372036854775808 , 36028797018963968 |
It was thus said that the Great D Burgess once stated:
> Forgive me if this has been previously noted: > The 5.3 manual says > > All bitwise operations convert its operands to integers (see §3.4.3), operate on all bits of those integers, and result in an integer. > > Both right and left shifts fill the vacant bits with zeros. > > In other words an "unsigned" shift or logical shift. No sign extension. > > Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio > > string.format("0x%016x",(1<<63)>>8) > 0x0080000000000000 > > Bash > # printf '0x%016x\n' $(( (1<<63)>>8 )) > 0xff80000000000000 > > PHP > printf '0x%016x\n' $(( (1<<63)>>8 )) > 0xff80000000000000 > > Perl > # perl -e 'printf "0x%016x\n",(1<<63)>>8' > 0x0080000000000000 > > SQLite 3.29.0 > sqlite> select printf('0x%016x',(1<<63)>>8); > 0xff80000000000000 > > *I wish this was highlighted in the manual.* > > What was the reasoning in choosing logical shift for >> rather than arithmetic? From the C89 standard (ISO/IEC 9899:1990), section 6.3.7 (emphasis added): The result of El >> E2 is El right-shifted E2 bit positions. If El has an unsigned type or if El has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of El divided by the quantity, 2 raised to the power E2. If El has a signed type and a negative value, the resulting value is implementation-defined. ^^^^^^^^^^^^^^^^^^^^^^ From that, I would assume that the only way to ensure consistent values across all C compilers is to only do unsigned shifts. -spc |
On Sun, Oct 13, 2019 at 9:59 PM Sean Conner <[hidden email]> wrote:
> > It was thus said that the Great D Burgess once stated: > > Forgive me if this has been previously noted: > > The 5.3 manual says > > > All bitwise operations convert its operands to integers (see §3.4.3), operate on all bits of those integers, and result in an integer. > > > Both right and left shifts fill the vacant bits with zeros. > > > > In other words an "unsigned" shift or logical shift. No sign extension. > > > > Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio > > > string.format("0x%016x",(1<<63)>>8) > > 0x0080000000000000 > > > > Bash > > # printf '0x%016x\n' $(( (1<<63)>>8 )) > > 0xff80000000000000 > > > > PHP > > printf '0x%016x\n' $(( (1<<63)>>8 )) > > 0xff80000000000000 > > > > Perl > > # perl -e 'printf "0x%016x\n",(1<<63)>>8' > > 0x0080000000000000 > > > > SQLite 3.29.0 > > sqlite> select printf('0x%016x',(1<<63)>>8); > > 0xff80000000000000 > > > > *I wish this was highlighted in the manual.* > > > > What was the reasoning in choosing logical shift for >> rather than arithmetic? > > From the C89 standard (ISO/IEC 9899:1990), section 6.3.7 (emphasis added): > > The result of El >> E2 is El right-shifted E2 bit positions. If El > has an unsigned type or if El has a signed type and a nonnegative > value, the value of the result is the integral part of the quotient > of El divided by the quantity, 2 raised to the power E2. If El has a > signed type and a negative value, the resulting value is > implementation-defined. > ^^^^^^^^^^^^^^^^^^^^^^ > > From that, I would assume that the only way to ensure consistent values > across all C compilers is to only do unsigned shifts. The Lua VM implements shifts here: https://github.com/lua/lua/blob/master/lvm.c#L673-L687 It took me a moment to understand that, but after looking at the intop macro in lvm.h (https://github.com/lua/lua/blob/master/lvm.h#L61), it casts the operands to unsigned before performing the operation (https://github.com/lua/lua/blob/master/llimits.h#L129-L141). I think it might be useful to offer both types of right shift. Perhaps the arithmetic shift can be offered as the >>> operator? |
> Perhaps the arithmetic shift can be offered as the >>> operator?
Excellent suggestion. |
On Mon, Oct 14, 2019 at 5:51 AM D Burgess wrote: > Perhaps the arithmetic shift can be offered as the >>> operator? (x >>> k) == (x >> k) - ((x & math.mininteger) >> (k-1)) |
Free forum by Nabble | Edit this page |