xtool/contrib/fundamentals/Utils/flcBits32.pas

786 lines
24 KiB
ObjectPascal

{******************************************************************************}
{ }
{ Library: Fundamentals 5.00 }
{ File name: flcBit32.pas }
{ File version: 5.03 }
{ Description: Bit function: 32 bit. }
{ }
{ Copyright: Copyright (c) 2001-2020, David J Butler }
{ All rights reserved. }
{ Redistribution and use in source and binary forms, with }
{ or without modification, are permitted provided that }
{ the following conditions are met: }
{ Redistributions of source code must retain the above }
{ copyright notice, this list of conditions and the }
{ following disclaimer. }
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
{ POSSIBILITY OF SUCH DAMAGE. }
{ }
{ Github: https://github.com/fundamentalslib }
{ E-mail: fundamentals.library at gmail.com }
{ }
{ Revision history: }
{ }
{ 2001/05/03 1.01 Improved bit functions. Added Pascal versions of }
{ assembly routines. }
{ 2015/06/07 4.02 Moved bit functions from cUtils to cBits32. }
{ 2016/01/09 5.03 Revised for Fundamentals 5. }
{ }
{ Supported compilers: }
{ }
{ Delphi XE7 Win32 5.03 2016/01/09 }
{ Delphi XE7 Win64 5.03 2016/01/09 }
{ Delphi 10 Win32 5.03 2016/01/09 }
{ Delphi 10 Win64 5.03 2016/01/09 }
{ }
{******************************************************************************}
{$INCLUDE ..\flcInclude.inc}
unit flcBits32;
interface
uses
{ Fundamentals }
flcStdTypes;
{ }
{ Bit functions }
{ }
function ClearBit32(const Value, BitIndex: Word32): Word32;
function SetBit32(const Value, BitIndex: Word32): Word32;
function IsBitSet32(const Value, BitIndex: Word32): Boolean;
function ToggleBit32(const Value, BitIndex: Word32): Word32;
function IsHighBitSet32(const Value: Word32): Boolean;
function SetBitScanForward32(const Value: Word32): Integer; overload;
function SetBitScanForward32(const Value, BitIndex: Word32): Integer; overload;
function SetBitScanReverse32(const Value: Word32): Integer; overload;
function SetBitScanReverse32(const Value, BitIndex: Word32): Integer; overload;
function ClearBitScanForward32(const Value: Word32): Integer; overload;
function ClearBitScanForward32(const Value, BitIndex: Word32): Integer; overload;
function ClearBitScanReverse32(const Value: Word32): Integer; overload;
function ClearBitScanReverse32(const Value, BitIndex: Word32): Integer; overload;
function ReverseBits32(const Value: Word32): Word32; overload;
function ReverseBits32(const Value: Word32; const BitCount: Integer): Word32; overload;
function SwapEndian32(const Value: Word32): Word32;
procedure SwapEndianBuf32(var Buf; const Count: Integer);
function TwosComplement32(const Value: Word32): Word32;
function RotateLeftBits16(const Value: Word; const Bits: Byte): Word;
function RotateLeftBits32(const Value: Word32; const Bits: Byte): Word32;
function RotateRightBits16(const Value: Word; const Bits: Byte): Word;
function RotateRightBits32(const Value: Word32; const Bits: Byte): Word32;
function BitCount32(const Value: Word32): Word32;
function IsPowerOfTwo32(const Value: Word32): Boolean;
function LowBitMask32(const HighBitIndex: Word32): Word32;
function HighBitMask32(const LowBitIndex: Word32): Word32;
function RangeBitMask32(const LowBitIndex, HighBitIndex: Word32): Word32;
function SetBitRange32(const Value: Word32;
const LowBitIndex, HighBitIndex: Word32): Word32;
function ClearBitRange32(const Value: Word32;
const LowBitIndex, HighBitIndex: Word32): Word32;
function ToggleBitRange32(const Value: Word32;
const LowBitIndex, HighBitIndex: Word32): Word32;
function IsBitRangeSet32(const Value: Word32;
const LowBitIndex, HighBitIndex: Word32): Boolean;
function IsBitRangeClear32(const Value: Word32;
const LowBitIndex, HighBitIndex: Word32): Boolean;
const
BitMaskTable32: array[0..31] of Word32 =
($00000001, $00000002, $00000004, $00000008,
$00000010, $00000020, $00000040, $00000080,
$00000100, $00000200, $00000400, $00000800,
$00001000, $00002000, $00004000, $00008000,
$00010000, $00020000, $00040000, $00080000,
$00100000, $00200000, $00400000, $00800000,
$01000000, $02000000, $04000000, $08000000,
$10000000, $20000000, $40000000, $80000000);
{ }
{ Test cases }
{ }
{$IFDEF DEBUG}
{$IFDEF TEST}
procedure Test;
{$ENDIF}
{$ENDIF}
implementation
{ }
{ Bit functions }
{ }
{$IFDEF ASM386_DELPHI}
function ReverseBits32(const Value: Word32): Word32; register; assembler;
asm
BSWAP EAX
MOV EDX, EAX
AND EAX, 0AAAAAAAAh
SHR EAX, 1
AND EDX, 055555555h
SHL EDX, 1
OR EAX, EDX
MOV EDX, EAX
AND EAX, 0CCCCCCCCh
SHR EAX, 2
AND EDX, 033333333h
SHL EDX, 2
OR EAX, EDX
MOV EDX, EAX
AND EAX, 0F0F0F0F0h
SHR EAX, 4
AND EDX, 00F0F0F0Fh
SHL EDX, 4
OR EAX, EDX
end;
{$ELSE}
function ReverseBits32(const Value: Word32): Word32;
var I : Byte;
begin
Result := 0;
for I := 0 to 31 do
if Value and BitMaskTable32[I] <> 0 then
Result := Result or BitMaskTable32[31 - I];
end;
{$ENDIF}
function ReverseBits32(const Value: Word32; const BitCount: Integer): Word32;
var I, C : Integer;
V : Word32;
begin
V := Value;
Result := 0;
C := BitCount;
if C > 32 then
C := 32;
for I := 0 to C - 1 do
begin
Result := (Result shl 1) or (V and 1);
V := V shr 1;
end;
end;
{$IFDEF ASM386_DELPHI}
function SwapEndian32(const Value: Word32): Word32; register; assembler;
asm
XCHG AH, AL
ROL EAX, 16
XCHG AH, AL
end;
{$ELSE}
function SwapEndian32(const Value: Word32): Word32;
begin
Result := ((Value and $000000FF) shl 24) or
((Value and $0000FF00) shl 8) or
((Value and $00FF0000) shr 8) or
((Value and $FF000000) shr 24);
end;
{$ENDIF}
procedure SwapEndianBuf32(var Buf; const Count: Integer);
var P : PWord32;
I : Integer;
begin
P := @Buf;
for I := 1 to Count do
begin
P^ := SwapEndian32(P^);
Inc(P);
end;
end;
{$IFDEF ASM386_DELPHI}
function TwosComplement32(const Value: Word32): Word32; register; assembler;
asm
NEG EAX
end;
{$ELSE}
function TwosComplement32(const Value: Word32): Word32;
begin
Result := Word32(not Value + 1);
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function RotateLeftBits16(const Value: Word; const Bits: Byte): Word;
asm
MOV CL, DL
ROL AX, CL
end;
{$ELSE}
function RotateLeftBits16(const Value: Word; const Bits: Byte): Word;
var I, B : Integer;
R : Word;
begin
R := Value;
if Bits >= 16 then
B := Bits mod 16
else
B := Bits;
for I := 1 to B do
if R and $8000 = 0 then
R := Word(R shl 1)
else
R := Word(R shl 1) or 1;
Result := R;
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function RotateLeftBits32(const Value: Word32; const Bits: Byte): Word32;
asm
MOV CL, DL
ROL EAX, CL
end;
{$ELSE}
function RotateLeftBits32(const Value: Word32; const Bits: Byte): Word32;
var I, B : Integer;
R : Word32;
begin
R := Value;
if Bits >= 32 then
B := Bits mod 32
else
B := Bits;
for I := 1 to B do
if R and $80000000 = 0 then
R := Word32(R shl 1)
else
R := Word32(R shl 1) or 1;
Result := R;
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function RotateRightBits16(const Value: Word; const Bits: Byte): Word;
asm
MOV CL, DL
ROR AX, CL
end;
{$ELSE}
function RotateRightBits16(const Value: Word; const Bits: Byte): Word;
var I, B : Integer;
R : Word;
begin
R := Value;
if Bits >= 16 then
B := Bits mod 16
else
B := Bits;
for I := 1 to B do
if R and 1 = 0 then
R := Word(R shr 1)
else
R := Word(R shr 1) or $8000;
Result := R;
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function RotateRightBits32(const Value: Word32; const Bits: Byte): Word32;
asm
MOV CL, DL
ROR EAX, CL
end;
{$ELSE}
function RotateRightBits32(const Value: Word32; const Bits: Byte): Word32;
var I, B : Integer;
R : Word32;
begin
R := Value;
if Bits >= 32 then
B := Bits mod 32
else
B := Bits;
for I := 1 to B do
if R and 1 = 0 then
R := Word32(R shr 1)
else
R := Word32(R shr 1) or $80000000;
Result := R;
end;
{$ENDIF}
{$IFDEF ___ASM386_DELPHI}
function SetBit32(const Value, BitIndex: Word32): Word32;
asm
{$IFOPT R+}
CMP BitIndex, 32
JB @RangeOk
JMP RaiseRangeCheckError
@RangeOk:
{$ENDIF}
OR EAX, DWORD PTR [BitIndex * 4 + BitMaskTable32]
end;
{$ELSE}
function SetBit32(const Value, BitIndex: Word32): Word32;
begin
Result := Value or BitMaskTable32[BitIndex];
end;
{$ENDIF}
{$IFDEF ___ASM386_DELPHI}
function ClearBit32(const Value, BitIndex: Word32): Word32;
asm
{$IFOPT R+}
CMP BitIndex, 32
JB @RangeOk
JMP RaiseRangeCheckError
@RangeOk:
{$ENDIF}
MOV ECX, DWORD PTR [BitIndex * 4 + BitMaskTable32]
NOT ECX
AND EAX, ECX
@Fin:
end;
{$ELSE}
function ClearBit32(const Value, BitIndex: Word32): Word32;
begin
Result := Value and not BitMaskTable32[BitIndex];
end;
{$ENDIF}
{$IFDEF ___ASM386_DELPHI}
function ToggleBit32(const Value, BitIndex: Word32): Word32;
asm
{$IFOPT R+}
CMP BitIndex, 32
JB @RangeOk
JMP RaiseRangeCheckError
@RangeOk:
{$ENDIF}
XOR EAX, DWORD PTR [BitIndex * 4 + BitMaskTable32]
end;
{$ELSE}
function ToggleBit32(const Value, BitIndex: Word32): Word32;
begin
Result := Value xor BitMaskTable32[BitIndex];
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function IsHighBitSet32(const Value: Word32): Boolean; register; assembler;
asm
TEST Value, $80000000
SETNZ AL
end;
{$ELSE}
function IsHighBitSet32(const Value: Word32): Boolean;
begin
Result := Value and $80000000 <> 0;
end;
{$ENDIF}
{$IFDEF ___ASM386_DELPHI}
function IsBitSet32(const Value, BitIndex: Word32): Boolean;
asm
{$IFOPT R+}
CMP BitIndex, 32
JB @RangeOk
JMP RaiseRangeCheckError
@RangeOk:
{$ENDIF}
MOV ECX, DWORD PTR BitMaskTable32 [BitIndex * 4]
TEST Value, ECX
SETNZ AL
end;
{$ELSE}
function IsBitSet32(const Value, BitIndex: Word32): Boolean;
begin
Result := Value and BitMaskTable32[BitIndex] <> 0;
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function SetBitScanForward32(const Value: Word32): Integer;
asm
OR EAX, EAX
JZ @NoBits
BSF EAX, EAX
RET
@NoBits:
MOV EAX, -1
end;
function SetBitScanForward32(const Value, BitIndex: Word32): Integer;
asm
CMP BitIndex, 32
JAE @NotFound
MOV ECX, BitIndex
MOV EDX, $FFFFFFFF
SHL EDX, CL
AND EDX, EAX
JE @NotFound
BSF EAX, EDX
RET
@NotFound:
MOV EAX, -1
end;
{$ELSE}
function SetBitScanForward32(const Value, BitIndex: Word32): Integer;
var I : Integer;
begin
if BitIndex < 32 then
for I := Integer(BitIndex) to 31 do
if Value and BitMaskTable32[I] <> 0 then
begin
Result := I;
exit;
end;
Result := -1;
end;
function SetBitScanForward32(const Value: Word32): Integer;
begin
Result := SetBitScanForward32(Value, 0);
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function SetBitScanReverse32(const Value: Word32): Integer;
asm
OR EAX, EAX
JZ @NoBits
BSR EAX, EAX
RET
@NoBits:
MOV EAX, -1
end;
function SetBitScanReverse32(const Value, BitIndex: Word32): Integer;
asm
CMP EDX, 32
JAE @NotFound
LEA ECX, [EDX - 31]
MOV EDX, $FFFFFFFF
NEG ECX
SHR EDX, CL
AND EDX, EAX
JE @NotFound
BSR EAX, EDX
RET
@NotFound:
MOV EAX, -1
end;
{$ELSE}
function SetBitScanReverse32(const Value, BitIndex: Word32): Integer;
var I : Integer;
begin
if BitIndex < 32 then
for I := Integer(BitIndex) downto 0 do
if Value and BitMaskTable32[I] <> 0 then
begin
Result := I;
exit;
end;
Result := -1;
end;
function SetBitScanReverse32(const Value: Word32): Integer;
begin
Result := SetBitScanReverse32(Value, 31);
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function ClearBitScanForward32(const Value: Word32): Integer;
asm
NOT EAX
OR EAX, EAX
JZ @NoBits
BSF EAX, EAX
RET
@NoBits:
MOV EAX, -1
end;
function ClearBitScanForward32(const Value, BitIndex: Word32): Integer;
asm
CMP EDX, 32
JAE @NotFound
MOV ECX, EDX
MOV EDX, $FFFFFFFF
NOT EAX
SHL EDX, CL
AND EDX, EAX
JE @NotFound
BSF EAX, EDX
RET
@NotFound:
MOV EAX, -1
end;
{$ELSE}
function ClearBitScanForward32(const Value, BitIndex: Word32): Integer;
var I : Integer;
begin
if BitIndex < 32 then
for I := Integer(BitIndex) to 31 do
if Value and BitMaskTable32[I] = 0 then
begin
Result := I;
exit;
end;
Result := -1;
end;
function ClearBitScanForward32(const Value: Word32): Integer;
begin
Result := ClearBitScanForward32(Value, 0);
end;
{$ENDIF}
{$IFDEF ASM386_DELPHI}
function ClearBitScanReverse32(const Value: Word32): Integer;
asm
NOT EAX
OR EAX, EAX
JZ @NoBits
BSR EAX, EAX
RET
@NoBits:
MOV EAX, -1
end;
function ClearBitScanReverse32(const Value, BitIndex: Word32): Integer;
asm
CMP EDX, 32
JAE @NotFound
LEA ECX, [EDX - 31]
MOV EDX, $FFFFFFFF
NEG ECX
NOT EAX
SHR EDX, CL
AND EDX, EAX
JE @NotFound
BSR EAX, EDX
RET
@NotFound:
MOV EAX, -1
end;
{$ELSE}
function ClearBitScanReverse32(const Value, BitIndex: Word32): Integer;
var I : Integer;
begin
if BitIndex < 32 then
for I := Integer(BitIndex) downto 0 do
if Value and BitMaskTable32[I] = 0 then
begin
Result := I;
exit;
end;
Result := -1;
end;
function ClearBitScanReverse32(const Value: Word32): Integer;
begin
Result := ClearBitScanReverse32(Value, 31);
end;
{$ENDIF}
const
BitCountTable32 : array[Byte] of Byte =
(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8);
{$IFDEF ASM386_DELPHI}
function BitCount32(const Value: Word32): Word32; register; assembler;
asm
MOVZX EDX, AL
MOVZX EDX, BYTE PTR [EDX + BitCountTable32]
MOVZX ECX, AH
ADD DL, BYTE PTR [ECX + BitCountTable32]
SHR EAX, 16
MOVZX ECX, AH
ADD DL, BYTE PTR [ECX + BitCountTable32]
AND EAX, $FF
ADD DL, BYTE PTR [EAX + BitCountTable32]
MOV AL, DL
end;
{$ELSE}
function BitCount32(const Value: Word32): Word32;
begin
Result := BitCountTable32[(Value and $000000FF) ] +
BitCountTable32[(Value and $0000FF00) shr 8 ] +
BitCountTable32[(Value and $00FF0000) shr 16] +
BitCountTable32[(Value and $FF000000) shr 24];
end;
{$ENDIF}
function IsPowerOfTwo32(const Value: Word32): Boolean;
begin
Result := BitCount32(Value) = 1;
end;
function LowBitMask32(const HighBitIndex: Word32): Word32;
begin
if HighBitIndex >= 32 then
Result := 0
else
Result := BitMaskTable32[HighBitIndex] - 1;
end;
function HighBitMask32(const LowBitIndex: Word32): Word32;
begin
if LowBitIndex >= 32 then
Result := 0
else
Result := not BitMaskTable32[LowBitIndex] + 1;
end;
function RangeBitMask32(const LowBitIndex, HighBitIndex: Word32): Word32;
begin
if (LowBitIndex >= 32) and (HighBitIndex >= 32) then
begin
Result := 0;
exit;
end;
Result := $FFFFFFFF;
if LowBitIndex > 0 then
Result := Result xor (BitMaskTable32[LowBitIndex] - 1);
if HighBitIndex < 31 then
Result := Result xor (not BitMaskTable32[HighBitIndex + 1] + 1);
end;
function SetBitRange32(const Value: Word32; const LowBitIndex, HighBitIndex: Word32): Word32;
begin
Result := Value or RangeBitMask32(LowBitIndex, HighBitIndex);
end;
function ClearBitRange32(const Value: Word32; const LowBitIndex, HighBitIndex: Word32): Word32;
begin
Result := Value and not RangeBitMask32(LowBitIndex, HighBitIndex);
end;
function ToggleBitRange32(const Value: Word32; const LowBitIndex, HighBitIndex: Word32): Word32;
begin
Result := Value xor RangeBitMask32(LowBitIndex, HighBitIndex);
end;
function IsBitRangeSet32(const Value: Word32; const LowBitIndex, HighBitIndex: Word32): Boolean;
var M: Word32;
begin
M := RangeBitMask32(LowBitIndex, HighBitIndex);
Result := Value and M = M;
end;
function IsBitRangeClear32(const Value: Word32; const LowBitIndex, HighBitIndex: Word32): Boolean;
begin
Result := Value and RangeBitMask32(LowBitIndex, HighBitIndex) = 0;
end;
{ }
{ Test cases }
{ }
{$IFDEF DEBUG}
{$IFDEF TEST}
{$ASSERTIONS ON}
procedure Test;
begin
Assert(SetBit32($100F, 5) = $102F, 'SetBit');
Assert(ClearBit32($102F, 5) = $100F, 'ClearBit');
Assert(ToggleBit32($102F, 5) = $100F, 'ToggleBit');
Assert(ToggleBit32($100F, 5) = $102F, 'ToggleBit');
Assert(IsBitSet32($102F, 5), 'IsBitSet');
Assert(not IsBitSet32($100F, 5), 'IsBitSet');
Assert(IsHighBitSet32($80000000), 'IsHighBitSet');
Assert(not IsHighBitSet32($00000001), 'IsHighBitSet');
Assert(not IsHighBitSet32($7FFFFFFF), 'IsHighBitSet');
Assert(SetBitScanForward32(0) = -1, 'SetBitScanForward');
Assert(SetBitScanForward32($1020) = 5, 'SetBitScanForward');
Assert(SetBitScanReverse32($1020) = 12, 'SetBitScanForward');
Assert(SetBitScanForward32($1020, 6) = 12, 'SetBitScanForward');
Assert(SetBitScanReverse32($1020, 11) = 5, 'SetBitScanForward');
Assert(ClearBitScanForward32($FFFFFFFF) = -1, 'ClearBitScanForward');
Assert(ClearBitScanForward32($1020) = 0, 'ClearBitScanForward');
Assert(ClearBitScanReverse32($1020) = 31, 'ClearBitScanForward');
Assert(ClearBitScanForward32($1020, 5) = 6, 'ClearBitScanForward');
Assert(ClearBitScanReverse32($1020, 12) = 11, 'ClearBitScanForward');
Assert(ReverseBits32($12345678) = $1E6A2C48, 'ReverseBits');
Assert(ReverseBits32($1) = $80000000, 'ReverseBits');
Assert(ReverseBits32($80000000) = $1, 'ReverseBits');
Assert(SwapEndian32($12345678) = $78563412, 'SwapEndian');
Assert(BitCount32($12341234) = 10, 'BitCount');
Assert(IsPowerOfTwo32(1), 'IsPowerOfTwo');
Assert(IsPowerOfTwo32(2), 'IsPowerOfTwo');
Assert(not IsPowerOfTwo32(3), 'IsPowerOfTwo');
Assert(RotateLeftBits32(0, 1) = 0, 'RotateLeftBits32');
Assert(RotateLeftBits32(1, 0) = 1, 'RotateLeftBits32');
Assert(RotateLeftBits32(1, 1) = 2, 'RotateLeftBits32');
Assert(RotateLeftBits32($80000000, 1) = 1, 'RotateLeftBits32');
Assert(RotateLeftBits32($80000001, 1) = 3, 'RotateLeftBits32');
Assert(RotateLeftBits32(1, 2) = 4, 'RotateLeftBits32');
Assert(RotateLeftBits32(1, 31) = $80000000, 'RotateLeftBits32');
Assert(RotateLeftBits32(5, 2) = 20, 'RotateLeftBits32');
Assert(RotateRightBits32(0, 1) = 0, 'RotateRightBits32');
Assert(RotateRightBits32(1, 0) = 1, 'RotateRightBits32');
Assert(RotateRightBits32(1, 1) = $80000000, 'RotateRightBits32');
Assert(RotateRightBits32(2, 1) = 1, 'RotateRightBits32');
Assert(RotateRightBits32(4, 2) = 1, 'RotateRightBits32');
Assert(LowBitMask32(10) = $3FF, 'LowBitMask');
Assert(HighBitMask32(28) = $F0000000, 'HighBitMask');
Assert(RangeBitMask32(2, 6) = $7C, 'RangeBitMask');
Assert(SetBitRange32($101, 2, 6) = $17D, 'SetBitRange');
Assert(ClearBitRange32($17D, 2, 6) = $101, 'ClearBitRange');
Assert(ToggleBitRange32($17D, 2, 6) = $101, 'ToggleBitRange');
Assert(IsBitRangeSet32($17D, 2, 6), 'IsBitRangeSet');
Assert(not IsBitRangeSet32($101, 2, 6), 'IsBitRangeSet');
Assert(not IsBitRangeClear32($17D, 2, 6), 'IsBitRangeClear');
Assert(IsBitRangeClear32($101, 2, 6), 'IsBitRangeClear');
end;
{$ENDIF}
{$ENDIF}
end.