Merge branch 'bigint' into day24-analytical
This commit is contained in:
commit
c25317c0fc
178
UBigInt.pas
178
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;
|
||||||
|
|
||||||
|
@ -138,7 +161,7 @@ end;
|
||||||
|
|
||||||
class function TBigInt.AddAbsoluteValues(constref AA, AB: TBigInt; const AReturnNegative: Boolean): TBigInt;
|
class function TBigInt.AddAbsoluteValues(constref AA, AB: TBigInt; const AReturnNegative: Boolean): TBigInt;
|
||||||
var
|
var
|
||||||
i, lenA, lenB, len, shorter: Integer;
|
i, j, lenA, lenB, len, shorter: Integer;
|
||||||
carry: Cardinal;
|
carry: Cardinal;
|
||||||
begin
|
begin
|
||||||
lenA := Length(AA.FDigits);
|
lenA := Length(AA.FDigits);
|
||||||
|
@ -185,9 +208,11 @@ begin
|
||||||
// carry-overs. This avoids additional tests for finding the shorter digit array.
|
// carry-overs. This avoids additional tests for finding the shorter digit array.
|
||||||
if (i < lenA) or (i < lenB) then
|
if (i < lenA) or (i < lenB) then
|
||||||
if lenA >= lenB then
|
if lenA >= lenB then
|
||||||
Move(AA.FDigits[i], Result.FDigits[i], CDigitSize * (len - i))
|
for j := i to len - 1 do
|
||||||
|
Result.FDigits[j] := AA.FDigits[j]
|
||||||
else
|
else
|
||||||
Move(AB.FDigits[i], Result.FDigits[i], CDigitSize * (len - i));
|
for j := i to len - 1 do
|
||||||
|
Result.FDigits[j] := AB.FDigits[j];
|
||||||
|
|
||||||
// Applies the remaining carry-overs until the end of the prepared result digit array.
|
// Applies the remaining carry-overs until the end of the prepared result digit array.
|
||||||
while (carry > 0) and (i < len) do
|
while (carry > 0) and (i < len) do
|
||||||
|
@ -212,7 +237,7 @@ class function TBigInt.SubtractAbsoluteValues(constref AA, AB: TBigInt; const AR
|
||||||
var
|
var
|
||||||
a, b: TBigInt;
|
a, b: TBigInt;
|
||||||
carry: Cardinal;
|
carry: Cardinal;
|
||||||
i, lastNonZeroDigitIndex, len: Integer;
|
i, j, lastNonZeroDigitIndex, len: Integer;
|
||||||
begin
|
begin
|
||||||
// Establishes the operand order, such that Abs(a) is not less than Abs(b).
|
// Establishes the operand order, such that Abs(a) is not less than Abs(b).
|
||||||
if (AA.CompareToAbsoluteValues(AB) >= 0) then
|
if (AA.CompareToAbsoluteValues(AB) >= 0) then
|
||||||
|
@ -277,7 +302,8 @@ begin
|
||||||
// Copies the missing unchanged digits from the longer operand to the result, if any. If there are none, then no trim
|
// Copies the missing unchanged digits from the longer operand to the result, if any. If there are none, then no trim
|
||||||
// needs to occur because the most significant digit is not zero.
|
// needs to occur because the most significant digit is not zero.
|
||||||
if i < len then
|
if i < len then
|
||||||
Move(a.FDigits[i], Result.FDigits[i], CDigitSize * (len - i))
|
for j := i to len - 1 do
|
||||||
|
Result.FDigits[j] := a.FDigits[j]
|
||||||
else if (lastNonZeroDigitIndex + 1 < len) then
|
else if (lastNonZeroDigitIndex + 1 < len) then
|
||||||
// Trims leading zeros from the digits array.
|
// Trims leading zeros from the digits array.
|
||||||
Delete(Result.FDigits, lastNonZeroDigitIndex + 1, len - lastNonZeroDigitIndex - 1);
|
Delete(Result.FDigits, lastNonZeroDigitIndex + 1, len - lastNonZeroDigitIndex - 1);
|
||||||
|
@ -362,6 +388,70 @@ 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
|
||||||
|
// 2 ^ (32 / charBlockSize) = AFromBase
|
||||||
|
case AFromBase of
|
||||||
|
2: charBlockSize := 32;
|
||||||
|
16: charBlockSize := 8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
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 + 1, 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 +462,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 +510,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 +532,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.FIsNegative := not A.FIsNegative;
|
Result.FDigits := Copy(A.FDigits, 0, len);
|
||||||
|
Result.FIsNegative := not A.FIsNegative;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := TBigInt.Zero;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
operator + (const A, B: TBigInt): TBigInt;
|
operator + (const A, B: TBigInt): TBigInt;
|
||||||
|
@ -475,7 +608,10 @@ begin
|
||||||
// Performs full digit shifts by copy if there are no bit shifts.
|
// Performs full digit shifts by copy if there are no bit shifts.
|
||||||
len := Length(A.FDigits);
|
len := Length(A.FDigits);
|
||||||
SetLength(Result.FDigits, len + digitShifts);
|
SetLength(Result.FDigits, len + digitShifts);
|
||||||
Move(A.FDigits[0], Result.FDigits[digitShifts], CDigitSize * len);
|
for i := 0 to digitShifts - 1 do
|
||||||
|
Result.FDigits[i] := 0;
|
||||||
|
for i := 0 to len - 1 do
|
||||||
|
Result.FDigits[i + digitShifts] := A.FDigits[i];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result.FIsNegative := A.IsNegative;
|
Result.FIsNegative := A.IsNegative;
|
||||||
|
@ -492,5 +628,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.
|
||||||
|
|
||||||
|
|
|
@ -144,10 +144,18 @@
|
||||||
<Filename Value="UPolynomialTestCases.pas"/>
|
<Filename Value="UPolynomialTestCases.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="..\UPolynomialRoots.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
<Unit>
|
<Unit>
|
||||||
<Filename Value="UPolynomialRootsTestCases.pas"/>
|
<Filename Value="UPolynomialRootsTestCases.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="UBigIntTestCases.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|
|
@ -9,7 +9,7 @@ uses
|
||||||
UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases, ULensLibraryTestCases,
|
UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases, ULensLibraryTestCases,
|
||||||
UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases,
|
UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases,
|
||||||
UPulsePropagationTestCases, UStepCounterTestCases, USandSlabsTestCases, ULongWalkTestCases,
|
UPulsePropagationTestCases, UStepCounterTestCases, USandSlabsTestCases, ULongWalkTestCases,
|
||||||
UNeverTellMeTheOddsTestCases, UPolynomialTestCases, UPolynomialRootsTestCases;
|
UNeverTellMeTheOddsTestCases, UBigIntTestCases, UPolynomialTestCases, UPolynomialRootsTestCases;
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,917 @@
|
||||||
|
{
|
||||||
|
Solutions to the Advent Of Code.
|
||||||
|
Copyright (C) 2022-2024 Stefan Müller
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
}
|
||||||
|
|
||||||
|
unit UBigIntTestCases;
|
||||||
|
|
||||||
|
{$mode ObjFPC}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testregistry, UBigInt;
|
||||||
|
|
||||||
|
type
|
||||||
|
// TODO: TBigIntAbsTestCase
|
||||||
|
// TODO: TBigIntFromDecTestCase
|
||||||
|
// TestCase('80091110002223289436355210101231765016693209176113648', 10, '80091110002223289436355210101231765016693209176113648');
|
||||||
|
// TestCase('-3201281944789146858325672846129872035678639439423746384198412894', 10, '-3201281944789146858325672846129872035678639439423746384198412894');
|
||||||
|
// TestCase('000000000000000000000000000000000000000080091', 10, '80091');
|
||||||
|
// TestCase('0000000000000000000000000000000000000000000000', 10, '0');
|
||||||
|
// TestCase('-000000000000000000000000000000004687616873215464763146843215486643215', 10, '-4687616873215464763146843215486643215');
|
||||||
|
// TestTryFromDec
|
||||||
|
// TODO: TBigIntFromOctTestCase
|
||||||
|
// OctValue, 8, DecValue:
|
||||||
|
// TestCase('3132521', 8, '832849');
|
||||||
|
// TestCase('772350021110002226514', 8, '9123449598017875276');
|
||||||
|
// TestCase('-247515726712721', 8, '-11520970560977');
|
||||||
|
// TestCase('000000000000000000000000000000000000000072', 8, '58');
|
||||||
|
// TestCase('000000000000000000000000000000000000000000000000000000000', 8, '0');
|
||||||
|
// OctValue, HexValue:
|
||||||
|
// TestCase('7440737076307076026772', '3C83BE3E638F82DFA');
|
||||||
|
// TestCase('1336625076203401614325664', '16F6547C8380E31ABB4');
|
||||||
|
// TestCase('3254410316166274457257121050201413373225', '6AC84338ECBC97ABCA22840C2DF695');
|
||||||
|
// TestCase('1441330072562106272767270117307274151276215', '642D81D5C88CBAFBAE09EC75E1A57C8D');
|
||||||
|
// TestCase('3533665174054677131163436413756431236774257271133', '3ADED4F82CDF964E71E85FBA329EFE2BD725B');
|
||||||
|
// TestCase('57346415317074055631627141161054073014006076155710653', '5EE686B3C782DCCE5CC271160EC18061F1B791AB');
|
||||||
|
// TestCase('000000000000000000000000000000245745251354033134', 8, '5838773085550172');
|
||||||
|
// TestTryFromOct
|
||||||
|
// TODO: TBigIntUnaryPlusTestCase
|
||||||
|
// TODO: TBigIntBitwiseLogicalTestCase
|
||||||
|
// TODO: TBigIntComplementTestCase
|
||||||
|
// TODO: TBigIntConversionTestCase
|
||||||
|
// TODO: TBigIntIncrementDecrementTestCase
|
||||||
|
// TODO: TBigIntQuotientTestCase
|
||||||
|
// TODO: TBigIntShiftRightTestCase
|
||||||
|
|
||||||
|
{ TBigIntSignTestCase }
|
||||||
|
|
||||||
|
TBigIntSignTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AHexValue: string; const AExpectedSign: Integer);
|
||||||
|
published
|
||||||
|
procedure TestZero;
|
||||||
|
procedure TestShortPositive;
|
||||||
|
procedure TestShortNegative;
|
||||||
|
procedure TestLongPositive;
|
||||||
|
procedure TestLongNegative;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntFromInt64TestCase }
|
||||||
|
|
||||||
|
TBigIntFromInt64TestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AValue: Int64);
|
||||||
|
published
|
||||||
|
procedure TestShortPositive;
|
||||||
|
procedure TestShortNegative;
|
||||||
|
procedure TestLongPositive;
|
||||||
|
procedure TestLongNegative;
|
||||||
|
procedure TestZero;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntFromHexTestCase }
|
||||||
|
|
||||||
|
TBigIntFromHexTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure TestShort(const AHexValue: string; const ADecValue: Int64);
|
||||||
|
published
|
||||||
|
procedure TestPositive;
|
||||||
|
procedure TestNegative;
|
||||||
|
procedure TestZero;
|
||||||
|
procedure TestLeadingZeros;
|
||||||
|
// TODO: TestTryFromHex
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntFromBinTestCase }
|
||||||
|
|
||||||
|
TBigIntFromBinTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure TestShort(const ABinValue: string; const ADecValue: Int64);
|
||||||
|
published
|
||||||
|
procedure TestPositive;
|
||||||
|
procedure TestNegative;
|
||||||
|
procedure TestLeadingZeros;
|
||||||
|
// TODO: TestTryFromBin
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntUnaryMinusTestCase }
|
||||||
|
|
||||||
|
TBigIntUnaryMinusTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AValue: Int64);
|
||||||
|
procedure TestTwice(const AValue: Int64);
|
||||||
|
published
|
||||||
|
procedure TestZero;
|
||||||
|
procedure TestPositive;
|
||||||
|
procedure TestNegative;
|
||||||
|
procedure TestPositiveTwice;
|
||||||
|
procedure TestNegativeTwice;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntSumTestCase }
|
||||||
|
|
||||||
|
TBigIntSumTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AHexValueLeft, AHexValueRight, AHexValueSum: string);
|
||||||
|
published
|
||||||
|
procedure TestShort;
|
||||||
|
procedure TestPositivePlusPositive;
|
||||||
|
procedure TestNegativePlusNegative;
|
||||||
|
procedure TestLargePositivePlusSmallNegative;
|
||||||
|
procedure TestSmallPositivePlusLargeNegative;
|
||||||
|
procedure TestLargeNegativePlusSmallPositive;
|
||||||
|
procedure TestSmallNegativePlusLargePositive;
|
||||||
|
procedure TestZeroPlusPositive;
|
||||||
|
procedure TestPositivePlusZero;
|
||||||
|
procedure TestZero;
|
||||||
|
procedure TestSumShorterLeft;
|
||||||
|
procedure TestSumShorterRight;
|
||||||
|
procedure TestSumEndsInCarry;
|
||||||
|
procedure TestSumEndsInCarryNewDigit;
|
||||||
|
procedure TestSumMultiCarry;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntDifferenceTestCase }
|
||||||
|
|
||||||
|
TBigIntDifferenceTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AHexValueMinuend, AHexValueSubtrahend, AHexValueDifference: string);
|
||||||
|
published
|
||||||
|
procedure TestShort;
|
||||||
|
procedure TestLargePositiveMinusSmallPositive;
|
||||||
|
procedure TestSmallPositiveMinusLargePositive;
|
||||||
|
procedure TestLargeNegativeMinusSmallNegative;
|
||||||
|
procedure TestSmallNegativeMinusLargeNegative;
|
||||||
|
procedure TestNegativeMinusPositive;
|
||||||
|
procedure TestPositiveMinusNegative;
|
||||||
|
procedure TestLargeOperands;
|
||||||
|
procedure TestPositiveMinusZero;
|
||||||
|
procedure TestZeroMinusPositive;
|
||||||
|
procedure TestZero;
|
||||||
|
procedure TestDifferenceShorterLeft;
|
||||||
|
procedure TestDifferenceShorterRight;
|
||||||
|
procedure TestDifferenceEndsInCarry;
|
||||||
|
procedure TestDifferenceEndsInCarryLosingDigit;
|
||||||
|
procedure TestDifferenceMultiCarry;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntProductTestCase }
|
||||||
|
|
||||||
|
TBigIntProductTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AHexValueLeft, AHexValueRight, AHexValueProduct: string);
|
||||||
|
published
|
||||||
|
procedure TestShort;
|
||||||
|
procedure TestLongPositiveTimesPositive;
|
||||||
|
procedure TestLongPositiveTimesNegative;
|
||||||
|
procedure TestLongNegativeTimesPositive;
|
||||||
|
procedure TestLongNegativeTimesNegative;
|
||||||
|
procedure TestZeroTimesPositive;
|
||||||
|
procedure TestZeroTimesNegative;
|
||||||
|
procedure TestZero;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntShiftLeftTestCase }
|
||||||
|
|
||||||
|
TBigIntShiftLeftTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure Test(const AHexValueOperand: string; const AShift: Integer; const AHexValueResult: string);
|
||||||
|
published
|
||||||
|
procedure TestShort;
|
||||||
|
procedure TestShortWithCarry;
|
||||||
|
procedure TestLongWithCarry;
|
||||||
|
procedure TestLongWithMultiDigitCarry;
|
||||||
|
procedure TestWithAlignedDigits;
|
||||||
|
procedure TestZero;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntEqualityTestCase }
|
||||||
|
|
||||||
|
TBigIntEqualityTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure TestEqual(const AValue: Int64);
|
||||||
|
procedure TestEqualHex(const AHexValue: string);
|
||||||
|
procedure TestNotEqualHex(const AHexValueLeft, AHexValueRight: string);
|
||||||
|
published
|
||||||
|
procedure TestShortEqual;
|
||||||
|
procedure TestLongEqual;
|
||||||
|
procedure TestZeroEqual;
|
||||||
|
procedure TestShortNotEqual;
|
||||||
|
procedure TestLongNotEqualSign;
|
||||||
|
procedure TestZeroNotEqual;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntComparisonTestCase }
|
||||||
|
|
||||||
|
TBigIntComparisonTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
procedure TestLessThan(const AHexValueLeft, AHexValueRight: string);
|
||||||
|
procedure TestGreaterThan(const AHexValueLeft, AHexValueRight: string);
|
||||||
|
procedure TestEqual(const AHexValue: string);
|
||||||
|
published
|
||||||
|
procedure TestLessSameLength;
|
||||||
|
procedure TestLessShorterLeft;
|
||||||
|
procedure TestLessNegativeShorterRight;
|
||||||
|
procedure TestGreaterSameLength;
|
||||||
|
procedure TestGreaterShorterRight;
|
||||||
|
procedure TestGreaterNegativeShorterLeft;
|
||||||
|
procedure TestEqualPositive;
|
||||||
|
procedure TestEqualNegative;
|
||||||
|
procedure TestEqualZero;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TBigIntSignTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntSignTestCase.Test(const AHexValue: string; const AExpectedSign: Integer);
|
||||||
|
var
|
||||||
|
a: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValue);
|
||||||
|
AssertEquals(AExpectedSign, a.Sign);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSignTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test('0', 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSignTestCase.TestShortPositive;
|
||||||
|
begin
|
||||||
|
Test('36A', 1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSignTestCase.TestShortNegative;
|
||||||
|
begin
|
||||||
|
Test('-29B7', -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSignTestCase.TestLongPositive;
|
||||||
|
begin
|
||||||
|
Test('1240168AB09ABDF8283B77124', 1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSignTestCase.TestLongNegative;
|
||||||
|
begin
|
||||||
|
Test('-192648F1305DD04757A24C873F29F60B6184B5', -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntFromInt64TestCase }
|
||||||
|
|
||||||
|
procedure TBigIntFromInt64TestCase.Test(const AValue: Int64);
|
||||||
|
var
|
||||||
|
a: TBigInt;
|
||||||
|
act: Int64;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromInt64(AValue);
|
||||||
|
AssertTrue('BigInt from ''' + IntToStr(AValue) + ''' could not be converted back to an Int64 value.',
|
||||||
|
a.TryToInt64(act));
|
||||||
|
AssertEquals('BigInt from ''' + IntToStr(AValue) + ''' converted back to Int64 was not equal to initial value.',
|
||||||
|
AValue, act);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromInt64TestCase.TestShortPositive;
|
||||||
|
begin
|
||||||
|
Test(17);
|
||||||
|
Test(4864321);
|
||||||
|
Test(Cardinal.MaxValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromInt64TestCase.TestShortNegative;
|
||||||
|
begin
|
||||||
|
Test(-54876);
|
||||||
|
Test(Integer.MinValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromInt64TestCase.TestLongPositive;
|
||||||
|
begin
|
||||||
|
Test(5800754643214654);
|
||||||
|
Test(Int64.MaxValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromInt64TestCase.TestLongNegative;
|
||||||
|
begin
|
||||||
|
Test(-94136445555883);
|
||||||
|
Test(Int64.MinValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromInt64TestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntFromHexTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntFromHexTestCase.TestShort(const AHexValue: string; const ADecValue: Int64);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValue);
|
||||||
|
b := TBigInt.FromInt64(ADecValue);
|
||||||
|
AssertTrue('BigInt from hexadecimal string ''' + AHexValue + ''' was not equal to ''' + IntToStr(ADecValue) + '''.',
|
||||||
|
a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromHexTestCase.TestPositive;
|
||||||
|
begin
|
||||||
|
TestShort('91', 145);
|
||||||
|
TestShort('800E111000222', 2252766466540066);
|
||||||
|
TestShort('DE0B227802AB233', 999995000000000563);
|
||||||
|
TestShort('19C0048155000', 453000000000000);
|
||||||
|
TestShort('3B9ACA00', 1000000000);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromHexTestCase.TestNegative;
|
||||||
|
begin
|
||||||
|
TestShort('-47', -71);
|
||||||
|
TestShort('-800E111000222', -2252766466540066);
|
||||||
|
TestShort('-4512FF3', -72429555);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromHexTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
TestShort('0', 0);
|
||||||
|
TestShort('-0', 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromHexTestCase.TestLeadingZeros;
|
||||||
|
begin
|
||||||
|
TestShort('000000000000000000000000000000004B', 75);
|
||||||
|
TestShort('-00000000000000000000000000000000A2', -162);
|
||||||
|
TestShort('00000000000000000000000000000000FF452849DB01', 280672493755137);
|
||||||
|
TestShort('000000000000000000000000000000000000', 0);
|
||||||
|
TestShort('-000000000000000000000000000000000000', 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntFromBinTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntFromBinTestCase.TestShort(const ABinValue: string; const ADecValue: Int64);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromBinaryString(ABinValue);
|
||||||
|
b := TBigInt.FromInt64(ADecValue);
|
||||||
|
AssertTrue('BigInt from binary string ''' + ABinValue + ''' was not equal to ''' + IntToStr(ADecValue) + '''.',
|
||||||
|
a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromBinTestCase.TestPositive;
|
||||||
|
begin
|
||||||
|
TestShort('110101010101101101010010110000101010100101001001010100110', 120109162101379750);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromBinTestCase.TestNegative;
|
||||||
|
begin
|
||||||
|
TestShort('-11100100111010100111000111100011110000100110110111100101010010', -4123780452057839954);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntFromBinTestCase.TestLeadingZeros;
|
||||||
|
begin
|
||||||
|
TestShort('0000000000000000000000000000000000000000000000000000000000000000000000111', 7);
|
||||||
|
TestShort('0000000000000000000000000000000000000000000000000000000000000000000000000000000', 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntUnaryMinusTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.Test(const AValue: Int64);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromInt64(AValue);
|
||||||
|
b := TBigInt.FromInt64(-AValue);
|
||||||
|
AssertTrue('Negative BigInt from ''' + IntToStr(AValue) + ''' was not equal to the BigInt from the negative value.',
|
||||||
|
b = -a);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.TestTwice(const AValue: Int64);
|
||||||
|
var
|
||||||
|
a: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromInt64(AValue);
|
||||||
|
AssertTrue('BigInt from ''' + IntToStr(AValue) + '''was not equal to the double negative of itself.',
|
||||||
|
a = -(-a));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.TestPositive;
|
||||||
|
begin
|
||||||
|
Test(234972358233);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.TestNegative;
|
||||||
|
begin
|
||||||
|
Test(-999214927400);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.TestPositiveTwice;
|
||||||
|
begin
|
||||||
|
TestTwice(8647613456601);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntUnaryMinusTestCase.TestNegativeTwice;
|
||||||
|
begin
|
||||||
|
TestTwice(-38600421308534);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntSumTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.Test(const AHexValueLeft, AHexValueRight, AHexValueSum: string);
|
||||||
|
var
|
||||||
|
a, b, s: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueLeft);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValueRight);
|
||||||
|
s := TBigInt.FromHexadecimalString(AHexValueSum);
|
||||||
|
AssertTrue('Sum of BigInt from ''' + AHexValueLeft + ''' and from ''' + AHexValueRight
|
||||||
|
+ ''' was not equal to the BigInt from ''' + AHexValueSum + '''.',
|
||||||
|
s = a + b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestShort;
|
||||||
|
begin
|
||||||
|
Test('5', '7', 'C');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestPositivePlusPositive;
|
||||||
|
begin
|
||||||
|
Test('7000822000111', '9000911000333', '10001133000444');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestNegativePlusNegative;
|
||||||
|
begin
|
||||||
|
Test('-129B92A84643D608141', '-4574DBA206951ECFE', '-12E10783E84A6B26E3F');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestLargePositivePlusSmallNegative;
|
||||||
|
begin
|
||||||
|
Test('87BAD26984', '-8DCB20461', '7EDE206523');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSmallPositivePlusLargeNegative;
|
||||||
|
begin
|
||||||
|
Test('A58301E4006', '-9851DA0FD433', '-8DF9A9F1942D');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestLargeNegativePlusSmallPositive;
|
||||||
|
begin
|
||||||
|
Test('-1FDB60CB5698870', '99CB1E00DE', '-1FDB572EA4B8792');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSmallNegativePlusLargePositive;
|
||||||
|
begin
|
||||||
|
Test('-1ED598BBFEC2', '59CD4F02ECB56', '57DFF5772CC94');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestZeroPlusPositive;
|
||||||
|
begin
|
||||||
|
Test('0', '9BB000911FF5A000333', '9BB000911FF5A000333');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestPositivePlusZero;
|
||||||
|
begin
|
||||||
|
Test('23009605A16BCBB294A1FD', '0', '23009605A16BCBB294A1FD');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test('0', '0', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSumShorterLeft;
|
||||||
|
begin
|
||||||
|
Test('3FFFF', '9000911000222', '9000911040221');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSumShorterRight;
|
||||||
|
begin
|
||||||
|
Test('9000911000555', '3000EEEE', '900094100F443');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSumEndsInCarry;
|
||||||
|
begin
|
||||||
|
Test('4000444000220', 'FFFFFFFF', '400054400021F');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSumEndsInCarryNewDigit;
|
||||||
|
begin
|
||||||
|
Test('99990000', '99990055', '133320055');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntSumTestCase.TestSumMultiCarry;
|
||||||
|
begin
|
||||||
|
Test('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'FFFFFFFF', '1000000000000000000000000FFFFFFFE');
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntDifferenceTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.Test(const AHexValueMinuend, AHexValueSubtrahend, AHexValueDifference: string);
|
||||||
|
var
|
||||||
|
a, b, s: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueMinuend);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValueSubtrahend);
|
||||||
|
s := TBigInt.FromHexadecimalString(AHexValueDifference);
|
||||||
|
AssertTrue('Difference of BigInt from ''' + AHexValueMinuend + ''' and from ''' + AHexValueSubtrahend
|
||||||
|
+ ''' was not equal to the BigInt from ''' + AHexValueDifference + '''.',
|
||||||
|
s = a - b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestShort;
|
||||||
|
begin
|
||||||
|
Test('230', '6D', '1C3');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestLargePositiveMinusSmallPositive;
|
||||||
|
begin
|
||||||
|
Test('910AAD86E5002455', '72DE020F932A1', '91037FA6C406F1B4');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestSmallPositiveMinusLargePositive;
|
||||||
|
begin
|
||||||
|
Test('3127541F4C0AA', '3818CD9FBE652B', '-3506585DC9A481');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestLargeNegativeMinusSmallNegative;
|
||||||
|
begin
|
||||||
|
Test('-B12BE1E20098', '-148F3137CED396', '13DE0555ECD2FE');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestSmallNegativeMinusLargeNegative;
|
||||||
|
begin
|
||||||
|
Test('-AF3FF1EC626908C', '-18295', '-AF3FF1EC6250DF7');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestNegativeMinusPositive;
|
||||||
|
begin
|
||||||
|
Test('-E493506B19', '20508ED255', '-104E3DF3D6E');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestPositiveMinusNegative;
|
||||||
|
begin
|
||||||
|
Test('114EEC66851AFD98', '-100AA4308C5249FBBFADEB89CD6A7D9CC', '100AA4308C5249FBC0C2DA5035BC2D764');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestLargeOperands;
|
||||||
|
begin
|
||||||
|
Test('1069FC8EA3D99C39E1C07AA078B77B5CC679CB448563345A878C603D32FB0F8FEFE02AD9574A5EB6',
|
||||||
|
'1069FC8EA3D99C39E1C07AA078B77B5CC679CB448563345A878C603D32FB0F8FEFE023C522B87F8C',
|
||||||
|
'7143491DF2A');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestPositiveMinusZero;
|
||||||
|
begin
|
||||||
|
Test('8ABB000911FF5A000333', '0', '8ABB000911FF5A000333');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestZeroMinusPositive;
|
||||||
|
begin
|
||||||
|
Test('0', '243961982DDD64F81B2', '-243961982DDD64F81B2');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test('0', '0', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestDifferenceShorterLeft;
|
||||||
|
begin
|
||||||
|
Test('3FFFF', '9000911040221', '-9000911000222');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestDifferenceShorterRight;
|
||||||
|
begin
|
||||||
|
Test('900094100F443', '3000EEEE', '9000911000555');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestDifferenceEndsInCarry;
|
||||||
|
begin
|
||||||
|
Test('400054400021F', 'FFFFFFFF', '4000444000220');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestDifferenceEndsInCarryLosingDigit;
|
||||||
|
begin
|
||||||
|
Test('133320055', '99990000', '99990055');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntDifferenceTestCase.TestDifferenceMultiCarry;
|
||||||
|
begin
|
||||||
|
Test('1000000000000000000000000FFFFFFFE', 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'FFFFFFFF');
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntProductTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.Test(const AHexValueLeft, AHexValueRight, AHexValueProduct: string);
|
||||||
|
var
|
||||||
|
a, b, s: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueLeft);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValueRight);
|
||||||
|
s := TBigInt.FromHexadecimalString(AHexValueProduct);
|
||||||
|
AssertTrue('Product of BigInt from ''' + AHexValueLeft + ''' and from ''' + AHexValueRight
|
||||||
|
+ ''' was not equal to the BigInt from ''' + AHexValueProduct + '''.',
|
||||||
|
s = a * b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestShort;
|
||||||
|
begin
|
||||||
|
Test('9', 'B', '63');
|
||||||
|
Test('29E531A', 'DF5F299', '248E3915103E8A');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestLongPositiveTimesPositive;
|
||||||
|
begin
|
||||||
|
Test('FFFFFFFF', 'FFFFFFFF', 'FFFFFFFE00000001');
|
||||||
|
Test('4873B23699D07741F1544862221B1966AA84512', '4DE0013', '160A322C656DEB1DD6D721D36E35F2E29B4D2A18192056');
|
||||||
|
Test('74FD3E6988116762', '22DB271AFC4941', 'FEDC8CD51DEE46BE83C283B5E31E2');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestLongPositiveTimesNegative;
|
||||||
|
begin
|
||||||
|
Test('23401834190D12FF3210F0B0129123AA', '-A4C0530234', '-16AF8B019CA1436BBFD1F1FB08494FFC9EF7E09288');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestLongNegativeTimesPositive;
|
||||||
|
begin
|
||||||
|
Test('-3ACB78882923810', 'F490B8022A4BCBFF34E01', '-382B2B9851BC93CB0308B502C3B036D71810');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestLongNegativeTimesNegative;
|
||||||
|
begin
|
||||||
|
Test('-554923FB201', '-9834FDC032', '32B514C1BA1E774EE8432');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestZeroTimesPositive;
|
||||||
|
begin
|
||||||
|
Test('0', '1AF5D0039B888AC00F299', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestZeroTimesNegative;
|
||||||
|
begin
|
||||||
|
Test('0', '-1AF5D0039B888AC00F299', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntProductTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test('0', '0', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntShiftLeftTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.Test(const AHexValueOperand: string; const AShift: Integer; const AHexValueResult: string);
|
||||||
|
var
|
||||||
|
a, s: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueOperand);
|
||||||
|
s := TBigInt.FromHexadecimalString(AHexValueResult);
|
||||||
|
AssertTrue('BigInt from hexadecimal string ''' + AHexValueOperand + ''' shifted left by ''' + IntToStr(AShift)
|
||||||
|
+ ''' was not equal to BigInt from hexadecimal string ''' + AHexValueResult + '''.',
|
||||||
|
s = (a << AShift));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.TestShort;
|
||||||
|
begin
|
||||||
|
// BIN 101
|
||||||
|
// BIN 101000
|
||||||
|
Test('5', 3, '28');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.TestShortWithCarry;
|
||||||
|
begin
|
||||||
|
// BIN 1110 1101 0111 0001 1010 1010
|
||||||
|
// BIN 1 1101 1010 1110 0011 0101 0100 0000 0000 0000
|
||||||
|
Test('ED71AA', 13, '1DAE354000');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.TestLongWithCarry;
|
||||||
|
begin
|
||||||
|
// BIN 1 0011 0000 1011 0010 0011 1110 0100 1100 1111 1001 0101 0100 0100 0101
|
||||||
|
// BIN 10 0110 0001 0110 0100 0111 1100 1001 1001 1111 0010 1010 1000 1000 1010 0000 0000
|
||||||
|
Test('130B23E4CF95445', 9, '261647C99F2A88A00');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.TestLongWithMultiDigitCarry;
|
||||||
|
begin
|
||||||
|
Test('C99F12A735A3B83901BF92011', 140, 'C99F12A735A3B83901BF9201100000000000000000000000000000000000');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.TestWithAlignedDigits;
|
||||||
|
begin
|
||||||
|
// Shifts the left operand by a multiple of the length of full TBigInt digits, so the digits will be shifted, but not
|
||||||
|
// changed.
|
||||||
|
Test('10F0F39C5E', 32 * 4, '10F0F39C5E00000000000000000000000000000000');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntShiftLeftTestCase.TestZero;
|
||||||
|
begin
|
||||||
|
Test('0', 119, '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntEqualityTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestEqual(const AValue: Int64);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromInt64(AValue);
|
||||||
|
b := TBigInt.FromInt64(AValue);
|
||||||
|
AssertTrue('Two BigInt from ''' + IntToStr(AValue) + ''' were not equal.', a = b);
|
||||||
|
AssertFalse('Two BigInt from ''' + IntToStr(AValue) + ''' were un-equal.', a <> b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestEqualHex(const AHexValue: string);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValue);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValue);
|
||||||
|
AssertTrue('Two BigInt from ''' + AHexValue + ''' were not equal.', a = b);
|
||||||
|
AssertFalse('Two BigInt from ''' + AHexValue + ''' were un-equal.', a <> b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestNotEqualHex(const AHexValueLeft, AHexValueRight: string);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueLeft);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValueRight);
|
||||||
|
AssertTrue('BigInt from ''' + AHexValueLeft + ''' and from ''' + AHexValueRight + ''' were not un-equal.',
|
||||||
|
a <> b);
|
||||||
|
AssertFalse('BigInt from ''' + AHexValueLeft + ''' and from ''' + AHexValueRight + ''' were equal.',
|
||||||
|
a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestShortEqual;
|
||||||
|
begin
|
||||||
|
TestEqual(14);
|
||||||
|
TestEqualHex('8000111000111');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestLongEqual;
|
||||||
|
begin
|
||||||
|
TestEqualHex('5AB60FF292A014BF1DD0A');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestZeroEqual;
|
||||||
|
begin
|
||||||
|
TestEqual(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestShortNotEqual;
|
||||||
|
begin
|
||||||
|
TestNotEqualHex('9FF99920', '100');
|
||||||
|
TestNotEqualHex('20001110002111', '70001110007111');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestLongNotEqualSign;
|
||||||
|
begin
|
||||||
|
TestNotEqualHex('48843AB320FF0041123A', '-48843AB320FF0041123A');
|
||||||
|
TestNotEqualHex('-B13F79D842A30957DD09523667', 'B13F79D842A30957DD09523667');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntEqualityTestCase.TestZeroNotEqual;
|
||||||
|
begin
|
||||||
|
TestNotEqualHex('0', 'F');
|
||||||
|
TestNotEqualHex('568F7', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBigIntComparisonTestCase }
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestLessThan(const AHexValueLeft, AHexValueRight: string);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueLeft);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValueRight);
|
||||||
|
AssertTrue('BigInt from ''' + AHexValueLeft + ''' was greater than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a < b);
|
||||||
|
AssertTrue('BigInt from ''' + AHexValueLeft + ''' was greater or equal than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a <= b);
|
||||||
|
AssertFalse('BigInt from ''' + AHexValueLeft + ''' was greater than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a > b);
|
||||||
|
AssertFalse('BigInt from ''' + AHexValueLeft + ''' was greater or equal than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a >= b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestGreaterThan(const AHexValueLeft, AHexValueRight: string);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValueLeft);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValueRight);
|
||||||
|
AssertFalse('BigInt from ''' + AHexValueLeft + ''' was less than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a < b);
|
||||||
|
AssertFalse('BigInt from ''' + AHexValueLeft + ''' was less or equal than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a <= b);
|
||||||
|
AssertTrue('BigInt from ''' + AHexValueLeft + ''' was less than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a > b);
|
||||||
|
AssertTrue('BigInt from ''' + AHexValueLeft + ''' was less or equal than BigInt from ''' + AHexValueRight + '''.',
|
||||||
|
a >= b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestEqual(const AHexValue: string);
|
||||||
|
var
|
||||||
|
a, b: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigInt.FromHexadecimalString(AHexValue);
|
||||||
|
b := TBigInt.FromHexadecimalString(AHexValue);
|
||||||
|
AssertFalse('First BigInt from ''' + AHexValue + ''' was less than the second.',
|
||||||
|
a < b);
|
||||||
|
AssertTrue('First BigInt from ''' + AHexValue + ''' was greater than the second.',
|
||||||
|
a <= b);
|
||||||
|
AssertFalse('First BigInt from ''' + AHexValue + ''' was greater than the second.',
|
||||||
|
a > b);
|
||||||
|
AssertTrue('First BigInt from ''' + AHexValue + ''' was less than the second.',
|
||||||
|
a >= b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestLessSameLength;
|
||||||
|
begin
|
||||||
|
TestLessThan('104234FF2B29100C012', '234867AB261F1003429103C');
|
||||||
|
TestLessThan('-9812FB2964AC7632865238BBD3', '294625DF51B2A842582244C18163490');
|
||||||
|
TestLessThan('-12834653A2856DF8', '-A946C2BF89401B8');
|
||||||
|
TestLessThan('-2F846', '0');
|
||||||
|
TestLessThan('0', 'FF67B');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestLessShorterLeft;
|
||||||
|
begin
|
||||||
|
TestLessThan('34FF2B29100C012', '234867AB261F1003429103C');
|
||||||
|
TestLessThan('0', 'BFF008112BA00012');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestLessNegativeShorterRight;
|
||||||
|
begin
|
||||||
|
TestLessThan('-9B72844AC', '1F3486B');
|
||||||
|
TestLessThan('-BB884F022111190', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestGreaterSameLength;
|
||||||
|
begin
|
||||||
|
TestGreaterThan('B042104234FF2B29100C012', '23867AB261F1003429103C');
|
||||||
|
TestGreaterThan('1294B77', '-611F3B93');
|
||||||
|
TestGreaterThan('-782163498326593562D548AAF715B4DC9143E42C68F39A29BB2', '-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF');
|
||||||
|
TestGreaterThan('783BDA0', '0');
|
||||||
|
TestGreaterThan('0', '-99B6D');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestGreaterShorterRight;
|
||||||
|
begin
|
||||||
|
TestGreaterThan('102343234423FF67278B11ADD345F6BB21232C9129100C012', '234867AB261F1003429103C');
|
||||||
|
TestGreaterThan('249D00F63BBAA8668B23', '0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestGreaterNegativeShorterLeft;
|
||||||
|
begin
|
||||||
|
TestGreaterThan('81F2A7B78B812', '-23490D7F19F247F91A365B1893BB701');
|
||||||
|
TestGreaterThan('0', '-80F88242B34127');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestEqualPositive;
|
||||||
|
begin
|
||||||
|
TestEqual('A44B80191059CA123318921A219BB');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestEqualNegative;
|
||||||
|
begin
|
||||||
|
TestEqual('-28912798DD1246DAC9FB4269908012D496896812FF3A8D071B32');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntComparisonTestCase.TestEqualZero;
|
||||||
|
begin
|
||||||
|
TestEqual('0');
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
RegisterTest(TBigIntSignTestCase);
|
||||||
|
RegisterTest(TBigIntFromInt64TestCase);
|
||||||
|
RegisterTest(TBigIntFromHexTestCase);
|
||||||
|
RegisterTest(TBigIntFromBinTestCase);
|
||||||
|
RegisterTest(TBigIntUnaryMinusTestCase);
|
||||||
|
RegisterTest(TBigIntSumTestCase);
|
||||||
|
RegisterTest(TBigIntDifferenceTestCase);
|
||||||
|
RegisterTest(TBigIntProductTestCase);
|
||||||
|
RegisterTest(TBigIntShiftLeftTestCase);
|
||||||
|
RegisterTest(TBigIntEqualityTestCase);
|
||||||
|
RegisterTest(TBigIntComparisonTestCase);
|
||||||
|
end.
|
||||||
|
|
Loading…
Reference in New Issue