uses
SysConst, RTLConsts, SysUtils;
const
MinInt = Low(Integer);
type
TIntegerPack =
Record
Private
FList:
Array of Record
Min, Max: Integer;
Value: Integer;
End;
FResult: UInt64;
FResSize: UInt64;
Function GetMin (
Index: Integer): Integer;
Function GetMax (
Index: Integer): Integer;
Function GetVal (
Index: Integer): Integer;
Procedure SetVal (
Index, X: Integer);
Procedure SetResult( X: UInt64);
Function GetSize (Bits: Integer): Integer;
Public
Function Add(Min, Max: Integer; Value: Integer = MinInt): Integer;
Property Min [
Index: Integer]: Integer
Read GetMin;
Property Max [
Index: Integer]: Integer
Read GetMax;
Property Value[
Index: Integer]: Integer
Read GetVal
Write SetVal;
Property Result: UInt64
Read FResult
Write SetResult;
Property ResSize: UInt64
Read FResSize;
Property Bytes: Integer
Index 8
Read GetSize;
Property Bits: Integer
Index 1
Read GetSize;
Procedure Clear;
End;
Function TIntegerPack.GetMin(
Index: Integer): Integer;
Begin
If Cardinal(
Index) >= Length(FList)
Then
Raise Exception.CreateResFmt(@SListIndexError, [
Index]);
Result := FList[
Index].Min;
End;
Function TIntegerPack.GetMax(
Index: Integer): Integer;
Begin
If Cardinal(
Index) >= Length(FList)
Then
Raise Exception.CreateResFmt(@SListIndexError, [
Index]);
Result := FList[
Index].Max;
End;
Function TIntegerPack.GetVal(
Index: Integer): Integer;
Begin
If Cardinal(
Index) >= Length(FList)
Then
Raise Exception.CreateResFmt(@SListIndexError, [
Index]);
Result := FList[
Index].Value;
End;
Procedure TIntegerPack.SetVal(
Index, X: Integer);
Begin
If Cardinal(
Index) >= Length(FList)
Then
Raise Exception.CreateResFmt(@SListIndexError, [
Index]);
If (X < FList[
Index].Min)
or (X > FList[
Index].Max)
Then
Raise Exception.CreateRes(@SArgumentOutOfRange);
FList[
Index].Value := X;
FResult := 0;
For Index := High(FList)
downto 0
do
With FList[
Index]
do
FResult := FResult * Cardinal(Max - Min + 1) + Cardinal(Value - Min);
End;
Procedure TIntegerPack.SetResult(X: UInt64);
Var Index: Integer;
Begin
For Index := 0
to High(FList)
do
With FList[
Index]
do Begin
Value := X
mod Cardinal(Max - Min + 1) + Min;
X := X
div Cardinal(Max - Min + 1);
End;
//If X <> 0 Then Raise ...;
FResult := 0;
For Index := High(FList)
downto 0
do
With FList[
Index]
do
FResult := FResult * Cardinal(Max - Min + 1) + Cardinal(Value - Min);
End;
Function TIntegerPack.GetSize(Bits: Integer): Integer;
Var X: UInt64;
Begin
Result := 0;
X := FResSize;
While X <> 0
do Begin
X := X
shr Bits;
Inc(Result);
End;
End;
Function TIntegerPack.Add(Min, Max: Integer; Value: Integer = MinInt): Integer;
Var Index: Integer;
X, T: Int64;
Begin
Result := Length(FList);
SetLength(FList, Result + 1);
Try
FList[Result].Min := Min;
FList[Result].Max := Max;
X := 1;
For Index := High(FList)
downto 0
do
With FList[
Index]
do Begin
T := X;
X := X * Cardinal(Max - Min + 1);
If X
div Cardinal(Max - Min + 1) <> T
Then
Raise EIntOverflow.CreateRes(@SIntOverflow);
End;
FResSize := X;
Except
SetLength(FList, High(FList));
Raise;
End;
If Value = MinInt
Then Value := Min;
SetVal(Result, Value);
End;
Procedure TIntegerPack.Clear;
Begin
FList :=
nil;
FResult := 0;
FResSize := 0;
End;