Sometimes you need a little bitmanipulation, but you are worried about all those AND, OR, XOR, SHL and SHR? So why don't you give a simple but smart set a chance?

First of all, we give the bits names for better handling, then we defining the sets, that represent the bits in a machine word:

type Bits = (Bit0,  Bit1,  Bit2,  Bit3,  Bit4,
Bit5, Bit6, Bit7, Bit8, Bit9,
Bit10, Bit11, Bit12, Bit13, Bit14,
Bit15, Bit16, Bit17, Bit18, Bit19,
Bit20, Bit21, Bit22, Bit23, Bit24,
Bit25, Bit26, Bit27, Bit28, Bit29,
Bit30, Bit31, Bit32, Bit33, Bit34,
Bit35, Bit36, Bit37, Bit38, Bit39,
Bit40, Bit41, Bit42, Bit43, Bit44,
Bit45, Bit46, Bit47, Bit48, Bit49,
Bit50, Bit51, Bit52, Bit53, Bit54,
Bit55, Bit56, Bit57, Bit58, Bit59,
Bit60, Bit61, Bit62, Bit63);

// Now we define the sets:

type TByteBits = set of Bit0..Bit7;
TWordBits = set of Bit0..Bit15;
TLongBits = set of Bit0..Bit31;
TInt64Bits = set of Bit0..Bit63;
// or set of Bits;

Thats nearly all. To set, clear or test a bit, we just use the usual set operators:

To set a bit
Include (mybitset, Bit24);
To clear it
Exclude (mybitset, Bit15);
Test it
if Bit5 in mybitset then ...

Even you can do bitwise manipulation:

mybitset:= [Bit7, Bit8] * [Bit5, Bit6];
mybitset:= [Bit7, Bit5] + [Bit5, Bit6];

To transfer numeric values to the Bitsets you can use these functions:

function ValToByteBits
(CONST v8: Byte): TByteBits;
// convert a Byte to a Bitset
var b: TByteBits absolute v8;
Result:= b;

function ValToWordBits
(CONST v16: Word): TWordBits;
// convert a Word to a Bitset
var b: TWordBits absolute v16;
Result:= b;

function ValToLongBits
(CONST v32: Integer): TLongBits;
// convert a Longword to a Bitset
var b: TLongBits absolute v32;
Result:= b;

function ValToInt64Bits
(CONST v64: Int64): TInt64Bits;
// convert a Int64 to a Bitset
var b: TInt64Bits absolute i64;
Result:= b;

These functions turn the set back to an numeric value:

function BitsToByte
(CONST v8: TByteBits): Byte;
// convert a Bitset to a Byte
var b: Byte absolute v8;
Result:= b;

function BitsToWord
(CONST v16: TWordBits): Word;
// convert a Bitset to a Word
var b: Word absolute v16;
Result:= b;

function BitsToInteger
(CONST v32: TLongBits): Integer;
// convert a Bitset to a Integer
var b: Integer absolute v32;
Result:= b;

function BitsToInt64
(CONST v64: TInt64Bits): Int64;
// convert a Bitset to a Int64
var b: Int64 absolute v64;
Result:= b;

As you see, we use the absolute directive to advice the compiler to put the local variable "on top" of the function parameter. With this technique the compiler produces a minimum of code and we get high performance.

Counting Bits

As seen before, bit manipulation is an easy job if you treat the bits as a set. Now I will show you a function, that will count the number of Bits (or Elements) in a given variable. In this function we use a special Pascal feature, the anonymous parameter. The parameter setvar is declared without any type. In fact, when we call the function we can put any variable on this place - not only a set for example, but we need to know the concrete size in bytes of the parameter to avoid reading outside the variable. To inner restrictions of the function, the size of the variable is limited to 256 Bit (the maximum size for a set). If you need more, make the type TBitArray bigger.

function CountBits (CONST setvar; size: Integer): Integer;
// First we declare an array of Bitsets:
type TBitArray = array [0..31] of TByteBits;
// We set it on top of setvar
var bits: TBitArray absolute setvar;
    i, c: Integer; // counting variables
    b: Bits;
 c:= 0; // start value for number of bits
 // count the number of bytes
 for i:= 0 to size - 1 do begin
  // for each byte count the number of bits
  for b:= Bit0 to Bit7 do begin
   if b in bits[i] then Inc (c);
 Result:= c;