VBspeed / Bits / ShiftLeft
VBspeed © 2000-10, updated: 09-Oct-2001
ShiftLeft


The Definition
Function ShiftLeft
Shifts the bits to the left the specified number of positions and returns the new value.
Bits "falling off" the left edge do not wrap around. Fill bits coming in from right are 0.

A shift left is effectively a multiplication by 2. Some common languages like C/C++ or Java have an operator for this job: "<<".
Declaration
Function ShiftLeft(Value As Long, ShiftCount as Long) As Long
Arguments
Valuevalue to use for operation
ShiftCountnumber of positions to shift, valid range is 0 thru 31.
You may use this function (VB5/6-compatible) to verify the correctness of your code.


The Charts
Calls
 lRet = ShiftLeft(Value, ShiftCount)
Call 1 Value = 1
ShiftCount = 8
Call 2 Value = 255
ShiftCount = 24
 VB5
CodeAuthorDopingNotes
ShiftLeft01 ThomasAPI 
ShiftLeft02 Donald  
ShiftLeft03 VB2TheMax  
ShiftLeft04 PaulAPI,ASM 
ShiftLeft05 Jost  
ShiftLeft06 Jost  
Call 1
67.920.297µs
43.540.133µs
54.020.151µs
11.000.038µs
31.720.064µs
21.310.049µs
Call 2
67.940.297µs
43.680.138µs
54.030.151µs
11.000.037µs
31.790.067µs
21.180.044µs
 VB6
CodeAuthorDopingNotes
ShiftLeft01 ThomasAPI 
ShiftLeft02 Donald  
ShiftLeft03 VB2TheMax  
ShiftLeft04 PaulAPI,ASM 
ShiftLeft05 Jost  
ShiftLeft06 Jost  
Call 1
69.490.328µs
43.840.133µs
53.960.137µs
11.000.035µs
31.870.065µs
21.330.046µs
Call 2
69.490.328µs
43.830.132µs
53.980.138µs
11.000.035µs
31.920.066µs
21.330.046µs
Conclusions
09-Oct-2001: Progress on Vbspeed is lightning-fast, just like the revision of Paul's ASM-doped ShiftLeft04, back and lonely on the top.
01-Oct-2001: Who said size didn't matter? ShiftLeft06's almost 200 lines of pure VB-code are faster than a handful of ASM bytes (ShiftLeft04).
Mail your code! How to read all those numbers


The Code
ShiftLeft01
added 18-Dec-2000
Doping: API
Private Type LARGEINT
  Long1 As Long
  Long2 As Long
End Type

Private Declare Function RLIShiftLeft Lib "ntdll" Alias "RtlLargeIntegerShiftLeft" _
    (ByVal Val1 As Long, ByVal Val2 As Long, ByVal ShiftCount As Long) As LARGEINT

Public Function ShiftLeft01(Value As Long, ByVal ShiftCount As Long) As Long ' by Thomas Kabir (contact@vbfrood.de, http://www.vbfrood.de), 20001215 Dim Result As LARGEINT Result = RLIShiftLeft(Value, 0, ShiftCount) ShiftLeft01 = Result.Long1 End Function
Author's comments:
Donald's comments:

top | charts


ShiftLeft02
submitted 18-Dec-2000 by Donald Lessau  
Doping: none
Public Function ShiftLeft02(Value As Long, ByVal ShiftCount As Long) As Long
' by Donald, donald@xbeat.net, 20001215
  Dim mask As Long
  
  Select Case ShiftCount
  Case 1 To 31
    ' mask out bits that are pushed over the edge anyway
    mask = Pow2(31 - ShiftCount)
    ShiftLeft02 = Value And (mask - 1)
    ' shift
    ShiftLeft02 = ShiftLeft02 * Pow2(ShiftCount)
    ' set sign bit
    If Value And mask Then
      ShiftLeft02 = ShiftLeft02 Or &H80000000
    End If
  Case 0
    ' ret unchanged
    ShiftLeft02 = Value
  End Select
  
End Function
Author's comments: See Pow2
Donald's comments:

top | charts


ShiftLeft03
added 18-Dec-2000
Doping: none
Public Function ShiftLeft03(ByVal Value As Long, ByVal times As Long) As Long
' by The VB2TheMax Team (as "ShiftLeft"), 20001217
    ' we need to create a mask of 1's corresponding to the
    ' times in VALUE that will be retained in the result
    Dim mask As Long, signBit As Long
    
    ' return zero if too many times
    If times >= 32 Then Exit Function
    ' return the value if zero times
    If times = 0 Then ShiftLeft03 = Value: Exit Function
    
    ' this extracts the bit in Value that will become the sign bit
    mask = Pow2(31 - times)
    ' this calculates the sign bit of the result
    signBit = CBool(Value And mask) And &H80000000
    ' this clears all the most significant times,
    ' that would be lost anyway, and also clears the sign bit
    Value = Value And (mask - 1)
    ' do the shift to the left, without risking an overflow
    ' and then add the sign bit
    ShiftLeft03 = (Value * Pow2(times)) Or signBit
End Function
Author's comments: See Pow2
Donald's comments:

top | charts


ShiftLeft04
submitted 26-Sep-2001 by Paul    http://www.syix.com/wpsjr1/index.html
revision 001, 09-Oct-2001
Doping: API and ASM (Assembly Snippets), all three Shift operations wrapped in module (download the module, VB5-compatible, zipped, 2KB)
The complete code is a bit too long to be displayed here ... download it to have a look.

Here's the ASM bytes (for each of the three Shift operations):
Private Const SHLCode As String = "8A4C240833C0F6C1E075068B442404D3E0C20800"  ' shl eax, cl = D3 E0
Private Const SHRCode As String = "8A4C240833C0F6C1E075068B442404D3E8C20800"  ' shr eax, cl = D3 E8
Private Const SARCode As String = "8A4C240833C0F6C1E075068B442404D3F8C20800"  ' sar eax, cl = D3 F8
Author's comments:
' These functions are inline asm hacks for SHL and SHR aka << >>
' in C, C++.  They shift using the following ASM code:

' mov eax, [esp+4]
' mov cl, [esp+8]
' shr eax, cl   ; or shl eax, cl
' ret 8

' Only the first five bits of the cl register are evaluated for either op code.
' So, as in C, if you do shl 8, 33 its the equivalent of shl 8, 1
' as (33 AND 31) = 1

' or shr 8, -1 is the same as shr 8, 31 as (255 and 31) = 31

' Personally, I think VB is sorely in need of true bit shifting ops,
' but MS assumes we VB programmers are a mindless bunch :(

' NOTE: YOU *MUST* CALL InitFunctionsShift() BEFORE USING THESE FUNCTIONS
Donald's comments:

top | charts


ShiftLeft05
submitted 28-Sep-2001 by Jost Schwider    vb-tec.de
Doping: none
Public Static Function ShiftLeft05(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by Jost Schwider, jost@schwider.de, 20010928
  Dim Pow2(0 To 31) As Long
  Dim i As Long
  Dim mask As Long
  
  Select Case ShiftCount
  Case 1 To 31
  
    'Ggf. Initialisieren:
    If i = 0 Then
      Pow2(0) = 1
      For i = 1 To 30
        Pow2(i) = 2 * Pow2(i - 1)
      Next i
    End If
    
    'Los gehts:
    mask = Pow2(31 - ShiftCount)
    If Value And mask Then
      ShiftLeft05 = (Value And (mask - 1)) * Pow2(ShiftCount) Or &H80000000
    Else
      ShiftLeft05 = (Value And (mask - 1)) * Pow2(ShiftCount)
    End If
  
  Case 0
  
    ShiftLeft05 = Value
  
  End Select
End Function
Author's comments:
Donald's comments:

top | charts


ShiftLeft06
submitted 01-Oct-2001 by Jost Schwider    vb-tec.de
Doping: none
Public Function ShiftLeft06(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by Jost Schwider, jost@schwider.de, 20011001
  Select Case ShiftCount
  Case 0&
    ShiftLeft06 = Value
  Case 1&
    If Value And &H40000000 Then
      ShiftLeft06 = (Value And &H3FFFFFFF) * &H2& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3FFFFFFF) * &H2&
    End If
  Case 2&
    If Value And &H20000000 Then
      ShiftLeft06 = (Value And &H1FFFFFFF) * &H4& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1FFFFFFF) * &H4&
    End If
  Case 3&
    If Value And &H10000000 Then
      ShiftLeft06 = (Value And &HFFFFFFF) * &H8& Or &H80000000
    Else
      ShiftLeft06 = (Value And &HFFFFFFF) * &H8&
    End If
  Case 4&
    If Value And &H8000000 Then
      ShiftLeft06 = (Value And &H7FFFFFF) * &H10& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7FFFFFF) * &H10&
    End If
  Case 5&
    If Value And &H4000000 Then
      ShiftLeft06 = (Value And &H3FFFFFF) * &H20& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3FFFFFF) * &H20&
    End If
  Case 6&
    If Value And &H2000000 Then
      ShiftLeft06 = (Value And &H1FFFFFF) * &H40& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1FFFFFF) * &H40&
    End If
  Case 7&
    If Value And &H1000000 Then
      ShiftLeft06 = (Value And &HFFFFFF) * &H80& Or &H80000000
    Else
      ShiftLeft06 = (Value And &HFFFFFF) * &H80&
    End If
  Case 8&
    If Value And &H800000 Then
      ShiftLeft06 = (Value And &H7FFFFF) * &H100& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7FFFFF) * &H100&
    End If
  Case 9&
    If Value And &H400000 Then
      ShiftLeft06 = (Value And &H3FFFFF) * &H200& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3FFFFF) * &H200&
    End If
  Case 10&
    If Value And &H200000 Then
      ShiftLeft06 = (Value And &H1FFFFF) * &H400& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1FFFFF) * &H400&
    End If
  Case 11&
    If Value And &H100000 Then
      ShiftLeft06 = (Value And &HFFFFF) * &H800& Or &H80000000
    Else
      ShiftLeft06 = (Value And &HFFFFF) * &H800&
    End If
  Case 12&
    If Value And &H80000 Then
      ShiftLeft06 = (Value And &H7FFFF) * &H1000& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7FFFF) * &H1000&
    End If
  Case 13&
    If Value And &H40000 Then
      ShiftLeft06 = (Value And &H3FFFF) * &H2000& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3FFFF) * &H2000&
    End If
  Case 14&
    If Value And &H20000 Then
      ShiftLeft06 = (Value And &H1FFFF) * &H4000& Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1FFFF) * &H4000&
    End If
  Case 15&
    If Value And &H10000 Then
      ShiftLeft06 = (Value And &HFFFF&) * &H8000& Or &H80000000
    Else
      ShiftLeft06 = (Value And &HFFFF&) * &H8000&
    End If
  Case 16&
    If Value And &H8000& Then
      ShiftLeft06 = (Value And &H7FFF&) * &H10000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7FFF&) * &H10000
    End If
  Case 17&
    If Value And &H4000& Then
      ShiftLeft06 = (Value And &H3FFF&) * &H20000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3FFF&) * &H20000
    End If
  Case 18&
    If Value And &H2000& Then
      ShiftLeft06 = (Value And &H1FFF&) * &H40000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1FFF&) * &H40000
    End If
  Case 19&
    If Value And &H1000& Then
      ShiftLeft06 = (Value And &HFFF&) * &H80000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &HFFF&) * &H80000
    End If
  Case 20&
    If Value And &H800& Then
      ShiftLeft06 = (Value And &H7FF&) * &H100000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7FF&) * &H100000
    End If
  Case 21&
    If Value And &H400& Then
      ShiftLeft06 = (Value And &H3FF&) * &H200000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3FF&) * &H200000
    End If
  Case 22&
    If Value And &H200& Then
      ShiftLeft06 = (Value And &H1FF&) * &H400000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1FF&) * &H400000
    End If
  Case 23&
    If Value And &H100& Then
      ShiftLeft06 = (Value And &HFF&) * &H800000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &HFF&) * &H800000
    End If
  Case 24&
    If Value And &H80& Then
      ShiftLeft06 = (Value And &H7F&) * &H1000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7F&) * &H1000000
    End If
  Case 25&
    If Value And &H40& Then
      ShiftLeft06 = (Value And &H3F&) * &H2000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3F&) * &H2000000
    End If
  Case 26&
    If Value And &H20& Then
      ShiftLeft06 = (Value And &H1F&) * &H4000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1F&) * &H4000000
    End If
  Case 27&
    If Value And &H10& Then
      ShiftLeft06 = (Value And &HF&) * &H8000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &HF&) * &H8000000
    End If
  Case 28&
    If Value And &H8& Then
      ShiftLeft06 = (Value And &H7&) * &H10000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H7&) * &H10000000
    End If
  Case 29&
    If Value And &H4& Then
      ShiftLeft06 = (Value And &H3&) * &H20000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H3&) * &H20000000
    End If
  Case 30&
    If Value And &H2& Then
      ShiftLeft06 = (Value And &H1&) * &H40000000 Or &H80000000
    Else
      ShiftLeft06 = (Value And &H1&) * &H40000000
    End If
  Case 31&
    If Value And &H1& Then
      ShiftLeft06 = &H80000000
    Else
      ShiftLeft06 = &H0&
    End If
  End Select
End Function
Author's comments:
Donald's comments:

top | charts




VBspeed © 2000-10 by Donald Lessau