Added more BigInt features and fixes
- Fixed some uses of Move - Added Sign, string initializers (hexadecimal and binary), explicit converter to Int64, comparison operators
This commit is contained in:
parent
eb2b4a3f99
commit
e11db7155a
153
UBigInt.pas
153
UBigInt.pas
|
@ -35,6 +35,8 @@ type
|
||||||
FDigits: TDigits;
|
FDigits: TDigits;
|
||||||
FIsNegative: Boolean;
|
FIsNegative: Boolean;
|
||||||
|
|
||||||
|
function GetSign: Integer;
|
||||||
|
|
||||||
// Copies consecutive digits from this BigInt to create a new one. The result will be positive. Leading zeros are
|
// Copies consecutive digits from this BigInt to create a new one. The result will be positive. Leading zeros are
|
||||||
// removed from the result, but AIndex + ACount must not exceed the number of digits of this BigInt.
|
// removed from the result, but AIndex + ACount must not exceed the number of digits of this BigInt.
|
||||||
// AIndex is the first (least significant) digit to be taken. The digit with this index will become the 0th digit of
|
// AIndex is the first (least significant) digit to be taken. The digit with this index will become the 0th digit of
|
||||||
|
@ -66,11 +68,19 @@ type
|
||||||
// Sign * (Abs(a) * Abs(b))
|
// Sign * (Abs(a) * Abs(b))
|
||||||
// where Sign is 1 for ReturnNegative = False and -1 otherwise.
|
// where Sign is 1 for ReturnNegative = False and -1 otherwise.
|
||||||
class function MultiplyAbsoluteValues(constref AA, AB: TBigInt; const AReturnNegative: Boolean): TBigInt; static;
|
class function MultiplyAbsoluteValues(constref AA, AB: TBigInt; const AReturnNegative: Boolean): TBigInt; static;
|
||||||
|
|
||||||
|
class function FromHexOrBinString(const AValue: string; const AFromBase: Integer): TBigInt; static;
|
||||||
|
class function ConvertDigitBlock(const AValue: string; var AStartIndex: Integer; const ACharBlockSize, AFromBase:
|
||||||
|
Integer): Cardinal;
|
||||||
public
|
public
|
||||||
property IsNegative: Boolean read FIsNegative;
|
property IsNegative: Boolean read FIsNegative;
|
||||||
|
property Sign: Integer read GetSign;
|
||||||
class property Zero: TBigInt read GetZero;
|
class property Zero: TBigInt read GetZero;
|
||||||
function CompareTo(constref AOther: TBigInt): Integer;
|
function CompareTo(constref AOther: TBigInt): Integer;
|
||||||
|
function TryToInt64(out AOutput: Int64): Boolean;
|
||||||
class function FromInt64(const AValue: Int64): TBigInt; static;
|
class function FromInt64(const AValue: Int64): TBigInt; static;
|
||||||
|
class function FromHexadecimalString(const AValue: string): TBigInt; static;
|
||||||
|
class function FromBinaryString(const AValue: string): TBigInt; static;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Operators }
|
{ Operators }
|
||||||
|
@ -83,6 +93,10 @@ type
|
||||||
operator shl (const A: TBigInt; const B: Integer): TBigInt;
|
operator shl (const A: TBigInt; const B: Integer): TBigInt;
|
||||||
operator = (const A, B: TBigInt): Boolean;
|
operator = (const A, B: TBigInt): Boolean;
|
||||||
operator <> (const A, B: TBigInt): Boolean;
|
operator <> (const A, B: TBigInt): Boolean;
|
||||||
|
operator < (const A, B: TBigInt): Boolean;
|
||||||
|
operator <= (const A, B: TBigInt): Boolean;
|
||||||
|
operator > (const A, B: TBigInt): Boolean;
|
||||||
|
operator >= (const A, B: TBigInt): Boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
@ -98,6 +112,16 @@ const
|
||||||
|
|
||||||
{ TBigInt }
|
{ TBigInt }
|
||||||
|
|
||||||
|
function TBigInt.GetSign: Integer;
|
||||||
|
begin
|
||||||
|
if FIsNegative then
|
||||||
|
Result := -1
|
||||||
|
else if (Length(FDigits) > 1) or (FDigits[0] <> 0) then
|
||||||
|
Result := 1
|
||||||
|
else
|
||||||
|
Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
function TBigInt.GetSegment(const AIndex, ACount: Integer): TBigInt;
|
function TBigInt.GetSegment(const AIndex, ACount: Integer): TBigInt;
|
||||||
var
|
var
|
||||||
trimmedCount: Integer;
|
trimmedCount: Integer;
|
||||||
|
@ -105,8 +129,7 @@ begin
|
||||||
trimmedCount := ACount;
|
trimmedCount := ACount;
|
||||||
while (trimmedCount > 1) and (FDigits[AIndex + trimmedCount - 1] = 0) do
|
while (trimmedCount > 1) and (FDigits[AIndex + trimmedCount - 1] = 0) do
|
||||||
Dec(trimmedCount);
|
Dec(trimmedCount);
|
||||||
SetLength(Result.FDigits, trimmedCount);
|
Result.FDigits := Copy(FDigits, AIndex, trimmedCount);
|
||||||
Move(FDigits[AIndex], Result.FDigits[0], CDigitSize * trimmedCount);
|
|
||||||
Result.FIsNegative := False;
|
Result.FIsNegative := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -362,6 +385,65 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TBigInt.FromHexOrBinString(const AValue: string; const AFromBase: Integer): TBigInt;
|
||||||
|
var
|
||||||
|
charBlockSize, offset, i, j, k, remainder: Integer;
|
||||||
|
d: Cardinal;
|
||||||
|
begin
|
||||||
|
charBlockSize := 64 div AFromBase;
|
||||||
|
if AValue[1] = '-' then
|
||||||
|
begin
|
||||||
|
offset := 2;
|
||||||
|
Result.FIsNegative := True;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
offset := 1;
|
||||||
|
Result.FIsNegative := False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Calculates the first (most significant) digit d of the result.
|
||||||
|
DivMod(AValue.Length - offset, charBlockSize, i, remainder);
|
||||||
|
k := offset;
|
||||||
|
d := 0;
|
||||||
|
// Checks the first block of chars that is not a full block.
|
||||||
|
if remainder > 0 then
|
||||||
|
d := ConvertDigitBlock(AValue, k, remainder, AFromBase);
|
||||||
|
// Checks full blocks of chars for first digit.
|
||||||
|
while (d = 0) and (i > 0) do
|
||||||
|
begin
|
||||||
|
Dec(i);
|
||||||
|
d := ConvertDigitBlock(AValue, k, charBlockSize, AFromBase);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Checks for zero.
|
||||||
|
if (d = 0) and (i = 0) then
|
||||||
|
Result := Zero
|
||||||
|
else begin
|
||||||
|
// Initializes the array of digits.
|
||||||
|
SetLength(Result.FDigits, i + 1);
|
||||||
|
Result.FDigits[i] := d;
|
||||||
|
|
||||||
|
// Calculates the other digits.
|
||||||
|
for j := i - 1 downto 0 do
|
||||||
|
Result.FDigits[j] := ConvertDigitBlock(AValue, k, charBlockSize, AFromBase);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TBigInt.ConvertDigitBlock(const AValue: string; var AStartIndex: Integer; const ACharBlockSize,
|
||||||
|
AFromBase: Integer): Cardinal;
|
||||||
|
var
|
||||||
|
part: string;
|
||||||
|
begin
|
||||||
|
part := Copy(AValue, AStartIndex, ACharBlockSize);
|
||||||
|
Inc(AStartIndex, ACharBlockSize);
|
||||||
|
case AFromBase of
|
||||||
|
2: part := '%' + part;
|
||||||
|
8: part := '&' + part;
|
||||||
|
16: part := '$' + part;
|
||||||
|
end;
|
||||||
|
Result := StrToDWord(part);
|
||||||
|
end;
|
||||||
|
|
||||||
function TBigInt.CompareTo(constref AOther: TBigInt): Integer;
|
function TBigInt.CompareTo(constref AOther: TBigInt): Integer;
|
||||||
begin
|
begin
|
||||||
if FIsNegative = AOther.FIsNegative then
|
if FIsNegative = AOther.FIsNegative then
|
||||||
|
@ -372,6 +454,35 @@ begin
|
||||||
Result := -Result;
|
Result := -Result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TBigInt.TryToInt64(out AOutput: Int64): Boolean;
|
||||||
|
begin
|
||||||
|
AOutput := 0;
|
||||||
|
Result := False;
|
||||||
|
case Length(FDigits) of
|
||||||
|
0: Result := True;
|
||||||
|
1: begin
|
||||||
|
AOutput := FDigits[0];
|
||||||
|
if FIsNegative then
|
||||||
|
AOutput := -AOutput;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
2: begin
|
||||||
|
if FDigits[1] <= Integer.MaxValue then
|
||||||
|
begin
|
||||||
|
AOutput := FDigits[1] * CBase + FDigits[0];
|
||||||
|
if FIsNegative then
|
||||||
|
AOutput := -AOutput;
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else if (FDigits[1] = Integer.MaxValue + 1) and (FDigits[0] = 0) and FIsNegative then
|
||||||
|
begin
|
||||||
|
AOutput := Int64.MinValue;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
class function TBigInt.FromInt64(const AValue: Int64): TBigInt;
|
class function TBigInt.FromInt64(const AValue: Int64): TBigInt;
|
||||||
var
|
var
|
||||||
absVal: Int64;
|
absVal: Int64;
|
||||||
|
@ -391,6 +502,16 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TBigInt.FromHexadecimalString(const AValue: string): TBigInt;
|
||||||
|
begin
|
||||||
|
Result := FromHexOrBinString(AValue, 16);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TBigInt.FromBinaryString(const AValue: string): TBigInt;
|
||||||
|
begin
|
||||||
|
Result := FromHexOrBinString(AValue, 2);
|
||||||
|
end;
|
||||||
|
|
||||||
{ Operators }
|
{ Operators }
|
||||||
|
|
||||||
operator := (const A: Int64): TBigInt;
|
operator := (const A: Int64): TBigInt;
|
||||||
|
@ -403,9 +524,13 @@ var
|
||||||
len: Integer;
|
len: Integer;
|
||||||
begin
|
begin
|
||||||
len := Length(A.FDigits);
|
len := Length(A.FDigits);
|
||||||
SetLength(Result.FDigits, len);
|
if (len > 1) or (A.FDigits[0] > 0) then
|
||||||
Move(A.FDigits[0], Result.FDigits[0], len);
|
begin
|
||||||
|
Result.FDigits := Copy(A.FDigits, 0, len);
|
||||||
Result.FIsNegative := not A.FIsNegative;
|
Result.FIsNegative := not A.FIsNegative;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := TBigInt.Zero;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
operator + (const A, B: TBigInt): TBigInt;
|
operator + (const A, B: TBigInt): TBigInt;
|
||||||
|
@ -492,5 +617,25 @@ begin
|
||||||
Result := A.CompareTo(B) <> 0;
|
Result := A.CompareTo(B) <> 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
operator < (const A, B: TBigInt): Boolean;
|
||||||
|
begin
|
||||||
|
Result := A.CompareTo(B) < 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator <= (const A, B: TBigInt): Boolean;
|
||||||
|
begin
|
||||||
|
Result := A.CompareTo(B) <= 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator > (const A, B: TBigInt): Boolean;
|
||||||
|
begin
|
||||||
|
Result := A.CompareTo(B) > 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator >= (const A, B: TBigInt): Boolean;
|
||||||
|
begin
|
||||||
|
Result := A.CompareTo(B) >= 0;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue