'===========================================================
' VBA における 32 ビット整数の高速ビットシフト関数群
' 論理左シフト(LogicalShiftLeft)、論理右シフト(LogicalShiftRight)、
' 算術右シフト(ArithmeticShiftRight)を高速かつ安全に実装。
' coded by isaku@pb4.so-net.ne.jp 2026
'===========================================================

Option Explicit

'-----------------------------------------------------------
' 高速論理左シフト:32ビット整数のビット列を shiftCount 分だけ左にシフトします。
' shiftCount の有効範囲は [1〜30] です。
'-----------------------------------------------------------
Public Function FastLogicalShiftLeft&(ByVal value&, ByVal shiftCount As Byte)
    Dim highBitMask&
    highBitMask = 2& ^ (31 - shiftCount)
    FastLogicalShiftLeft = (value And (highBitMask - 1)) * (2& ^ shiftCount)
    If (value And highBitMask) = highBitMask Then FastLogicalShiftLeft = FastLogicalShiftLeft Or &H80000000
End Function

'-----------------------------------------------------------
' 高速論理右シフト:32ビット整数のビット列を shiftCount 分だけ右にシフトします。
' shiftCount の有効範囲は [1〜30]。符号付き整数に対応。
'-----------------------------------------------------------
Public Function FastLogicalShiftRight&(ByVal value&, ByVal shiftCount As Byte)
    If value >= 0 Then
        FastLogicalShiftRight = value \ (2& ^ shiftCount)
    Else
        FastLogicalShiftRight = ((value And &H7FFFFFFF) \ (2& ^ shiftCount)) Or (2& ^ (31 - shiftCount))
    End If
End Function

'-----------------------------------------------------------
' 高速算術右シフト:符号ビットを保持したまま右にシフトします。
' shiftCount の有効範囲は [1〜30]。
'-----------------------------------------------------------
Public Function FastArithmeticShiftRight&(ByVal value&, ByVal shiftCount As Byte)
    FastArithmeticShiftRight = value \ (2& ^ shiftCount)
    If value < 0 And value Mod (2& ^ shiftCount) <> 0 Then FastArithmeticShiftRight = FastArithmeticShiftRight - 1
End Function

'-----------------------------------------------------------
' 論理左シフト:入力値の検証と境界条件の処理を含む安全な左シフト。
'-----------------------------------------------------------
Public Function LogicalShiftLeft&(ByVal value&, ByVal shiftCount As Byte)
    Dim highBitMask&
    shiftCount = shiftCount And 31 ' 0〜31 に制限
    
    Select Case shiftCount
        Case 0
            LogicalShiftLeft = value
        Case Is > 31
            LogicalShiftLeft = 0
        Case 31
            LogicalShiftLeft = IIf((value And 1) = 1, &H80000000, 0)
        Case Else
            highBitMask = 2& ^ (31 - shiftCount)
            LogicalShiftLeft = (value And (highBitMask - 1)) * (2& ^ shiftCount)
            If (value And highBitMask) = highBitMask Then LogicalShiftLeft = LogicalShiftLeft Or &H80000000
    End Select
End Function

'-----------------------------------------------------------
' 論理右シフト:入力値の検証と境界条件の処理を含む安全な右シフト。
'-----------------------------------------------------------
Public Function LogicalShiftRight&(ByVal value&, ByVal shiftCount As Byte)
    shiftCount = shiftCount And 31 ' 0〜31 に制限
    
    Select Case shiftCount
        Case 0
            LogicalShiftRight = value
        Case 31
            LogicalShiftRight = IIf(value < 0, 1, 0)
        Case Is > 31
            LogicalShiftRight = 0
        Case Else
            If value >= 0 Then
                LogicalShiftRight = value \ (2& ^ shiftCount)
            Else
                LogicalShiftRight = ((value And &H7FFFFFFF) \ (2& ^ shiftCount)) Or (2& ^ (31 - shiftCount))
            End If
    End Select
End Function

'-----------------------------------------------------------
' 算術右シフト:入力値の検証と境界条件の処理を含む安全な右シフト。
' 負の値に対して符号ビットを保持します。
'-----------------------------------------------------------
Public Function ArithmeticShiftRight&(ByVal value&, ByVal shiftCount As Byte)
    shiftCount = shiftCount And 31 ' 0〜31 に制限
    
    Select Case shiftCount
        Case 0
            ArithmeticShiftRight = value
        Case Is >= 31
            ArithmeticShiftRight = IIf(value < 0, -1, 0)
        Case Else
            ArithmeticShiftRight = value \ (2& ^ shiftCount)
            If value < 0 And value Mod (2& ^ shiftCount) <> 0 Then ArithmeticShiftRight = ArithmeticShiftRight - 1
    End Select
End Function