home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************}
- {* AABitSet *}
- {* Copyright (c) Julian M Bucknall 1999 *}
- {* All rights reserved. *}
- {*********************************************************}
- {* Algorithms Alfresco bitset *}
- {*********************************************************}
-
- {Note: this unit is released as freeware. In other words, you are free
- to use this unit in your own applications, however I retain all
- copyright to the code. JMB}
-
- unit AABitSet;
-
- interface
-
- uses
- SysUtils;
-
- type
- {$IFDEF Windows}
- TaaMemSizeType = word;
- {$ELSE}
- TaaMemSizeType = integer;
- {$ENDIF}
-
- TaaBitSet = class
- private
- FBitArray : PByteArray;
- FBitArraySize : TaaMemSizeType;
- FBitCount : longint;
- FSetBitCount : longint;
- protected
- function bsGetBit(aIndex : longint) : boolean;
- procedure bsSetBit(aIndex : longint; aValue : boolean);
-
- procedure bsRecountSetBits;
- public
- constructor Create(aBitCount : longint);
- destructor Destroy; override;
-
- procedure ClearAllBits;
- {-clear all bits}
- procedure SetAllBits;
- {-set all bits}
-
- function GetNextBit : longint;
- {-find a false bit, set it true, and return its index}
-
- procedure AndBitSet(aBitSet : TaaBitSet);
- {-AND the given bitset with ours}
- procedure NotBitSet;
- {-NOT all bits in our bitset}
- procedure OrBitSet(aBitSet : TaaBitSet);
- {-OR the given bitset with ours}
- procedure XorBitSet(aBitSet : TaaBitSet);
- {-XOR the given bitset with ours}
-
- property Bits[aIndex : longint] : boolean
- read bsGetBit write bsSetBit; default;
-
- property BitCount : longint read FBitCount;
- property SetBitCount : longint read FSetBitCount;
- end;
-
- implementation
-
- {====================================================================}
- constructor TaaBitSet.Create(aBitCount : longint);
- begin
- inherited Create;
- if (aBitCount <= 0) then
- raise Exception.Create('TaaBitSet.Create: The number of bits must be greater than zero');
- {$IFDEF Windows}
- if (aBitCount > 524000) then
- raise Exception.Create('TaaBitSet.Create: In Delphi 1, the number of bits must be less than 524000');
- {$ENDIF}
- FBitArraySize := (aBitCount + 7) div 8;
- FBitCount := aBitCount;
- FBitArray := AllocMem(FBitArraySize);
- end;
- {--------}
- destructor TaaBitSet.Destroy;
- begin
- if (FBitArray <> nil) then begin
- FreeMem(FBitArray, FBitArraySize);
- FBitArray := nil;
- end;
- inherited Destroy;
- end;
- {--------}
- procedure TaaBitSet.AndBitSet(aBitSet : TaaBitSet);
- var
- i : longint;
- begin
- if (BitCount <> aBitSet.BitCount) then
- raise Exception.Create('TaaBitSet.AndBitSet: The bitsets must have the same number of bits');
- for i := 0 to pred(FBitArraySize) do
- FBitArray^[i] := FBitArray^[i] and aBitSet.FBitArray^[i];
- bsRecountSetBits;
- end;
- {--------}
- function TaaBitSet.bsGetBit(aIndex : longint) : boolean;
- var
- BytePtr : ^byte;
- Mask : byte;
- begin
- BytePtr := @FBitArray^[aIndex div 8];
- Mask := 1 shl (aIndex mod 8);
- Result := (BytePtr^ and Mask) <> 0;
- end;
- {--------}
- procedure TaaBitSet.bsRecountSetBits;
- const
- BitsPerByte : 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);
- var
- i : TaaMemSizeType;
- NewCount : longint;
- FullBytes : TaaMemSizeType;
- begin
- {do the easy count first}
- NewCount := 0;
- FullBytes := BitCount div 8;
- for i := 0 to pred(FullBytes) do
- inc(NewCount, BitsPerByte[FBitArray^[i]]);
- {now count the last 1 to 7 booleans}
- for i := (FullBytes * 8) to pred(BitCount) do
- if Bits[i] then
- inc(NewCount);
- FSetBitCount := NewCount;
- end;
- {--------}
- procedure TaaBitSet.bsSetBit(aIndex : longint; aValue : boolean);
- var
- BytePtr : ^byte;
- Mask : byte;
- begin
- BytePtr := @FBitArray^[aIndex div 8];
- Mask := 1 shl (aIndex mod 8);
- if aValue then begin
- if ((BytePtr^ and Mask) = 0) then
- inc(FSetBitCount);
- BytePtr^ := BytePtr^ or Mask;
- end
- else begin
- if ((BytePtr^ and Mask) <> 0) then
- dec(FSetBitCount);
- BytePtr^ := BytePtr^ and (not Mask);
- end;
- end;
- {--------}
- procedure TaaBitSet.ClearAllBits;
- begin
- FillChar(FBitArray^, FBitArraySize, 0);
- FSetBitCount := 0;
- end;
- {--------}
- function TaaBitSet.GetNextBit : longint;
- var
- i : TaaMemSizeType;
- ByteInx : longint;
- FullBytes : TaaMemSizeType;
- OurByte : byte;
- Mask : byte;
- begin
- {first find a byte that's not $FF, excluding the last byte; this
- means that byte has clear bits}
- ByteInx := -1;
- FullBytes := BitCount div 8;
- for i := 0 to pred(FullBytes) do
- if (FBitArray^[i] <> $FF) then begin
- ByteInx := i;
- Break;
- end;
- {if we found a byte, then work out the index of the bit that's free}
- if (ByteInx <> -1) then begin
- Mask := 1;
- OurByte := FBitArray^[ByteInx];
- for i := 0 to 7 do begin
- if ((OurByte and Mask) = 0) then begin
- Result := (ByteInx * 8) + i;
- FBitArray^[ByteInx] := FBitArray^[ByteInx] or Mask;
- inc(FSetBitCount);
- Exit;
- end;
- Mask := Mask * 2;
- end;
- end
- {otherwise check the 1-7 bits in the final byte}
- else begin
- for i := (FullBytes * 8) to pred(BitCount) do
- if not Bits[i] then begin
- Result := i;
- Bits[i] := true;
- Exit;
- end;
- end;
- {we failed to find a clear bit}
- Result := -1;
- end;
- {--------}
- procedure TaaBitSet.NotBitSet;
- var
- i : integer;
- begin
- for i := 0 to pred(FBitArraySize) do
- FBitArray^[i] := not FBitArray^[i];
- FSetBitCount := BitCount - FSetBitCount;
- end;
- {--------}
- procedure TaaBitSet.OrBitSet(aBitSet : TaaBitSet);
- var
- i : longint;
- begin
- if (BitCount <> aBitSet.BitCount) then
- raise Exception.Create('TaaBitSet.OrBitSet: The bitsets must have the same number of bits');
- for i := 0 to pred(FBitArraySize) do
- FBitArray^[i] := FBitArray^[i] or aBitSet.FBitArray^[i];
- bsRecountSetBits;
- end;
- {--------}
- procedure TaaBitSet.SetAllBits;
- begin
- FillChar(FBitArray^, FBitArraySize, $FF);
- FSetBitCount := FBitCount;
- end;
- {--------}
- procedure TaaBitSet.XorBitSet(aBitSet : TaaBitSet);
- var
- i : longint;
- begin
- if (BitCount <> aBitSet.BitCount) then
- raise Exception.Create('TaaBitSet.XorBitSet: The bitsets must have the same number of bits');
- for i := 0 to pred(FBitArraySize) do
- FBitArray^[i] := FBitArray^[i] xor aBitSet.FBitArray^[i];
- bsRecountSetBits;
- end;
- {====================================================================}
-
- end.
-