Circular left shift

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
sylau
Posts: 4
Joined: 06 Jan 2015 16:23

Circular left shift

#1 Post by sylau » 12 Aug 2017 17:09

Hello,

I am trying to implement a circular left shift in set /a. Regular left shift works well, but I cannot rotate the front bits back.

For example

Code: Select all

set /a x=0xAA00FF00


x is now

Code: Select all

in binary:      10101010000000001111111100000000
in hexadecimal: AA00FF00


If I circularly left shifted it by 4 bits, x should be

Code: Select all

in binary:      10100000000011111111000000001010
in hexadecimal: A00FF00A


I'd prefer it if there were no string manipulation involved.

Thanks, WOLGA

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Circular left shift

#2 Post by Aacini » 13 Aug 2017 00:01

Code: Select all

@echo off
setlocal

set /A x=0xAA00FF00

set /A "shift=x<<4 | x>>28&0xF"

echo Result  = %shift%

set /A correct=0xA00FF00A

echo Correct = %correct%

Output:

Code: Select all

Result  = -1609568246
Correct = -1609568246

Antonio

sylau
Posts: 4
Joined: 06 Jan 2015 16:23

Re: Circular left shift

#3 Post by sylau » 13 Aug 2017 07:10

Aacini, is there a way to make it so that the number of bits I am shifting by is variable?

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Circular left shift

#4 Post by aGerman » 13 Aug 2017 07:15

You could extend Antonio's equation a little.

Code: Select all

@echo off &setlocal

set /a "x=0xAA00FF00, sh=-28"
call :printhex %x%

set /a "sh=((sh %% 32) + 32) %% 32, y=(x << sh) | ( (x >> (32 - sh)) & ((1 << sh) - 1) )"
call :printhex %y%

pause
exit /b


:printhex
cmd /c exit %~1
echo %=exitcode%
exit /b

%sh% is the bits to shift.
The 2nd SET /A command consists of two comma-separated equations.
- The first normalizes %sh% to result in a positive value in range 0...31. Thus, values greater than 32 will work as well as negative values.
- The second is Antonio's equation, generalized to work with any normalized %sh% value.

There are some extra parentheses that hopefully make it easier to understand.

Steffen

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Circular left shift

#5 Post by Aacini » 13 Aug 2017 08:29

sylau wrote:Aacini, is there a way to make it so that the number of bits I am shifting by is variable?

Yes. Instead "4" put the desired bits, instead "28" put "32-bits" and adjust the mask:

Code: Select all

set /A "bits=4, shift=x<<bits | x>>32-bits&(1<<bits)-1"

Antonio

sylau
Posts: 4
Joined: 06 Jan 2015 16:23

Re: Circular left shift

#6 Post by sylau » 13 Aug 2017 09:02

Aacini wrote:
sylau wrote:Aacini, is there a way to make it so that the number of bits I am shifting by is variable?

Yes. Instead "4" put the desired bits, instead "28" put "32-bits" and adjust the mask:

Code: Select all

set /A "bits=4, shift=x<<bits | x>>32-bits&(1<<bits)-1"

Antonio


Thank you! If you don't mind me asking, how does it work? It's hard for me to wrap my head around the logic.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Circular left shift

#7 Post by aGerman » 13 Aug 2017 09:30

For binary operations you need to think binary :wink:
In your example the binary equivalent of 0xAA00FF00 is 10101010000000001111111100000000

Code: Select all

left OR operand:
        10101010000000001111111100000000
<<  4   10100000000011111111000000000000

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

right OR operand:
        10100000000011111111000000000000
>> 28   11111111111111111111111111111010  (where 28 is 32-4)
&  15   00000000000000000000000000001111  (where 15 is (1<<4)-1)
result  00000000000000000000000000001010

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

OR operation
        10100000000011111111000000000000
|       00000000000000000000000000001010
result  10100000000011111111000000001010

The reason why you need the bitwise AND is that numbers in batch are 32bit signed integers. Right-shifting is implemented as two's complement arithmetic shifting. Thus, ones are shifted in for negative numbers.

Steffen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Circular left shift

#8 Post by IcarusLives » 13 Aug 2017 20:36

aGerman wrote:For binary operations you need to think binary :wink:
In your example the binary equivalent of 0xAA00FF00 is 10101010000000001111111100000000

Code: Select all

left OR operand:
        10101010000000001111111100000000
<<  4   10100000000011111111000000000000

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

right OR operand:
        10100000000011111111000000000000
>> 28   11111111111111111111111111111010  (where 28 is 32-4)
&  15   00000000000000000000000000001111  (where 15 is (1<<4)-1)
result  00000000000000000000000000001010

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

OR operation
        10100000000011111111000000000000
|       00000000000000000000000000001010
result  10100000000011111111000000001010

The reason why you need the bitwise AND is that numbers in batch are 32bit signed integers. Right-shifting is implemented as two's complement arithmetic shifting. Thus, ones are shifted in for negative numbers.

Steffen


This is excellent information! Thank you for sharing!

OP, what is the purpose of this project? The responses for this are interesting, and I'm learning a lot.

Post Reply