VBspeed / Bits / ShiftRight
VBspeed © 2000-10, updated: 20-Nov-2001
ShiftRight


NOTE --- 09-Oct-2001
All ShiftRight codes previously shown here (ShiftRight01 thru ShiftRight04) returned WRONG results for most of the cases where Value is negative. Thanks to Paul for seeing what nobody else saw.
The codes shown below are CORRECT.


The Definition
Function ShiftRight
Shifts the bits to the right the specified number of positions and returns the new value.
Bits "falling off" the right edge do not wrap around. Fill bits coming in from left match bit 31 (the sign bit): if bit 31 is 1 the fill bits will be 1 (see ShiftRightZ for the alternative zero-fill-in version).

A shift right is effectively a division by 2 (rounding downward, see Examples). Some common languages like C/C++ or Java have an operator for this job: ">>".
Declaration
Function ShiftRight(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.
Examples
ShiftRight(6, 0) -> 6 (00000000000000000000000000000110)
ShiftRight(6, 1) -> 3 (00000000000000000000000000000011)
ShiftRight(6, 2) -> 1 (00000000000000000000000000000001)
ShiftRight(6, 3) -> 0 (00000000000000000000000000000000)

ShiftRight(-6, 0) -> -6 (11111111111111111111111111111010)
ShiftRight(-6, 1) -> -3 (11111111111111111111111111111101)
ShiftRight(-6, 2) -> -2 (11111111111111111111111111111110)
ShiftRight(-6, 3) -> -1 (11111111111111111111111111111111)
Note the asymmetry (marked red) due to effective downward rounding (when ShiftRight is interpreted as a division operation).
You may use this function (VB5/6-compatible) to verify the correctness of your code.


The Charts
Calls
Call 1 ShiftRight(256, 8) --> 1
Call 2 ShiftRight(&H87654321, 24) --> -121
Call 3 ShiftRight(-1, 31) --> -1
 VB5
CodeAuthorDopingNotes
ShiftRight05 Donald  
ShiftRight06 Donald  
ShiftRight07 PaulAPI,ASM 
ShiftRight08 Jost  
ShiftRight09 René  
Call 1
32.190.158µs
22.030.147µs
X0.520.037µs
11.000.072µs
424.311.752µs
Call 2
23.880.180µs
36.520.303µs
X0.810.038µs
11.000.046µs
437.781.752µs
Call 3
41.110.055µs
11.000.049µs
X0.760.037µs
21.020.050µs
31.040.051µs
 VB6
CodeAuthorDopingNotes
ShiftRight05 Donald  
ShiftRight06 Donald  
ShiftRight07 PaulAPI,ASM 
ShiftRight08 Jost  
ShiftRight09 René  
Call 1
32.300.193µs
22.240.187µs
X0.410.035µs
11.000.084µs
421.791.824µs
Call 2
24.480.208µs
37.200.333µs
X0.750.035µs
11.000.046µs
439.401.824µs
Call 3
21.010.049µs
11.000.049µs
X0.710.034µs
31.040.051µs
41.060.051µs
Conclusions
...
Mail your code! How to read all those numbers


The Code
ShiftRight05
submitted 09-Oct-2001 by Donald Lessau  
Doping: none
Public Static Function ShiftRight05(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by Donald, donald@xbeat.net, 20011009
  Dim lPow2(0 To 30) As Long
  Dim i As Long
  
  Select Case ShiftCount
  Case 0
    ShiftRight05 = Value
  Case 1 To 30
    If i = 0 Then
      lPow2(0) = 1
      For i = 1 To 30
        lPow2(i) = 2 * lPow2(i - 1)
      Next
    End If
    If Value And &H80000000 Then
      ShiftRight05 = Value \ lPow2(ShiftCount)
      If ShiftRight05 * lPow2(ShiftCount) <> Value Then
        ShiftRight05 = ShiftRight05 - 1
      End If
    Else
      ShiftRight05 = Value \ lPow2(ShiftCount)
    End If
  Case 31
    If Value And &H80000000 Then
      ShiftRight05 = -1
    Else
      ShiftRight05 = 0
    End If
  End Select
End Function
Author's comments:
Donald's comments:

top | charts


ShiftRight06
submitted 09-Oct-2001 by Donald Lessau  
Doping: none
Public Static Function ShiftRight06(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by Donald, donald@xbeat.net, 20011009
  Dim lPow2(0 To 30) As Long
  Dim i As Long
  
  Select Case ShiftCount
  Case 0 To 30
    If i = 0 Then
      lPow2(0) = 1
      For i = 1 To 30
        lPow2(i) = 2 * lPow2(i - 1)
      Next
    End If
    If Value And &H80000000 Then
      ShiftRight06 = Int(Value / lPow2(ShiftCount))
    Else
      ShiftRight06 = Value \ lPow2(ShiftCount)
    End If
  Case 31
    If Value And &H80000000 Then
      ShiftRight06 = -1
    Else
      ShiftRight06 = 0
    End If
  End Select
End Function
Author's comments:
Donald's comments:

top | charts


ShiftRight07
submitted 09-Oct-2001 by Paul    http://www.syix.com/wpsjr1/index.html
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


ShiftRight08
submitted 10-Oct-2001 by Jost Schwider    vb-tec.de
Doping: none
Public Function ShiftRight08(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by Jost Schwider, jost@schwider.de, 20011010
  Select Case ShiftCount
  Case 0&:  ShiftRight08 = Value
  Case 1&:  ShiftRight08 = (Value And &HFFFFFFFE) \ &H2&
  Case 2&:  ShiftRight08 = (Value And &HFFFFFFFC) \ &H4&
  Case 3&:  ShiftRight08 = (Value And &HFFFFFFF8) \ &H8&
  Case 4&:  ShiftRight08 = (Value And &HFFFFFFF0) \ &H10&
  Case 5&:  ShiftRight08 = (Value And &HFFFFFFE0) \ &H20&
  Case 6&:  ShiftRight08 = (Value And &HFFFFFFC0) \ &H40&
  Case 7&:  ShiftRight08 = (Value And &HFFFFFF80) \ &H80&
  Case 8&:  ShiftRight08 = (Value And &HFFFFFF00) \ &H100&
  Case 9&:  ShiftRight08 = (Value And &HFFFFFE00) \ &H200&
  Case 10&: ShiftRight08 = (Value And &HFFFFFC00) \ &H400&
  Case 11&: ShiftRight08 = (Value And &HFFFFF800) \ &H800&
  Case 12&: ShiftRight08 = (Value And &HFFFFF000) \ &H1000&
  Case 13&: ShiftRight08 = (Value And &HFFFFE000) \ &H2000&
  Case 14&: ShiftRight08 = (Value And &HFFFFC000) \ &H4000&
  Case 15&: ShiftRight08 = (Value And &HFFFF8000) \ &H8000&
  Case 16&: ShiftRight08 = (Value And &HFFFF0000) \ &H10000
  Case 17&: ShiftRight08 = (Value And &HFFFE0000) \ &H20000
  Case 18&: ShiftRight08 = (Value And &HFFFC0000) \ &H40000
  Case 19&: ShiftRight08 = (Value And &HFFF80000) \ &H80000
  Case 20&: ShiftRight08 = (Value And &HFFF00000) \ &H100000
  Case 21&: ShiftRight08 = (Value And &HFFE00000) \ &H200000
  Case 22&: ShiftRight08 = (Value And &HFFC00000) \ &H400000
  Case 23&: ShiftRight08 = (Value And &HFF800000) \ &H800000
  Case 24&: ShiftRight08 = (Value And &HFF000000) \ &H1000000
  Case 25&: ShiftRight08 = (Value And &HFE000000) \ &H2000000
  Case 26&: ShiftRight08 = (Value And &HFC000000) \ &H4000000
  Case 27&: ShiftRight08 = (Value And &HF8000000) \ &H8000000
  Case 28&: ShiftRight08 = (Value And &HF0000000) \ &H10000000
  Case 29&: ShiftRight08 = (Value And &HE0000000) \ &H20000000
  Case 30&: ShiftRight08 = (Value And &HC0000000) \ &H40000000
  Case 31&: ShiftRight08 = CBool(Value And &H80000000)
  End Select
End Function
Author's comments:
Donald's comments:

top | charts


ShiftRight09
submitted 20-Nov-2001 by René Rhéaume  
Doping: none
Public Function ShiftRight09(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by René Rhéaume, rener@mediom.qc.ca, 20011118 based on
' Jost Schwider ShiftRight08
  Const conMaxLong As Long = &HFFFFFFFF
  Dim lngPower2 As Long
  Select Case ShiftCount
  Case 0&:  ShiftRight09 = Value
  Case 1& To 30&
    lngPower2 = 2 ^ ShiftCount
    ShiftRight09 = (Value And conMaxLong - lngPower2& + 1&) \ lngPower2&
  Case 31&: ShiftRight09 = CBool(Value And &H80000000)
  End Select
End Function
Author's comments:
Donald's comments: ShiftRight08-generator.

top | charts




VBspeed © 2000-10 by Donald Lessau