rotate left/right Functions (overloaded)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

rotate left/right Functions (overloaded)

Post by MrSwiss »

Sometimes we are in a position where bit rotation is usefull, but FB has no equivalent.
In assembly language there are the rol and, ror statements to do that.
The rotate_procs.bi file contains the FB rotl() and, rotr() Functions for:
ULong or ULongInt data-types (overloaded and private).
This means:
- If only the one Function is used, the others are NOT included in the binary.
- The compiler picks the appropriate Function to use, depending on variable size.
Usage:
- rotl(v_in, rbit) or rotr(v_in, rbit)
Where:
v_in = value/variable to manipulate
rbit = number of bits to rotate (optional, default = 1)

rotate_procs.bi:

Code: Select all

' rotate_procs.bi -- (c) 2021-01-06, MrSwiss

#Ifndef __ROTATE_PROCS_BI__
#Define __ROTATE_PROCS_BI__

' the same as: rol (assembly statement) rotate bits to left
Declare Function rotl OverLoad(ByVal As ULong, ByVal As ULong=1) As ULong
Declare Function rotl OverLoad(ByVal As ULongInt, ByVal As ULong=1) As ULongInt
' the same as: ror (assembly statement) rotate bits to right
Declare Function rotr OverLoad(ByVal As ULong, ByVal As ULong=1) As ULong
Declare Function rotr OverLoad(ByVal As ULongInt, ByVal As ULong=1) As ULongInt

Private Function rotl OverLoad( _       ' rotate left
    ByVal v_in  As ULong,    _          ' value to rotate (32 bits)
    ByVal rbit  As ULong = 1 _          ' _opt_ rotation in bits (default: 1)
    ) As ULong
    If rbit < 1 OrElse rbit > 31 Then Return 0
    Return (v_in Shl rbit) Or (v_in Shr (32 - rbit))
End Function

Private Function rotl OverLoad( _       ' as above
    ByVal v_in  As ULongInt, _          ' value to rotate (64 bits)
    ByVal rbit  As ULong = 1 _          ' as above
    ) As ULongInt
    If rbit < 1 OrElse rbit > 63 Then Return 0
    Return (v_in Shl rbit) Or (v_in Shr (64 - rbit))
End Function

Private Function rotr OverLoad( _       ' rotate right
    ByVal v_in  As ULong,    _          ' value to rotate (32 bits)
    ByVal rbit  As ULong = 1 _          ' _opt_ rotation in bits (default: 1)
    ) As ULong
    If rbit < 1 OrElse rbit > 31 Then Return 0
    Return (v_in Shr rbit) Or (v_in Shl (32 - rbit))
End Function

Private Function rotr OverLoad( _       ' as above
    ByVal v_in  As ULongInt, _          ' value to rotate (64 bits)
    ByVal rbit  As ULong = 1 _          ' as above
    ) As ULongInt
    If rbit < 1 OrElse rbit > 63 Then Return 0
    Return (v_in Shr rbit) Or (v_in Shl (64 - rbit))
End Function

#EndIf  ' __ROTATE_PROCS_BI__
' ----- EOF -----
A little DEMO, rotate_procs.bas:

Code: Select all

' rotate_procs.bas -- (c) 2021-01-06, MrSwiss

#Include "rotate_procs.bi"

' DEMO code (only the 32-bit variants are used here)
' it proves that: rotl() has invers proportional results _
' to rotr() and, vice versa (second part of demo)
Dim As Long test = &h8091A2B3

? "test: "; test, Bin(test, 32)
?
For i As UInteger = 1 To 31             ' 0 or 32 throw ERROR = 0
    ? "rotl("; test; ", "; i; "): ", Bin(rotl(test, i), 32)
Next

? : ? "press a key to continue ... "
Sleep : ? : ?

? "test: "; test, Bin(test, 32)
?

For i As UInteger = 1 To 31             ' 0 or 32 throw ERROR = 0
    ? "rotl("; test; ", "; i; "): ", Bin(rotl(test, i), 32)
    Var inv = 32 - i
    ? "rotr("; test; ", "; inv; "): ", Bin(rotr(test, inv), 32)
    ?
Next

? : ? "... done ... ";
Sleep
' ----- EOF -----
Vortex
Posts: 118
Joined: Sep 19, 2005 9:50

Re: rotate left/right Functions (overloaded)

Post by Vortex »

Hi MrSwiss,

Thanks for your code. Here is something similar for 32-bit coding :

Code: Select all

Function _ror Naked ( Byval a As Uinteger , Byval b As Uinteger) As Uinteger

Asm
   mov eax,DWORD Ptr [esp+4]
   mov ecx,DWORD Ptr [esp+8]
   ror eax,cl
   ret 2*4
End Asm

End Function

Function _rol Naked ( Byval a As Uinteger , Byval b As Uinteger) As Uinteger

Asm
   mov eax,DWORD Ptr [esp+4]
   mov ecx,DWORD Ptr [esp+8]
   rol eax,cl
   ret 2*4
End Asm

End Function

Print "ror 192,2 =",_ror(192,2)
Print "rol 96,2 =",_rol(96,2)
For 64-bit :

Code: Select all

Function _ror Naked ( Byval a As Uinteger , Byval b As Uinteger) As Uinteger

Asm
   mov rax,rcx
   mov rcx,rdx
   ror rax,cl
   ret
End Asm

End Function

Function _rol Naked ( Byval a As Uinteger , Byval b As Uinteger) As Uinteger

Asm
   mov rax,rcx
   mov rcx,rdx
   rol rax,cl
   ret
End Asm

End Function

Print "ror 192,2 =",_ror(192,2)
Print "rol 96,2 =",_rol(96,2)
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: rotate left/right Functions (overloaded)

Post by MrSwiss »

Hi Vortex,

Thanks for the assembly versions.

My explicit purposes where:
  • avoid inline assembly to avoid portability issues (aka: FB code only)
  • incorporate range check and indicate 'argument errors'
  • leave 'behind the scenes' stuff to the compiler
  • not having to deal with FB's U/Integer data-type (explicitly)
Post Reply