Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
sylau
- Posts: 4
- Joined: 06 Jan 2015 16:23
#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
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:
#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
#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
#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:
#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
#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
#7
Post
by aGerman » 13 Aug 2017 09:30
For binary operations you need to think binary
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
#8
Post
by IcarusLives » 13 Aug 2017 20:36
aGerman wrote:For binary operations you need to think binary
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.