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.158s
22.030.147s
X0.520.037s
11.000.072s
424.311.752s
Call 2
23.880.180s
36.520.303s
X0.810.038s
11.000.046s
437.781.752s
Call 3
41.110.055s
11.000.049s
X0.760.037s
21.020.050s
31.040.051s
 VB6
CodeAuthorDopingNotes
ShiftRight05 Donald  
ShiftRight06 Donald  
ShiftRight07 PaulAPI,ASM 
ShiftRight08 Jost  
ShiftRight09 Ren  
Call 1
32.300.193s
22.240.187s
X0.410.035s
11.000.084s
421.791.824s
Call 2
24.480.208s
37.200.333s
X0.750.035s
11.000.046s
439.401.824s
Call 3
21.010.049s
11.000.049s
X0.710.034s
31.040.051s
41.060.051s
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 Rhaume  
Doping: none
Public Function ShiftRight09(ByVal Value As Long, ByVal ShiftCount As Long) As Long
' by Ren Rhaume, 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