Ignore:
Timestamp:
Oct 25, 2023, 12:33:07 AM (7 months ago)
Author:
chronos
Message:
  • Added: Common package.
  • Modified: Improved BigInt class.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/ByteArray/BigInt.pas

    r46 r47  
    99  TArrayOfByte = array of Byte;
    1010
     11  TBigIntSize = Byte;
     12
    1113  { TBigInt }
    1214
    1315  TBigInt = record
    1416  private
    15     function GetSize: Byte;
    16     procedure SetSize(AValue: Byte);
     17    FData: array of Byte;
     18    function GetData(Index: TBigIntSize): Byte;
     19    function GetSize: TBigIntSize;
     20    procedure SetData(Index: TBigIntSize; AValue: Byte);
     21    procedure SetSize(AValue: TBigIntSize);
    1722  public
    18     Data: array of Byte;
    1923    class operator Implicit(A: Byte): TBigInt;
    2024    class operator Implicit(A: Word): TBigInt;
     
    3337    class operator Implicit(A: TBigInt): PByte;
    3438    class operator Inc(A: TBigInt) : TBigInt;
     39    class operator Dec(A: TBigInt) : TBigInt;
    3540    class operator Add(A, B: TBigInt): TBigInt;
    3641    class operator Subtract(A, B: TBigInt): TBigInt;
     
    4247    class operator GreaterThanOrEqual(A, B: TBigInt): Boolean;
    4348    procedure Shrink;
    44     procedure SetByteArray(AData: TArrayOfByte; ASize: Byte);
    45     procedure GetByteArray(var AData: TArrayOfByte; ASize: Byte);
    46     function Copy(Size: Byte): TBigInt;
     49    procedure SetByteArray(AData: TArrayOfByte; ASize: TBigIntSize);
     50    procedure GetByteArray(var AData: TArrayOfByte; ASize: TBigIntSize);
     51    function Copy(Size: TBigIntSize): TBigInt;
    4752    property Size: Byte read GetSize write SetSize;
    48   end;
    49 
    50 function TryStrToBigInt(const S: string; Out I: TBigInt): Boolean;
     53    property Data[Index: TBigIntSize]: Byte read GetData write SetData;
     54  end;
     55
     56function TryStrToBigInt(const S: string; out I: TBigInt): Boolean;
     57
    5158
    5259implementation
    5360
    54 function TryStrToBigInt(const S: string; Out I: TBigInt): Boolean;
     61resourcestring
     62  SUnsupportedByteSize = 'Unsupported byte size';
     63
     64function TryStrToBigInt(const S: string; out I: TBigInt): Boolean;
    5565var
    5666  Value: Int64;
     
    6272{ TBigInt }
    6373
    64 function TBigInt.GetSize: Byte;
    65 begin
    66   Result := Length(Data);
    67 end;
    68 
    69 procedure TBigInt.SetSize(AValue: Byte);
    70 var
    71   LastSize: Byte;
     74function TBigInt.GetSize: TBigIntSize;
     75begin
     76  Result := Length(FData);
     77end;
     78
     79function TBigInt.GetData(Index: TBigIntSize): Byte;
     80begin
     81  if Index < Size then Result := FData[Index]
     82    else Result := 0;
     83end;
     84
     85procedure TBigInt.SetData(Index: TBigIntSize; AValue: Byte);
     86begin
     87  if Index > Size - 1 then Size := Index + 1;
     88  FData[Index] := AValue;
     89end;
     90
     91procedure TBigInt.SetSize(AValue: TBigIntSize);
     92var
     93  LastSize: TBigIntSize;
    7294begin
    7395  LastSize := GetSize;
    74   SetLength(Data, AValue);
     96  SetLength(FData, AValue);
    7597  if AValue > LastSize then
    76     FillChar(Data[LastSize], AValue - LastSize, 0);
     98    FillChar(FData[LastSize], AValue - LastSize, 0);
    7799end;
    78100
     
    80102begin
    81103  Result.Size := 1;
    82   Result.Data[0] := A;
     104  Result.FData[0] := A;
    83105end;
    84106
     
    86108begin
    87109  Result.Size := 2;
    88   PWord(@Result.Data[0])^ := A;
     110  PWord(@Result.FData[0])^ := A;
    89111  Result.Shrink;
    90112end;
     
    93115begin
    94116  Result.Size := 1;
    95   PByte(@Result.Data[0])^ := A;
     117  PByte(@Result.FData[0])^ := A;
    96118  Result.Shrink;
    97119end;
     
    100122begin
    101123  Result.Size := 4;
    102   PInteger(@Result.Data[0])^ := A;
     124  PInteger(@Result.FData[0])^ := A;
    103125  Result.Shrink;
    104126end;
     
    107129begin
    108130  Result.Size := 8;
    109   PQWord(@Result.Data[0])^ := A;
     131  PQWord(@Result.FData[0])^ := A;
    110132  Result.Shrink;
    111133end;
     
    114136begin
    115137  Result.Size := 8;
    116   PInt64(@Result.Data[0])^ := A;
     138  PInt64(@Result.FData[0])^ := A;
    117139  Result.Shrink;
    118140end;
     
    120142class operator TBigInt.Implicit(A: TBigInt): UInt8;
    121143begin
    122   if A.Size = 1 then Result := A.Data[0]
    123     else raise Exception.Create('x');
     144  if A.Size = 1 then Result := A.FData[0]
     145    else raise Exception.Create(SUnsupportedByteSize);
    124146end;
    125147
    126148class operator TBigInt.Implicit(A: TBigInt): Int8;
    127149begin
    128   if A.Size = 1 then Result := A.Data[0]
    129     else raise Exception.Create('x');
     150  if A.Size = 1 then Result := A.FData[0]
     151    else raise Exception.Create(SUnsupportedByteSize);
    130152end;
    131153
    132154class operator TBigInt.Implicit(A: TBigInt): UInt16;
    133155begin
    134   if A.Size = 2 then Result := PUInt16(@A.Data[0])^
    135     else raise Exception.Create('x');
     156  if A.Size = 2 then Result := PUInt16(@A.FData[0])^
     157    else raise Exception.Create(SUnsupportedByteSize);
    136158end;
    137159
    138160class operator TBigInt.Implicit(A: TBigInt): Int16;
    139161begin
    140   if A.Size = 2 then Result := PInt16(@A.Data[0])^
    141     else raise Exception.Create('x');
     162  if A.Size = 2 then Result := PInt16(@A.FData[0])^
     163    else raise Exception.Create(SUnsupportedByteSize);
    142164end;
    143165
     
    145167begin
    146168  case A.Size of
    147     1: Result := PByte(@A.Data[0])^;
    148     2: Result := PWord(@A.Data[0])^;
    149     4: Result := PDWord(@A.Data[0])^;
    150     8: Result := PQWord(@A.Data[0])^;
    151     else raise Exception.Create('x');
     169    1: Result := PByte(@A.FData[0])^;
     170    2: Result := PWord(@A.FData[0])^;
     171    3: Result := PWord(@A.FData[0])^ or (PByte(@A.FData[2])^ shl 16);
     172    4: Result := PDWord(@A.FData[0])^;
     173    8: Result := PQWord(@A.FData[0])^;
     174    else raise Exception.Create(SUnsupportedByteSize);
    152175  end;
    153176end;
     
    155178class operator TBigInt.Implicit(A: TBigInt): UInt32;
    156179begin
    157   if A.Size = 4 then Result := PInt32(@A.Data[0])^
    158     else raise Exception.Create('x');
     180  if A.Size = 4 then Result := PInt32(@A.FData[0])^
     181    else raise Exception.Create(SUnsupportedByteSize);
    159182end;
    160183
    161184class operator TBigInt.Implicit(A: TBigInt): UInt64;
    162185begin
    163   if A.Size = 8 then Result := PUInt64(@A.Data[0])^
    164     else raise Exception.Create('x');
     186  if A.Size = 8 then Result := PUInt64(@A.FData[0])^
     187    else raise Exception.Create(SUnsupportedByteSize);
    165188end;
    166189
    167190class operator TBigInt.Implicit(A: TBigInt): Int64;
    168191begin
    169   if A.Size = 8 then Result := PInt64(@A.Data[0])^
    170     else raise Exception.Create('x');
     192  if A.Size = 8 then Result := PInt64(@A.FData[0])^
     193    else raise Exception.Create(SUnsupportedByteSize);
    171194end;
    172195
    173196class operator TBigInt.Implicit(A: TBigInt): PByte;
    174197begin
    175   if A.Size = 4 then Result := PByte(@PInteger(@A.Data[0])^)
    176     else raise Exception.Create('x');
     198  if A.Size = 4 then Result := PByte(@PInteger(@A.FData[0])^)
     199    else raise Exception.Create(SUnsupportedByteSize);
    177200end;
    178201
    179202class operator TBigInt.Inc(A: TBigInt): TBigInt;
    180203begin
     204  Result := A + 1;
     205end;
     206
     207class operator TBigInt.Dec(A: TBigInt): TBigInt;
     208begin
     209  Result := A - 1;
     210end;
     211
     212class operator TBigInt.Add(A, B: TBigInt): TBigInt;
     213var
     214  I: Integer;
     215  V: SmallInt;
     216  Carry: Byte;
     217begin
     218  Result.Size := Max(A.Size, B.Size);
     219  Carry := 0;
     220  I := 0;
     221  while (I < Result.Size) or (Carry > 0) do begin
     222    V := A.Data[I] + B.Data[I] + Carry;
     223    if V >= 256 then begin
     224      Carry := 1;
     225    end else Carry := 0;
     226    Result.Data[I] := V and $ff;
     227    Inc(I);
     228  end;
     229end;
     230
     231class operator TBigInt.Subtract(A, B: TBigInt): TBigInt;
     232var
     233  I: Integer;
     234  V: SmallInt;
     235  Carry: Byte;
     236begin
    181237  Result.Size := A.Size;
    182   case Result.Size of
    183     1: PByte(@Result.Data[0])^ := PByte(@A.Data[0])^ + 1;
    184     2: PWord(@Result.Data[0])^ := PWord(@A.Data[0])^ + 1;
    185     4: PDWord(@Result.Data[0])^ := PDWord(@A.Data[0])^ + 1;
    186     8: PQWord(@Result.Data[0])^ := PQWord(@A.Data[0])^ + 1;
    187   end;
    188 end;
    189 
    190 class operator TBigInt.Add(A, B: TBigInt): TBigInt;
    191 var
    192   CommonSize: Byte;
    193 begin
    194   CommonSize := Max(A.Size, B.Size);
    195   A.Size := CommonSize;
    196   B.Size := CommonSize;
    197   Result.Size := CommonSize;
    198   case Result.Size of
    199     1: PByte(@Result.Data[0])^ := PByte(@A.Data[0])^ + PByte(@B.Data[0])^;
    200     2: PWord(@Result.Data[0])^ := PWord(@A.Data[0])^ + PWord(@B.Data[0])^;
    201     4: PDWord(@Result.Data[0])^ := PDWord(@A.Data[0])^ + PDWord(@B.Data[0])^;
    202     8: PQWord(@Result.Data[0])^ := PQWord(@A.Data[0])^ + PQWord(@B.Data[0])^;
    203   end;
    204 end;
    205 
    206 class operator TBigInt.Subtract(A, B: TBigInt): TBigInt;
    207 var
    208   CommonSize: Byte;
    209 begin
    210   CommonSize := Max(A.Size, B.Size);
    211   A.Size := CommonSize;
    212   B.Size := CommonSize;
    213   Result.Size := CommonSize;
    214   case Result.Size of
    215     1: PByte(@Result.Data[0])^ := PByte(@A.Data[0])^ - PByte(@B.Data[0])^;
    216     2: PWord(@Result.Data[0])^ := PWord(@A.Data[0])^ - PWord(@B.Data[0])^;
    217     4: PDWord(@Result.Data[0])^ := PDWord(@A.Data[0])^ - PDWord(@B.Data[0])^;
    218     8: PQWord(@Result.Data[0])^ := PQWord(@A.Data[0])^ - PQWord(@B.Data[0])^;
     238  Carry := 0;
     239  I := 0;
     240  while (I < Result.Size) or (Carry > 0) do begin
     241    V := A.Data[I] - B.Data[I] - Carry;
     242    if V < 0 then begin
     243      Carry := 1;
     244    end else Carry := 0;
     245    Result.Data[I] := V and $ff;
     246    Inc(I);
    219247  end;
    220248end;
    221249
    222250class operator TBigInt.Equal(A, B: TBigInt): Boolean;
    223 begin
    224 
     251var
     252  I: Byte;
     253begin
     254  Result := A.Size = B.Size;
     255  for I := 0 to A.Size - 1 do
     256    if A.FData[I] <> B.FData[I] then begin
     257      Result := False;
     258      Break;
     259    end;
    225260end;
    226261
    227262class operator TBigInt.NotEqual(A, B: TBigInt): Boolean;
    228 begin
    229 
     263var
     264  I: Byte;
     265begin
     266  Result := A.Size = B.Size;
     267  for I := 0 to A.Size - 1 do
     268    if A.FData[I] <> B.FData[I] then begin
     269      Result := False;
     270      Break;
     271    end;
     272  Result := not Result;
    230273end;
    231274
     
    255298begin
    256299  I := Size - 1;
    257   while (I > 0) and (Data[I] = 0) do
     300  while (I > 0) and (FData[I] = 0) do
    258301    Dec(I);
    259302  Size := I + 1;
    260303end;
    261304
    262 procedure TBigInt.SetByteArray(AData: TArrayOfByte; ASize: Byte);
     305procedure TBigInt.SetByteArray(AData: TArrayOfByte; ASize: TBigIntSize);
    263306begin
    264307  Size := ASize;
    265   Move(AData[0], Data[0], Size);
    266 end;
    267 
    268 procedure TBigInt.GetByteArray(var AData: TArrayOfByte; ASize: Byte);
     308  Move(AData[0], FData[0], Size);
     309end;
     310
     311procedure TBigInt.GetByteArray(var AData: TArrayOfByte; ASize: TBigIntSize);
    269312begin
    270313  SetLength(AData, ASize);
    271   Move(Data[0], AData[0], Size);
    272 end;
    273 
    274 function TBigInt.Copy(Size: Byte): TBigInt;
     314  Move(FData[0], AData[0], Size);
     315end;
     316
     317function TBigInt.Copy(Size: TBigIntSize): TBigInt;
    275318begin
    276319  Result.Size := Size;
    277320  case Result.Size of
    278     1: PByte(@Result.Data[0])^ := PByte(@Data[0])^;
    279     2: PWord(@Result.Data[0])^ := PWord(@Data[0])^;
    280     4: PDWord(@Result.Data[0])^ := PDWord(@Data[0])^;
    281     8: PQWord(@Result.Data[0])^ := PQWord(@Data[0])^;
     321    1: PByte(@Result.FData[0])^ := PByte(@FData[0])^;
     322    2: PWord(@Result.FData[0])^ := PWord(@FData[0])^;
     323    4: PDWord(@Result.FData[0])^ := PDWord(@FData[0])^;
     324    8: PQWord(@Result.FData[0])^ := PQWord(@FData[0])^;
    282325  end;
    283326end;
Note: See TracChangeset for help on using the changeset viewer.