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; | ||||
|     FIsNegative: Boolean; | ||||
| 
 | ||||
|     function GetSign: Integer; | ||||
| 
 | ||||
|     // 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. | ||||
|     // 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)) | ||||
|     // where Sign is 1 for ReturnNegative = False and -1 otherwise. | ||||
|     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 | ||||
|     property IsNegative: Boolean read FIsNegative; | ||||
|     property Sign: Integer read GetSign; | ||||
|     class property Zero: TBigInt read GetZero; | ||||
|     function CompareTo(constref AOther: TBigInt): Integer; | ||||
|     function TryToInt64(out AOutput: Int64): Boolean; | ||||
|     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; | ||||
| 
 | ||||
|   { Operators } | ||||
| @ -83,6 +93,10 @@ type | ||||
|   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; | ||||
| 
 | ||||
| implementation | ||||
| 
 | ||||
| @ -98,6 +112,16 @@ const | ||||
| 
 | ||||
| { 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; | ||||
| var | ||||
|   trimmedCount: Integer; | ||||
| @ -105,8 +129,7 @@ begin | ||||
|   trimmedCount := ACount; | ||||
|   while (trimmedCount > 1) and (FDigits[AIndex + trimmedCount - 1] = 0) do | ||||
|     Dec(trimmedCount); | ||||
|   SetLength(Result.FDigits, trimmedCount); | ||||
|   Move(FDigits[AIndex], Result.FDigits[0], CDigitSize * trimmedCount); | ||||
|   Result.FDigits := Copy(FDigits, AIndex, trimmedCount); | ||||
|   Result.FIsNegative := False; | ||||
| end; | ||||
| 
 | ||||
| @ -138,7 +161,7 @@ end; | ||||
| 
 | ||||
| class function TBigInt.AddAbsoluteValues(constref AA, AB: TBigInt; const AReturnNegative: Boolean): TBigInt; | ||||
| var | ||||
|   i, lenA, lenB, len, shorter: Integer; | ||||
|   i, j, lenA, lenB, len, shorter: Integer; | ||||
|   carry: Cardinal; | ||||
| begin | ||||
|   lenA := Length(AA.FDigits); | ||||
| @ -185,9 +208,11 @@ begin | ||||
|   // carry-overs. This avoids additional tests for finding the shorter digit array. | ||||
|   if (i < lenA) or (i < 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 | ||||
|       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. | ||||
|   while (carry > 0) and (i < len) do | ||||
| @ -212,7 +237,7 @@ class function TBigInt.SubtractAbsoluteValues(constref AA, AB: TBigInt; const AR | ||||
| var | ||||
|   a, b: TBigInt; | ||||
|   carry: Cardinal; | ||||
|   i, lastNonZeroDigitIndex, len: Integer; | ||||
|   i, j, lastNonZeroDigitIndex, len: Integer; | ||||
| begin | ||||
|   // Establishes the operand order, such that Abs(a) is not less than Abs(b). | ||||
|   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 | ||||
|   // needs to occur because the most significant digit is not zero. | ||||
|   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 | ||||
|     // Trims leading zeros from the digits array. | ||||
|     Delete(Result.FDigits, lastNonZeroDigitIndex + 1, len - lastNonZeroDigitIndex - 1); | ||||
| @ -362,6 +388,70 @@ begin | ||||
|   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; | ||||
| begin | ||||
|   if FIsNegative = AOther.FIsNegative then | ||||
| @ -372,6 +462,35 @@ begin | ||||
|     Result := -Result; | ||||
| 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; | ||||
| var | ||||
|   absVal: Int64; | ||||
| @ -391,6 +510,16 @@ begin | ||||
|   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 } | ||||
| 
 | ||||
| operator := (const A: Int64): TBigInt; | ||||
| @ -403,9 +532,13 @@ var | ||||
|   len: Integer; | ||||
| begin | ||||
|   len := Length(A.FDigits); | ||||
|   SetLength(Result.FDigits, len); | ||||
|   Move(A.FDigits[0], Result.FDigits[0], len); | ||||
|   Result.FIsNegative := not A.FIsNegative; | ||||
|   if (len > 1) or (A.FDigits[0] > 0) then | ||||
|   begin | ||||
|     Result.FDigits := Copy(A.FDigits, 0, len); | ||||
|     Result.FIsNegative := not A.FIsNegative; | ||||
|   end | ||||
|   else | ||||
|     Result := TBigInt.Zero; | ||||
| end; | ||||
| 
 | ||||
| operator + (const A, B: TBigInt): TBigInt; | ||||
| @ -475,7 +608,10 @@ begin | ||||
|       // Performs full digit shifts by copy if there are no bit shifts. | ||||
|       len := Length(A.FDigits); | ||||
|       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; | ||||
| 
 | ||||
|     Result.FIsNegative := A.IsNegative; | ||||
| @ -492,5 +628,25 @@ 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; | ||||
| 
 | ||||
| operator >= (const A, B: TBigInt): Boolean; | ||||
| begin | ||||
|   Result := A.CompareTo(B) >= 0; | ||||
| end; | ||||
| 
 | ||||
| end. | ||||
| 
 | ||||
|  | ||||
| @ -144,10 +144,18 @@ | ||||
|         <Filename Value="UPolynomialTestCases.pas"/> | ||||
|         <IsPartOfProject Value="True"/> | ||||
|       </Unit> | ||||
|       <Unit> | ||||
|         <Filename Value="..\UPolynomialRoots.pas"/> | ||||
|         <IsPartOfProject Value="True"/> | ||||
|       </Unit> | ||||
|       <Unit> | ||||
|         <Filename Value="UPolynomialRootsTestCases.pas"/> | ||||
|         <IsPartOfProject Value="True"/> | ||||
|       </Unit> | ||||
|       <Unit> | ||||
|         <Filename Value="UBigIntTestCases.pas"/> | ||||
|         <IsPartOfProject Value="True"/> | ||||
|       </Unit> | ||||
|     </Units> | ||||
|   </ProjectOptions> | ||||
|   <CompilerOptions> | ||||
|  | ||||
| @ -9,7 +9,7 @@ uses | ||||
|   UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases, ULensLibraryTestCases, | ||||
|   UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases, | ||||
|   UPulsePropagationTestCases, UStepCounterTestCases, USandSlabsTestCases, ULongWalkTestCases, | ||||
|   UNeverTellMeTheOddsTestCases, UPolynomialTestCases, UPolynomialRootsTestCases; | ||||
|   UNeverTellMeTheOddsTestCases, UBigIntTestCases, UPolynomialTestCases, UPolynomialRootsTestCases; | ||||
| 
 | ||||
| {$R *.res} | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										917
									
								
								tests/UBigIntTestCases.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										917
									
								
								tests/UBigIntTestCases.pas
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user