Ignore:
Timestamp:
Nov 22, 2023, 10:09:35 PM (10 months ago)
Author:
chronos
Message:
  • Modified: Extended BigInt type implementation.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/ByteArray/BigInt.pas

    r52 r55  
    3636    class operator Implicit(A: TBigInt): Int64;
    3737    class operator Implicit(A: TBigInt): PByte;
     38    class operator Negative(A: TBigInt): TBigInt;
    3839    class operator Inc(A: TBigInt) : TBigInt;
    3940    class operator Dec(A: TBigInt) : TBigInt;
     
    4647    class operator GreaterThan(A, B: TBigInt): Boolean;
    4748    class operator GreaterThanOrEqual(A, B: TBigInt): Boolean;
     49    class operator BitwiseXor(A, B: TBigInt): TBigInt;
     50    class operator BitwiseAnd(A, B: TBigInt): TBigInt;
     51    class operator BitwiseOr(A, B: TBigInt): TBigInt;
     52    class operator LeftShift(A: TBigInt; B: Integer): TBigInt;
     53    class operator RightShift(A: TBigInt; B: Integer): TBigInt;
     54    class operator Modulus(A, B: TBigInt): TBigInt;
     55    class operator IntDivide(A, B: TBigInt): TBigInt;
    4856    procedure Shrink;
    4957    function IsNegative: Boolean;
    5058    function IsZero: Boolean;
    5159    function IsPositive: Boolean;
     60    procedure Invert;
    5261    procedure SetByteArray(AData: TArrayOfByte; ASize: TBigIntSize);
    5362    procedure GetByteArray(var AData: TArrayOfByte; ASize: TBigIntSize);
    54     function Copy(Size: TBigIntSize): TBigInt;
     63    function Copy(Size: TBigIntSize): TBigInt; overload;
     64    function Copy: TBigInt; overload;
    5565    property Size: TBigIntSize read GetSize write SetSize;
    5666    property Data[Index: TBigIntSize]: Byte read GetData write SetData;
     
    5868
    5969function TryStrToBigInt(const S: string; out I: TBigInt): Boolean;
     70function IntToStr(Value: TBigInt): string; overload;
     71function IntToHex(Value: TBigInt): string; overload;
     72function IntToHex(Value: TBigInt; Digits: Integer): string; overload;
    6073
    6174
     
    6477resourcestring
    6578  SUnsupportedByteSize = 'Unsupported byte size';
     79  SOutOfRange = 'Out of range';
     80
     81const
     82   HexDigits: array[0..15] of Char = '0123456789ABCDEF';
    6683
    6784function TryStrToBigInt(const S: string; out I: TBigInt): Boolean;
     
    7390end;
    7491
     92function IntToHex(Value: TBigInt): string;
     93begin
     94  Result := '';
     95  while Value <> 0 do begin
     96    Result := HexDigits[Value and 15] + Result;
     97    Value := Value shr 4;
     98  end;
     99  if Result = '' then Result := '0';
     100end;
     101
     102function IntToHex(Value: TBigInt; Digits: Integer): string;
     103var
     104  I: Integer;
     105begin
     106  if Digits = 0 then
     107    Digits := 1;
     108  Result := '';
     109  SetLength(Result, Digits);
     110  for I := 0 to Digits - 1 do
     111  begin
     112    Result[Digits - I] := HexDigits[Value and 15];
     113    Value := Value shr 4;
     114  end ;
     115  while Value <> 0 do begin
     116    Result := HexDigits[Value and 15] + Result;
     117    Value := Value shr 4;
     118  end;
     119end;
     120
     121function IntToStr(Value: TBigInt): string;
     122begin
     123  Result := '';
     124  if Value < 0 then begin
     125    Value := -Value;
     126    while Value > 9 do begin
     127      Result := Chr(Ord('0') + (Value mod 10)) + Result;
     128      Value := Value div 10;
     129    end;
     130    Result := '-' + Chr(Ord('0') + (Value mod 10)) + Result;
     131  end else begin
     132    while Value > 9 do begin
     133      Result := Chr(Ord('0') + (Value mod 10)) + Result;
     134      Value := Value div 10;
     135    end;
     136    Result := Chr(Ord('0') + Value) + Result;
     137  end;
     138end;
     139
    75140{ TBigInt }
    76141
     
    88153procedure TBigInt.SetData(Index: TBigIntSize; AValue: Byte);
    89154begin
    90   if Index > Integer(Size) - 1 then Size := Index + 1;
     155  if Index >= Integer(Size) then raise Exception.Create(SOutOfRange);
    91156  FData[Index] := AValue;
    92157end;
     
    209274end;
    210275
     276class operator TBigInt.Negative(A: TBigInt): TBigInt;
     277begin
     278  Result := A.Copy(A.Size);
     279  Result.Invert;
     280  Result := Result + 1;
     281end;
     282
    211283class operator TBigInt.Inc(A: TBigInt): TBigInt;
    212284begin
     
    224296  V: SmallInt;
    225297  Carry: Byte;
    226 begin
    227   Result.Size := Max(A.Size, B.Size);
     298  Size: Byte;
     299begin
     300  Size := Max(A.Size, B.Size);
     301  Result.Size := Size;
    228302  Carry := 0;
    229303  I := 0;
    230   while (I < Result.Size) or (Carry > 0) do begin
     304  while (I < Size) or (Carry > 0) do begin
     305    if I >= Result.Size then Result.Size := I + 1;
    231306    V := A.Data[I] + B.Data[I] + Carry;
    232307    if V >= 256 then begin
     
    240315class operator TBigInt.Subtract(A, B: TBigInt): TBigInt;
    241316var
    242   I: Integer;
    243   V: SmallInt;
    244   Carry: Byte;
    245 begin
    246   Result.Size := Max(A.Size, B.Size);
    247   Carry := 0;
    248   I := 0;
    249   while (I < Result.Size) or (Carry > 0) do begin
    250     V := A.Data[I] - B.Data[I] - Carry;
    251     if V < 0 then begin
    252       Carry := 1;
    253     end else Carry := 0;
    254     Result.Data[I] := V and $ff;
    255     Inc(I);
    256   end;
     317  Size: TBigIntSize;
     318begin
     319  Size := Max(A.Size, B.Size);
     320  Result := A + -B;
     321  Result.Size := Size;
     322  Result.Shrink;
    257323end;
    258324
     
    316382end;
    317383
     384class operator TBigInt.BitwiseXor(A, B: TBigInt): TBigInt;
     385var
     386  I: TBigIntSize;
     387begin
     388  Result.Size := Max(A.Size, B.Size);
     389  for I := 0 to Result.Size - 1 do
     390    Result.Data[I] := A.Data[I] xor B.Data[I];
     391  Result.Shrink;
     392end;
     393
     394class operator TBigInt.BitwiseAnd(A, B: TBigInt): TBigInt;
     395var
     396  I: TBigIntSize;
     397begin
     398  Result.Size := Max(A.Size, B.Size);
     399  for I := 0 to Result.Size - 1 do
     400    Result.Data[I] := A.Data[I] and B.Data[I];
     401  Result.Shrink;
     402end;
     403
     404class operator TBigInt.BitwiseOr(A, B: TBigInt): TBigInt;
     405var
     406  I: TBigIntSize;
     407begin
     408  Result.Size := Max(A.Size, B.Size);
     409  for I := 0 to Result.Size - 1 do
     410    Result.Data[I] := A.Data[I] or B.Data[I];
     411  Result.Shrink;
     412end;
     413
     414class operator TBigInt.LeftShift(A: TBigInt; B: Integer): TBigInt;
     415var
     416  ByteShift: TBigIntSize;
     417  BitShift: Byte;
     418  I: Integer;
     419begin
     420  if (B and 7) = 0 then begin
     421    // Full byte shift
     422    ByteShift := B shr 3;
     423    Result.Size := A.Size + ByteShift;
     424    Move(A.FData[0], Result.FData[ByteShift], A.Size);
     425    FillChar(Result.FData[0], ByteShift, 0);
     426  end else begin
     427    // Partial byte shift
     428    ByteShift := B shr 3;
     429    BitShift := B - ByteShift;
     430    Result.Size := Result.Size + ByteShift + 1;
     431    for I := 0 to A.Size - 1 do begin
     432      Result.FData[I + ByteShift] := (A.FData[I] shl BitShift) and $ff;
     433      if I > 0 then Result.FData[I + ByteShift] := Result.FData[I + ByteShift] or (A.FData[I] shl BitShift shl 8);
     434    end;
     435  end;
     436  Result.Shrink;
     437end;
     438
     439class operator TBigInt.RightShift(A: TBigInt; B: Integer): TBigInt;
     440var
     441  ByteShift: TBigIntSize;
     442  BitShift: Byte;
     443  I: Integer;
     444begin
     445  if (B and 7) = 0 then begin
     446    // Full byte shift
     447    ByteShift := B shr 3;
     448    Result.Size := A.Size - ByteShift;
     449    Move(A.FData[ByteShift], Result.FData[0], A.Size);
     450  end else begin
     451    // Partial byte shift
     452    ByteShift := B shr 3;
     453    BitShift := B - ByteShift;
     454    Result.Size := Result.Size - ByteShift;
     455    for I := 0 to A.Size - 1 do begin
     456      Result.FData[I] := (A.FData[I + ByteShift] shr BitShift) and $ff;
     457      if I < (A.Size - 1) then Result.FData[I] := Result.FData[I] or (((A.FData[I + ByteShift] shl 8) shr BitShift) and $ff);
     458    end;
     459  end;
     460  Result.Shrink;
     461end;
     462
     463class operator TBigInt.Modulus(A, B: TBigInt): TBigInt;
     464begin
     465
     466end;
     467
     468class operator TBigInt.IntDivide(A, B: TBigInt): TBigInt;
     469begin
     470
     471end;
     472
    318473procedure TBigInt.Shrink;
    319474var
     
    346501begin
    347502  Result := (FData[Size - 1] and $80) = 0;
     503end;
     504
     505procedure TBigInt.Invert;
     506var
     507  I: Byte;
     508begin
     509  for I := 0 to Size - 1 do
     510    FData[I] := FData[I] xor $ff;
    348511end;
    349512
     
    372535end;
    373536
     537function TBigInt.Copy: TBigInt;
     538begin
     539  Result := Copy(Size);
     540end;
     541
    374542end.
    375543
Note: See TracChangeset for help on using the changeset viewer.