From 35b7606d7b55ad37a8dd6b2091c639c0d688d0b2 Mon Sep 17 00:00:00 2001 From: rvelthuis Date: Fri, 16 Nov 2018 21:36:08 +0100 Subject: [PATCH] Minor memory leak in AddWithOffset removed --- .gitignore | 3 + Source/Velthuis.Loggers.pas | 203 +- .../BigDecimalDevelopmentTests.dproj | 86 +- .../BigIntegerDevelopmentTests.dpr | 10 +- .../BigIntegerDevelopmentTests.dproj | 6 +- Tests/BigIntegers/TestBigIntegers.pas | 3382 +++++++++-------- .../BigRationalDevelopmentTests.dproj | 155 +- Visualizers/BigNumVisualizers.dpk | 4 +- Visualizers/BigNumVisualizers.dproj | 124 +- Visualizers/BigNumberVisualizers.dproj | 96 +- Visualizers/BigNumbers.dpk | 4 +- Visualizers/BigNumbers.dproj | 124 +- 12 files changed, 2116 insertions(+), 2081 deletions(-) diff --git a/.gitignore b/.gitignore index b8b2e13..6754013 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,9 @@ info.plist.TemplateOSX.xml **/*.printerrors **/FastFibonacci/** ls-tree.txt +**/XBigIntegerDevelopment* +**/Velthuis.Magnitudes.pas +**/X.Big* DataGenerators/BigIntegers/Java/BigIntegerTestDataGenerator/nbproject/private/** DataGenerators/BigIntegers/Java/BigIntegerTestDataGenerator/build/** DataGenerators/BigIntegers/Java/BigIntegerTestDataGenerator/dist/** diff --git a/Source/Velthuis.Loggers.pas b/Source/Velthuis.Loggers.pas index a1136c6..ab8d46a 100644 --- a/Source/Velthuis.Loggers.pas +++ b/Source/Velthuis.Loggers.pas @@ -1,100 +1,103 @@ -{---------------------------------------------------------------------------} -{ } -{ File: Velthuis.Loggers.pas } -{ Function: Very simple logger type } -{ Language: Delphi version XE3 or later } -{ Author: Rudy Velthuis } -{ Copyright: (c) 2016 Rudy Velthuis } -{ } -{ License: Redistribution and use in source and binary forms, with or } -{ without modification, are permitted provided that the } -{ following conditions are met: } -{ } -{ * Redistributions of source code must retain the above } -{ copyright notice, this list of conditions and the following } -{ disclaimer. } -{ * Redistributions in binary form must reproduce the above } -{ copyright notice, this list of conditions and the following } -{ disclaimer in the documentation and/or other materials } -{ provided with the distribution. } -{ } -{ Disclaimer: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" } -{ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT } -{ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND } -{ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO } -{ EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE } -{ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, } -{ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, } -{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, } -{ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED } -{ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT } -{ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) } -{ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF } -{ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } -{ } -{---------------------------------------------------------------------------} - -unit Velthuis.Loggers; - -interface - -uses - System.Classes; - -type - ILogger = interface - ['{B6821CA6-64F8-48B0-89D0-A9A3E6304D82}'] - procedure Log(Msg: string); overload; - procedure Log(Format: string; Args: array of const); overload; - end; - - TLogger = class(TInterfacedObject, ILogger) - private - FStream: TStream; - FWriter: TStreamWriter; - public - constructor Create(S: TStream); overload; - constructor Create(LogFileName: string); overload; - destructor Destroy; override; - procedure Log(Msg: string); overload; - procedure Log(Format: string; Args: array of const); overload; - end; - -implementation - -uses - System.SysUtils; - -{ TLogger } - -constructor TLogger.Create(S: TStream); -begin - FStream := S; - FWriter := TStreamWriter.Create(S); -end; - -constructor TLogger.Create(LogFileName: string); -var - F: TFileStream; -begin - F := TFileStream.Create(LogFileName, fmCreate); - Create(F); -end; - -destructor TLogger.Destroy; -begin - FWriter.Free; - FStream.Free; -end; - -procedure TLogger.Log(Msg: string); -begin - FWriter.WriteLine(Msg); -end; - -procedure TLogger.Log(Format: string; Args: array of const); -begin - FWriter.WriteLine(System.SysUtils.Format(Format, Args)); -end; - -end. +{---------------------------------------------------------------------------} +{ } +{ File: Velthuis.Loggers.pas } +{ Function: Very simple logger type } +{ Language: Delphi version XE3 or later } +{ Author: Rudy Velthuis } +{ Copyright: (c) 2016 Rudy Velthuis } +{ } +{ License: Redistribution and use in source and binary forms, with or } +{ without modification, are permitted provided that the } +{ following conditions are met: } +{ } +{ * Redistributions of source code must retain the above } +{ copyright notice, this list of conditions and the following } +{ disclaimer. } +{ * Redistributions in binary form must reproduce the above } +{ copyright notice, this list of conditions and the following } +{ disclaimer in the documentation and/or other materials } +{ provided with the distribution. } +{ } +{ Disclaimer: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" } +{ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT } +{ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND } +{ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO } +{ EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE } +{ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, } +{ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, } +{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, } +{ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED } +{ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT } +{ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) } +{ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF } +{ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } +{ } +{---------------------------------------------------------------------------} + +unit Velthuis.Loggers; + +interface + +uses + System.Classes; + +type + ILogger = interface + ['{B6821CA6-64F8-48B0-89D0-A9A3E6304D82}'] + procedure Log(Msg: string); overload; + procedure Log(Format: string; Args: array of const); overload; + end; + + TLogger = class(TInterfacedObject, ILogger) + private + FStream: TStream; + FWriter: TStreamWriter; + public + constructor Create(S: TStream); overload; + constructor Create(LogFileName: string); overload; + destructor Destroy; override; + procedure Log(Msg: string); overload; + procedure Log(Format: string; Args: array of const); overload; + end; + +var + Logger: TLogger = nil; + +implementation + +uses + System.SysUtils; + +{ TLogger } + +constructor TLogger.Create(S: TStream); +begin + FStream := S; + FWriter := TStreamWriter.Create(S); +end; + +constructor TLogger.Create(LogFileName: string); +var + F: TFileStream; +begin + F := TFileStream.Create(LogFileName, fmCreate); + Create(F); +end; + +destructor TLogger.Destroy; +begin + FWriter.Free; + FStream.Free; +end; + +procedure TLogger.Log(Msg: string); +begin + FWriter.WriteLine(Msg); +end; + +procedure TLogger.Log(Format: string; Args: array of const); +begin + FWriter.WriteLine(System.SysUtils.Format(Format, Args)); +end; + +end. diff --git a/Tests/BigDecimals/BigDecimalDevelopmentTests.dproj b/Tests/BigDecimals/BigDecimalDevelopmentTests.dproj index 25d8c2f..c2b76fd 100644 --- a/Tests/BigDecimals/BigDecimalDevelopmentTests.dproj +++ b/Tests/BigDecimals/BigDecimalDevelopmentTests.dproj @@ -1,7 +1,7 @@  {DCFEB574-48AF-4E4B-B811-FB7EC60879F8} - 18.4 + 18.5 None True Debug @@ -13,11 +13,6 @@ true - - true - Base - true - true Base @@ -57,9 +52,6 @@ false false - - DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;ibxbindings;FireDACDSDriver;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) - DBXSqliteDriver;RESTComponents;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;SysToolsDBDR;emsclientfiredac;DataSnapFireDAC;svnui;tethering;FireDACADSDriver;DBXMSSQLDriver;SysToolsDR;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;ibxbindings;FireDACDSDriver;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) @@ -147,24 +139,29 @@ true + + + BigDecimalDevelopmentTests.exe + true + + .\ true - - - BigDecimalDevelopmentTests.exe + + true - + true - + true @@ -180,6 +177,11 @@ true + + + true + + 1 @@ -189,7 +191,6 @@ 1 - Contents\MacOS 0 @@ -199,6 +200,12 @@ 1 + + + res\xml + 1 + + library\lib\armeabi-v7a @@ -236,6 +243,12 @@ 1 + + + res\values-v21 + 1 + + res\drawable @@ -314,6 +327,11 @@ 1 .framework + + Contents\MacOS + 1 + .framework + 0 @@ -336,6 +354,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .dll;.bpl @@ -359,6 +382,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .bpl @@ -381,6 +409,10 @@ Contents\Resources\StartUp\ 0 + + Contents\Resources\StartUp\ + 0 + 0 @@ -517,23 +549,41 @@ 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + ..\ 1 + + ..\ + 1 + Contents 1 + + Contents + 1 + Contents\Resources 1 + + Contents\Resources + 1 + @@ -556,6 +606,10 @@ Contents\MacOS 1 + + Contents\MacOS + 1 + 0 @@ -595,11 +649,11 @@ + False - False True True diff --git a/Tests/BigIntegers/BigIntegerDevelopmentTests.dpr b/Tests/BigIntegers/BigIntegerDevelopmentTests.dpr index 4232c57..aed52e5 100644 --- a/Tests/BigIntegers/BigIntegerDevelopmentTests.dpr +++ b/Tests/BigIntegers/BigIntegerDevelopmentTests.dpr @@ -12,16 +12,18 @@ program BigIntegerDevelopmentTests; } // FastMM4 can slow down testing a lot. -{ $DEFINE USEFASTMM4} +{$DEFINE USEFASTMM4} {$IFDEF CONSOLE_TESTRUNNER} {$APPTYPE CONSOLE} {$ENDIF} +{$WARN UNIT_EXPERIMENTAL OFF} + uses - {$IFDEF USEFASTMM4} +{$IFDEF USEFASTMM4} FastMM4, - {$ENDIF } +{$ENDIF } DUnitTestRunner, Velthuis.Sizes in '..\..\Source\Velthuis.Sizes.pas', Velthuis.RandomNumbers in '..\..\Source\Velthuis.RandomNumbers.pas', @@ -40,7 +42,9 @@ uses {$R *.RES} begin +{$IFDEF USEFASTMM4} ReportMemoryLeaksOnShutdown := True; +{$ENDIF} DoDebug := False; DUnitTestRunner.RunRegisteredTests; end. diff --git a/Tests/BigIntegers/BigIntegerDevelopmentTests.dproj b/Tests/BigIntegers/BigIntegerDevelopmentTests.dproj index 66fd0fc..cd58592 100644 --- a/Tests/BigIntegers/BigIntegerDevelopmentTests.dproj +++ b/Tests/BigIntegers/BigIntegerDevelopmentTests.dproj @@ -65,7 +65,7 @@ None BigIntegerDevelopmentTests _CONSOLE_TESTRUNNER;$(DCC_Define) - $(BDS)\Source\DUnit\src;$(DCC_UnitSearchPath) + $(BDS)\Source\DUnit\src;D:\Source\DropBox\Delphi\FastMM4-master\;$(DCC_UnitSearchPath) System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) $(Platform)\$(Config) $(Platform)\$(Config) @@ -88,9 +88,8 @@ DEBUG;$(DCC_Define) true - false - true true + true true @@ -111,6 +110,7 @@ auto 1033 true + D:\Source\DropBox\Delphi\FastMM4-master;$(DCC_UnitSearchPath) false diff --git a/Tests/BigIntegers/TestBigIntegers.pas b/Tests/BigIntegers/TestBigIntegers.pas index 1b75c66..243c729 100644 --- a/Tests/BigIntegers/TestBigIntegers.pas +++ b/Tests/BigIntegers/TestBigIntegers.pas @@ -1,1689 +1,1693 @@ -unit TestBigIntegers; - -//////////////////////////////////////////////////////////////////////////////////////// -// // -// Delphi DUnit Test Case // -// ---------------------- // -// This unit contains a skeleton test case class generated by the Test Case Wizard. // -// Modify the generated code to correctly setup and call the methods from the unit // -// being tested. // -// // -//////////////////////////////////////////////////////////////////////////////////////// - -interface - -uses - TestFramework, - System.Types, - System.Generics.Defaults, - System.SysUtils, - System.Math, - Velthuis.BigIntegers, - Velthuis.RandomNumbers, - Velthuis.Loggers; - -{$IF BigInteger.Immutable} -{$DEFINE IMMUTABLE} -{$IFEND} - -{$IF RTLVersion >= 29.0} -{$DEFINE HASINVARIANT} -{$IFEND} - -type - // Test methods for BigInteger records. - TTestBigInteger = class(TTestCase) -// strict private -// A, B, C, D, E, F: BigInteger; - public - procedure Error(const Msg: string); - procedure SetUp; override; - procedure TearDown; override; - published - procedure TestParse; - procedure TestTryParse; - procedure TestCreateBytes; - procedure TestCreateRandom; - procedure TestCreateDouble; - procedure TestIsZero; - procedure TestIsPositive; - procedure TestIsEven; - procedure TestIsPowerOfTwo; - procedure TestIsOne; - procedure TestToString; - procedure TestToHex; - procedure TestTestBit; - procedure TestSetBit; - procedure TestClearBit; - procedure TestFlipBit; - procedure TestAdd; -{$IFNDEF IMMUTABLE} - procedure TestAddFunction; - procedure TestInc; - procedure TestDec; -{$ENDIF} - procedure TestSubtract; - procedure TestMultiply; - procedure TestMultiplyKaratsuba; - procedure TestMultiplyToomCook3; - procedure TestIntDivide; - procedure TestIntDivide16; - procedure TestIntDivide32; - procedure TestModulus; - procedure TestModulus16; - procedure TestModulus32; - procedure TestSquare; - procedure TestNegative; - procedure TestBitwiseAnd; - procedure TestBitwiseOr; - procedure TestBitwiseXor; - procedure TestLogicalNot; - procedure TestLeftShift; - procedure TestRightShift; - procedure TestEqual; - procedure TestNotEqual; - procedure TestGreaterThan; - procedure TestGreaterThanOrEqual; - procedure TestLessThan; - procedure TestLessThanOrEqual; - procedure TestAsDouble; - procedure TestAsInteger; - procedure TestAsCardinal; - procedure TestAsInt64; - procedure TestAsUInt64; - procedure TestDivMod; - procedure TestDivModKnuth; - procedure TestDivModBurnikelZiegler; - procedure TestDivMod16; - procedure TestDivMod32; -// procedure TestAbs; - procedure TestBitLength; - procedure TestGreatestCommonDivisor; - procedure TestLn; - procedure TestMax; - procedure TestMin; - procedure TestModPow; - procedure TestPow; - procedure TestNthRoot; - procedure TestSqrt; - procedure TestToByteArray; - procedure TestModInverse; - procedure TestFactorial; - procedure TestPred; - procedure TestSucc; - end; - -implementation - -{$IFDEF MSWINDOWS} -uses - Winapi.Windows; -{$ENDIF} - -{$I 'BigIntegerTestResults.inc'} -{$I 'BigIntegerArithmeticResults.inc'} -{$I 'BigIntegerBitwiseResults.inc'} -{$I 'BigIntegerConvertResults.inc'} -{$I 'BigIntegerMathResults.inc'} - -procedure TTestBigInteger.Error(const Msg: string); -begin -{$IFDEF MSWINDOWS} - OutputDebugString(PChar(Msg)); -{$ELSE} - {$IFDEF CONSOLE} - Writeln(ErrOutput, Msg); - {$ENDIF} -{$ENDIF} -end; - -procedure TTestBigInteger.SetUp; -begin -{$IF HASINVARIANT} - Status(Format('Compiler version: %0.1f', [System.CompilerVersion], TFormatSettings.Invariant)); -{$ELSE} - Status(Format('Compiler version: %0.1f', [System.CompilerVersion])); -{$ENDIF} -{$IFDEF WIN64} - Status('Win64'); -{$ENDIF} -{$IFDEF WIN32} - Status('Win32'); -{$ENDIF} - if Velthuis.BigIntegers.PurePascal then - Status('PUREPASCAL') - else - begin - if BigInteger.StallAvoided then - Status('Asssembler: partial flag stall code used') - else - Status('Assembler: plain code'); - end; -end; - -procedure TTestBigInteger.TearDown; -begin -end; - -procedure TTestBigInteger.TestIsZero; -var - MinusOne, One, Zero: BigInteger; -begin - MinusOne := '-1'; - One := '1'; - Zero := '0'; - - Check(not MinusOne.IsZero); - Check(not One.IsZero); - Check(Zero.IsZero); -end; - -procedure TTestBigInteger.TestIsPositive; -var - MinusOne, One, Zero: BigInteger; -begin - MinusOne := '-1'; - One := '1'; - Zero := '0'; - - Check(not MinusOne.IsPositive); - Check(One.IsPositive); - Check(not Zero.IsPositive); -end; - -procedure TTestBigInteger.TestIsEven; -var - A, B, C, D, E: BigInteger; -begin - A := -1234; - B := -1233; - C := 0; - D := 1233; - E := 1234; - - CheckTrue(A.IsEven); - CheckFalse(B.IsEven); - CheckTrue(C.IsEven); - CheckFalse(D.IsEven); - CheckTrue(E.IsEven); -end; - -procedure TTestBigInteger.TestIsPowerOfTwo; -var - I: Integer; - Value, MinusValue, ValueMinusOne, ValuePlusOne, MinusValueMinusOne, MinusValuePlusOne: BigInteger; - - function Msg(const S: string; const Int: BigInteger): string; - begin - Result := Format('(%d) Value = %s (hex), A = %s (hex), Info: %s', [I, Int.ToString(16), Value.ToString(16), S]); - end; - -begin - Value := 4; - for I := 4 to 100 do - begin - Value := Value shl 1; - MinusValue := -Value; - ValueMinusOne := Value - BigInteger.One; - ValuePlusOne := Value + BigInteger.One; - MinusValueMinusOne := MinusValue - BigInteger.One; - MinusValuePlusOne := MinusValue + BigInteger.One; - - CheckTrue(Value.IsPowerOfTwo, Msg('A', Value)); - CheckTrue(MinusValue.IsPowerOfTwo, Msg('-A', MinusValue)); - CheckFalse(ValueMinusOne.IsPowerOfTwo, Msg('A - 1', ValueMinusOne)); - CheckFalse(ValuePlusOne.IsPowerOfTwo, Msg('A + 1', ValuePlusOne)); - CheckFalse(MinusValueMinusOne.IsPowerOfTwo, Msg('-A - 1', MinusValueMinusOne)); - CheckFalse(MinusValuePlusOne.IsPowerOfTwo, Msg('-A + 1', MinusValuePlusOne)); - end; -end; - -procedure TTestBigInteger.TestIsOne; -var - MinusOne, One, Zero: BigInteger; -begin - MinusOne := BigInteger.MinusOne; - One := BigInteger.One; - Zero := '0'; - - CheckFalse(MinusOne.IsOne); - CheckTrue(One.IsOne); - CheckFalse(Zero.IsOne); -end; - -procedure TTestBigInteger.TestToString; -var - I: Integer; - ValueStr, CheckStr: string; - Value: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - BigInteger.Decimal; - Value := Arguments[I]; - ValueStr := Value.ToString; - CheckStr := Arguments[I]; - Check(ValueStr = CheckStr); - BigInteger.Hexadecimal; - ValueStr := Value.ToString; - CheckStr := HexResults[I].val; - Check(ValueStr = CheckStr); - BigInteger.Decimal; - end; -end; - -procedure TTestBigInteger.TestTryParse; -var - I: Integer; - Res: TTryParseResult; - Value: BigInteger; -begin - for I := Low(TryParseResults) to High(TryParseResults) do - begin - Res := TryParseResults[I]; - Check(BigInteger.TryParse(Res.Str, Res.Base, Value) = Res.Result); - if Res.Result then - Check(Value.ToString(10) = Res.Str10); - end; -end; - -procedure TTestBigInteger.TestToHex; -var - I: Integer; - S1, S2: string; - Value: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - S1 := Value.ToHexString; - S2 := HexResults[i].val; - Check(S1 = S2); - end; -end; - -procedure TTestBigInteger.TestAdd; -var - I, J, N: Integer; - Left, Right, Sum, CheckSum: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - try - Sum := Left + Right; - except - on E: Exception do - Error(E.ClassName + ': ' + E.Message); - end; - CheckSum := AddResults[N].val; - Check(Sum = CheckSum, Format('(%d,%d) %s + %s = %s (%s, diff=%s)', [I, J, Left.ToString(16), Right.ToString(16), Sum.ToString(16), CheckSum.ToString(16), (Sum - CheckSum).ToString(16)])); - Inc(N); - end; - end; -end; - -{$IF not BigInteger.Immutable} -procedure TTestBigInteger.TestAddFunction; -var - I, J, N: Integer; - A, B, C, D: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - for J := 0 to High(Arguments) do - begin - B := Arguments[J]; - try - C := A; - C.Add(B); - except - on E: Exception do - Error(E.ClassName + ': ' + E.Message); - end; - D := AddResults[N].val; - Check(C = D, Format('(%d,%d) %s + %s = %s (%s)', [I, J, A.ToString(16), B.ToString(16), C.ToString(16), D.ToString(16)])); - Inc(N); - end; - end; -end; -{$ENDIF} - -procedure TTestBigInteger.TestSetBit; -var - I, J, N, Bit: Integer; - Value, BitSet: BigInteger; - TR: TTestResult; -begin - N := Length(bits); - for I := 1 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to High(Bits) do - begin - Bit := Bits[J]; - TR := SetBitResults[N]; - Inc(N); - BitSet := Value.SetBit(Bit); - Check(BitSet = BigInteger(TR.Val), Format('(%d,%d): $%s.SetBit(%d) = $%s ($%s)', [I, J, Value.ToString(16), Bit, BitSet.ToString(16), BigInteger(TR.val).ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestClearBit; -var - I, J, N, Bit: Integer; - Value, Cleared: BigInteger; - TR: TTestResult; -begin - N := Length(bits); - for I := 1 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to High(Bits) do - begin - Bit := Bits[J]; - TR := ClearBitResults[N]; - Inc(N); - Cleared := Value.ClearBit(Bit); - Check(Cleared = BigInteger(TR.Val), Format('(%d,%d): $%s.ClearBit(%d) = $%s ($%s)', [I, J, Value.ToString(16), Bit, Cleared.ToString(16), BigInteger(TR.val).ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestFactorial; -var - I, N: Integer; - Value, CheckValue: BigInteger; -begin - for I := 0 to High(BitShifts) do - begin - N := BitShifts[I]; - Value := BigInteger.Factorial(N); - CheckValue := FactorialResults[I].Val; - Check(Value = CheckValue); - end; -end; - -procedure TTestBigInteger.TestFlipBit; -var - I, J, N, Bit: Integer; - Value, Flipped: BigInteger; - TR: TTestResult; -begin - N := Length(bits); - for I := 1 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to High(Bits) do - begin - Bit := Bits[J]; - TR := FlipBitResults[N]; - Inc(N); - Flipped := Value.FlipBit(Bit); - Check(Flipped = BigInteger(TR.Val), Format('(%d,%d): $%s.FlipBit(%d) = $%s ($%s)', [I, J, Value.ToString(16), Bit, Flipped.ToString(16), BigInteger(TR.val).ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestSqrt; -var - I, Exp: Integer; - Base, Arg, Root, RootSquared, RootPlusOneSquared: BigInteger; -begin - for I := 10 to High(BitShifts) do - begin - Base := BitShifts[I]; - for Exp := 2 to 100 do - begin - Arg := BigInteger.Pow(Base, Exp) + BigInteger.Pow(Base, Exp - 1); - Root := BigInteger.Sqrt(Arg); - RootSquared := Root * Root; - RootPlusOneSquared := (Root + 1) * (Root + 1); - Check((RootSquared <= Arg) and (Arg < RootPlusOneSquared), Format('(%d,%d) Sqrt(%s) = %s (%s not in [%s..%s])', [I, Exp, Arg.ToString(16), Root.ToString(16), Arg.ToString(16), RootSquared.ToString(16), RootPlusOneSquared.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestSquare; -var - I: Integer; - Value, Square, CheckSquare: BigInteger; -begin - for I := 0 to High(MultiplyResults) do - begin - Value := MultiplyResults[I].val; - Square := BigInteger.Sqr(Value); - CheckSquare := Value * Value; - Check(Square = CheckSquare, Format('(%d) Sqr(%s) = %s (%s)', [I, Value.ToString(16), Square.ToString(16), CheckSquare.ToString(16)])); - end; -end; - -procedure TTestBigInteger.TestSubtract; -var - I, J, N: Integer; - Minuend, Subtrahend, Difference, CheckDifference: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Minuend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Subtrahend := Arguments[J]; - try - Difference := Minuend - Subtrahend; - except - on E: Exception do - Error(E.ClassName + ': ' + E.Message); - end; - CheckDifference := SubtractResults[N].val; - Check(Difference = CheckDifference, Format('(%d,%d) %s - %s = %s (%s)', [I, J, Minuend.ToString, Subtrahend.ToString, Difference.ToString, CheckDifference.ToString])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestSucc; -var - Value, Successor, ValuePlusOne: BigInteger; - I: Integer; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - Successor := Value.Succ; - ValuePlusOne := Value + BigInteger.One; - Check(Successor = ValuePlusOne, Format('(%d) Pred(%s) = %s (%s)', [I, string(Value), string(Successor), string(ValuePlusOne)])); - end; -end; - -procedure TTestBigInteger.TestMultiply; -var - I, J, N: Integer; - S, ErrorMsg: string; - Left, Right, Product, CheckProduct: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - S := MultiplyResults[N].val; - CheckProduct := S; - try - Product := BigInteger.Multiply(Left, Right); - except - on E: Exception do - Error('Multiplication error, ' + E.ClassName + ': ' + E.Message); - end; - ErrorMsg := Format('(%d,%d,%d) %s * %s = %s (%s, diff = %s)', [I, J, N, Left.ToString(16), Right.ToString(16), Product.ToString(16), CheckProduct.ToString(16), (CheckProduct - Product).ToString(16)]); - Check(Product = CheckProduct, ErrorMsg); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestMultiplyKaratsuba; -var - I: Integer; - R: IRandom; - BaseFactor, Factor, Product, BaseCaseProduct: BigInteger; -begin - R := TDelphiRandom.Create($123456); - BaseFactor := BigInteger.Create((BigInteger.KaratsubaThreshold + Random(100)) * 32, R); - for I := 1 to 20 do - begin - Factor := BigInteger.Create((BigInteger.KaratsubaThreshold + Random(100)) * 32, R); - BigInteger.MultiplyKaratsuba(BaseFactor, Factor, Product); - - // It is safe to assume that result given by MultiplyBaseCase is correct. - BigInteger.MultiplyBaseCase(BaseFactor, Factor, BaseCaseProduct); - - Check(Product = BaseCaseProduct, Format('(%d x %d): %s * %s = %s (%s), diff = %s', [BaseFactor.Size, Factor.Size, BaseFactor.ToString(16), Factor.ToString(16), Product.ToString(16), BaseCaseProduct.ToString(16), (Product - BaseCaseProduct).ToString(16)])); - BaseFactor := Factor; - end; -end; - -procedure TTestBigInteger.TestMultiplyToomCook3; -var - I: Integer; - R: IRandom; - BaseFactor, Factor, Product, BaseCaseProduct: BigInteger; -begin - R := TDelphiRandom.Create($123456); - BaseFactor := BigInteger.Create((BigInteger.ToomCook3Threshold + Random(100)) * 32, R); - for I := 1 to 20 do - begin - Factor := BigInteger.Create((BigInteger.ToomCook3Threshold + Random(100)) * 32, R); - Product := BigInteger.MultiplyToomCook3(BaseFactor, Factor); - - // It is safe to assume that result given by MultiplyBaseCase is correct. - BigInteger.MultiplyBaseCase(BaseFactor, Factor, BaseCaseProduct); - - Check(Product = BaseCaseProduct, Format('(%d x %d): %s * %s = %s (%s), diff = %s', [BaseFactor.Size, Factor.Size, BaseFactor.ToString(16), Factor.ToString(16), Product.ToString(16), BaseCaseProduct.ToString(16), (Product - BaseCaseProduct).ToString(16)])); - BaseFactor := Factor; - end; -end; - -{$IFNDEF IMMUTABLE} -procedure TTestBigInteger.TestInc; -var - I: Integer; - Value, SuccValue, IncValue: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - SuccValue := Value + 1; - IncValue := Value; - Inc(IncValue); - Check(IncValue = SuccValue, Format('(%d) %s --> %s (%s)', [I, Value.ToString(16), IncValue.ToString(16), SuccValue.ToString(16)])); - end; -end; -{$ENDIF} - -procedure TTestBigInteger.TestIntDivide; -var - I, J, N: Integer; - TR: TTestResult; - Dividend, Divisor, Quotient, CheckQuotient: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[J]; - TR := DivisionResults[N]; - Inc(N); - try - Quotient := Dividend div Divisor; - except - on E: EZeroDivide do - begin - Check(TR.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); - Continue; - end; - on E: Exception do - Error('TestIntDivide: Unexpected ' + E.ClassName + ' exception: ''' + E.Message + ''''); - end; - Check(TR.info = triOk, Format('(%d,%d) Expected an exception', [I, J])); - CheckQuotient := TR.val; - Check(Quotient = CheckQuotient, Format('(%d,%d) %s div %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Quotient.ToString(16), CheckQuotient.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestIntDivide16; -var - I, J: Integer; - U16: UInt16; - Dividend, Divisor, U16Equiv, U16Quotent, U16EquivQuotient: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[I]; - U16 := UInt16(Divisor); - U16Equiv := U16; - if U16 = 0 then - Continue; - U16Quotent := Dividend div U16; - U16EquivQuotient := Dividend div U16Equiv; - Check(U16EquivQuotient = U16Quotent, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16Quotent.ToString(16), U16EquivQuotient.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestIntDivide32; -var - I, J: Integer; - U32: UInt16; - Dividend, Divisor, U32Equiv, U32Quotient, U32EquivQuotient: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[I]; - U32 := UInt32(Divisor); - U32Equiv := U32; - if U32 = 0 then - Continue; - U32Quotient := Dividend div U32; - U32EquivQuotient := Dividend div U32Equiv; - Check(U32EquivQuotient = U32Quotient, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32Quotient.ToString(16), U32EquivQuotient.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestModInverse; -var - I, J, N: Integer; - TR: TTestResult; - Value, Modulus, Inverse: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Modulus := Arguments[J]; - TR := InvModResults[N]; - Inc(N); - // Only test if B <> 0 and A, B are coprime. - if Modulus.IsZero or (BigInteger.GreatestCommonDivisor(Value, Modulus) <> BigInteger.One) then - Continue; - try - Inverse := BigInteger.Zero; - Inverse := BigInteger.ModInverse(Value, Modulus); - except - on E: Exception do - begin - Check(TR.Info <> triOk, Format('(%d,%d,%d): Unexpected exception %s: %s', [I, J, N - 1, E.ClassName, E.Message])); - Continue; - end; - end; - Check(TR.Info = triOk, Format('(%d,%d,%d): Unexpected error ''%s''', [I, J, N - 1, TR.Val])); - Check(Inverse = BigInteger(TR.Val), Format('(%d,%d): ModInverse: %s * %s mod %s = %s', [I, J, Value.ToString, Inverse.ToString, Modulus.ToString, (Value * Inverse mod Modulus).ToString])); - end; - end; -end; - -procedure TTestBigInteger.TestModulus; -var - I, J, N: Integer; - TR: TTestResult; - Dividend, Divisor, Modulus, CheckModulus: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[J]; - TR := ModulusResults[N]; - Inc(N); - try - Modulus := Dividend mod Divisor; - except - on E: EZeroDivide do - begin - Check(TR.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); - Continue; - end; - on E: Exception do - Error('TestModulus: Unexpected ' + E.ClassName + ' exception: ' + E.Message); - end; - Check(TR.info = triOk, Format('(%d,%d) Expected exception did not occur', [I, J])); - CheckModulus := TR.Val; - Check(Modulus = CheckModulus, Format('(%d,%d) %s mod %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Modulus.ToString(16), CheckModulus.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestModulus16; -var - I, J: Integer; - U16: UInt16; - Dividend, Divisor, U16Equiv, U16Quot, U16EquivQuot: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[I]; - U16 := UInt16(Divisor); - U16Equiv := U16; - if U16 = 0 then - Continue; - U16Quot := Dividend mod U16; - U16EquivQuot := Dividend mod U16Equiv; - Check(U16EquivQuot = U16Quot, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16Quot.ToString(16), U16EquivQuot.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestModulus32; -var - I, J: Integer; - U32: UInt32; - Dividend, Divisor, U32Equiv, U32Mod, U32EquivMod: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[I]; - U32 := UInt32(Divisor); - U32Equiv := U32; - if U32 = 0 then - Continue; - U32Mod := Dividend mod U32; - U32EquivMod := Dividend mod U32Equiv; - Check(U32EquivMod = U32Mod, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32Mod.ToString(16), U32EquivMod.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestNegative; -var - I: Integer; - Value, Negated, CheckNegated: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - Negated := -Value; - CheckNegated := NegationResults[I].val; - Check(Negated = CheckNegated); - end; -end; - -procedure TTestBigInteger.TestBitwiseAnd; -var - I, J, N: Integer; - Left, Right, Anded, CheckAnded: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - try - Anded := Left and Right; - except - on E: Exception do - Error(E.ClassName + ': ' + E.Message); - end; - CheckAnded := BitwiseAndResults[N].val; - Check(Anded = CheckAnded, Format('(%d,%d) %s and %s = %s (%s)', [I, J, Left.ToString(16), Right.ToString(16), Anded.ToString(16), CheckAnded.ToString(16)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestBitwiseOr; -var - I, J, N: Integer; - Left, Right, Ored, CheckOred: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - try - Ored := Left or Right; - except - on E: Exception do - Error(E.ClassName + ': ' + E.Message); - end; - CheckOred := BitwiseOrResults[N].val; - Check(Ored = CheckOred, Format('(%d,%d) %s or %s = %s (%s)', [I, J, Left.ToString(16), Right.ToString(16), Ored.ToString(16), CheckOred.ToString(16)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestBitwiseXor; -var - I, J, N: Integer; - Left, Right, Xored, CheckXored: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - try - Xored := Left xor Right; - except - on E: Exception do - Error(E.ClassName + ': ' + E.Message); - end; - CheckXored := BitwiseXorResults[N].val; - Check(Xored = CheckXored, Format('(%d,%d) %s xor %s = %s (%s)', [I, J, Left.ToString(16), Right.ToString(16), Xored.ToString(16), CheckXored.ToString(16)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestCreateBytes; -var - I: Integer; - Bytes: TArray; - Value, FromBytes: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - Bytes := Value.ToByteArray; - FromBytes := BigInteger.Create(Bytes); - Check(Value = FromBytes, Format('(%d), Create(%s.ToByteArray) = %s', [I, Value.ToString(16), FromBytes.ToString(16)])); - end; -end; - -procedure TTestBigInteger.TestCreateDouble; -var - I: Integer; - Value, CheckValue: BigInteger; -begin - BigInteger.RoundingMode := BigInteger.TRoundingMode.rmTruncate; - for I := 0 to High(Doubles) do - begin - Value := BigInteger.Create(Doubles[I]); - CheckValue := CreateDoubleResults[I].val; - Check(Value = CheckValue, Format('(%d) BigInteger.Create(%f) = %s (%s)', [I, Doubles[I], Value.ToString(16), CheckValue.ToString(16)])); - end; -end; - -procedure TTestBigInteger.TestCreateRandom; -var - I, NumBits: Integer; - ARandom: IRandom; - Value: BigInteger; -begin - ARandom := TDelphiRandom.Create; - for I := 0 to 1000 do - begin - NumBits := I; - Value := BigInteger.Create(NumBits, ARandom); - Check(Value.BitLength <= NumBits, Format('%s (bits = %d), Numbits = %d', [Value.ToString(16), Value.BitLength, NumBits])); - end; -end; - -procedure TTestBigInteger.TestLogicalNot; -var - I: Integer; - Value, NotValue, CheckNotValue: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - NotValue := not Value; - CheckNotValue := LogicalNotResults[I].val; - Check(NotValue = CheckNotValue, Format('(%d) not %s = %s (%s)', [I, Value.ToString(16), NotValue.ToString(16), CheckNotValue.ToString(16)])); - end; -end; - -procedure TTestBigInteger.TestLeftShift; -var - I, J, N, Shift: Integer; - Value, Shifted, CheckShifted: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to High(BitShifts) do - begin - Shift := BitShifts[J]; - Shifted := Value shl Shift; - CheckShifted := LeftShiftResults[N].val; - Check(Shifted = CheckShifted, Format('(%d,%d) %s shl %d = %s (%s)', [I, J, Value.ToString(16), Shift, Shifted.ToString(16), CheckShifted.ToString(16)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestRightShift; -var - I, J, N, Shift: Integer; - Value, Shifted, CheckShifted: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to High(BitShifts) do - begin - Shift := BitShifts[J]; - Shifted := Value shr Shift; - CheckShifted := RightShiftResults[N].val; - Check(Shifted = CheckShifted, Format('(%d,%d) %s shr %d = %s (%s)', [I, J, Value.ToString(16), Shift, Shifted.ToString(16), CheckShifted.ToString(16)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestEqual; -var - I, J, N: Integer; - Comp, CheckComp: Boolean; - Left, Right: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - Comp := Left = Right; - CheckComp := ComparisonResults[N, crEqual]; - Check(Comp = CheckComp, Format('%d,%d: %s = %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestNotEqual; -var - I, J, N: Integer; - Comp, CheckComp: Boolean; - Left, Right: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - Comp := Left <> Right; - CheckComp := ComparisonResults[N, crNotEqual]; - Check(Comp = CheckComp, Format('%d,%d: %s <> %s: %s (%s)', [I, j, Arguments[I], Arguments[j], BoolToStr(Comp), BoolToStr(CheckComp)])); - Inc(N); - end; - end; -end; - -// Seems to have become slower since the code change. Is the old method (binary search) better for the relatively small values tested here? -procedure TTestBigInteger.TestNthRoot; -var - I, Exponent: Integer; - Value, TestValue, Root, PowerOfRoot, PowerOfRootPlusOne: BigInteger; -begin - for I := 0 to High(BitShifts) do - begin - Value := BitShifts[I]; - Exponent := 2; - while Exponent <= 100 do - begin - TestValue := BigInteger.Pow(Value, Exponent) + BigInteger.Pow(Value, Exponent - 1); - Root := BigInteger.NthRoot(TestValue, Exponent); - PowerOfRoot := BigInteger.Pow(Root, Exponent); - PowerOfRootPlusOne := BigInteger.Pow(Root.Succ, Exponent); - if not ((PowerOfRoot <= TestValue) and (TestValue < PowerOfRootPlusOne)) then - Writeln(Format('(%d,%d) NthRoot(%s, %d) = %s (%s)', [I, Exponent, TestValue.ToString(16), Exponent, Root.ToString(16), Value.ToString(16)])); - Inc(Exponent, 5); - end; - end; -end; - -procedure TTestBigInteger.TestTestBit; -var - I, J: Integer; - BitIsSet, CheckBitIsSet: Boolean; - Rand: Integer; - Value, ShiftedValue: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - for J := 0 to 19 do - begin - Rand := System.Random(Value.BitLength + 4 * SizeOf(TLimb)); - ShiftedValue := BigInteger.One shl Rand; - BitIsSet := Value.TestBit(Rand); - CheckBitIsSet := (ShiftedValue and Value) <> 0; - Check(BitIsSet = CheckBitIsSet, Format('%d,%d: %s.TestBit(%d): %s (%s) <-- %s (%s)', [I, J, Value.ToString(16), Rand, BoolToStr(BitIsSet), BoolToStr(CheckBitIsSet), Value.ToString(16), ShiftedValue.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestGreaterThan; -var - I, J, N: Integer; - Comp, CheckComp: Boolean; - Left, Right: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - Comp := Left > Right; - CheckComp := ComparisonResults[N, crGreater]; - Check(Comp = CheckComp, Format('%d,%d: %s > %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestGreaterThanOrEqual; -var - I, J, N: Integer; - Comp, CheckComp: Boolean; - Left, Right: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - Comp := Left >= Right; - CheckComp := ComparisonResults[N, crGreaterEqual]; - Check(Comp = CheckComp, Format('%d,%d: %s >= %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestLessThan; -var - I, J, N: Integer; - Comp, CheckComp: Boolean; - Left, Right: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - Comp := Left < Right; - CheckComp := ComparisonResults[N, crLess]; - Check(Comp = CheckComp, Format('%d,%d: %s < %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestLessThanOrEqual; -var - I, J, N: Integer; - Comp, CheckComp: Boolean; - Left, Right: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Left := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Right := Arguments[J]; - Comp := Left <= Right; - CheckComp := ComparisonResults[N, crLessEqual]; - Check(Comp = CheckComp, Format('%d,%d: %s <= %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); - Inc(N); - end; - end; -end; - -function Dbl2Hex(const D: Double): string; -begin - Result := Format('%.8X', [PUInt64(@D)^]); -end; - -procedure TTestBigInteger.TestAsDouble; -var - I: Integer; - D1, D2: Double; - Value: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - D1 := Value.AsDouble; - D2 := DoubleResults[I]; - if IsInfinite(D1) then - Check(IsInfinite(D2)) - else if IsNan(D1) then - Check(IsNan(D2)) - else - Check(SameValue(D1, D2), Format('(%d): Double(%s) = %0.15f # $%s (%0.15f # $%s)', [I, Value.ToString, D1, Dbl2Hex(D1), D2, Dbl2Hex(D2)])); - end; -end; - -procedure TTestBigInteger.TestAsInteger; -var - I, Int1, Int2: Integer; - A: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - try - Int1 := A.AsInteger; - Int2 := StrToInt(AsIntegerResults[I].val); - Check(Int1 = Int2); - except - on E: EConvertError do - Check(AsIntegerResults[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); - on E: Exception do - Error('TestAsInteger: Unexpected exception: ' + E.ClassName + ': ' + E.Message); - end; - end; -end; - -procedure TTestBigInteger.TestAsCardinal; -var - I: Integer; - Card1, Card2: Cardinal; - A: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - try - Card1 := A.AsCardinal; - Card2 := StrToInt(AsCardinalResults[I].val); - Check(Card1 = Card2, Format('%d: %d (%d)', [I, Card1, Card2])); - except - on E: EConvertError do - Check(AsCardinalResults[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); - on E: Exception do - Error('TestAsCardinal: Unexpected exception: ' + E.ClassName + ': ' + E.Message); - end; - end; -end; - -procedure TTestBigInteger.TestAsInt64; -var - I: Integer; - Int1, Int2: Int64; - Value: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - try - Int1 := Value.AsInt64; - Int2 := StrToInt64(AsInt64Results[I].val); - Check(Int1 = Int2); - except - on E: EConvertError do - Check(AsInt64Results[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); - on E: Exception do - Error('TestAsInt64: Unexpected exception: ' + E.ClassName + ': ' + E.Message); - end; - end; -end; - -procedure TTestBigInteger.TestAsUInt64; -var - I: Integer; - UInt1: UInt64; - S1, S2: string; - Value: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - try - // Must use string comparison, because on some versions there is no suitable StrToUInt64, so - // there is no way to compare UInt64s. - UInt1 := Value.AsUInt64; - S1 := Format('%u', [UInt1]); - except - on E: EConvertError do - begin - Check(AsUInt64Results[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); - Continue; - end; - on E: Exception do - Error('TestAsUInt64: Unexpected exception: ' + E.ClassName + ': ' + E.Message); - end; - S2 := AsUInt64Results[I].val; - Check(S1 = S2, Format('%d: %s.ToUInt64 = %s (%s)', [I, Value.ToString, S1, S2])); - end; -end; - -{$IFNDEF IMMUTABLE} -procedure TTestBigInteger.TestDec; -var - I: Integer; - Value, PredValue, DecValue: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - PredValue := Value - 1; - DecValue := Value; - Dec(DecValue); - Check(DecValue = PredValue, Format('(%d) %s --> %s (%s)', [I, Value.ToString, DecValue.ToString, PredValue.ToString])); - Check(Value = PredValue + 1); - end; -end; -{$ENDIF} - -procedure TTestBigInteger.TestDivMod; -var - I, J, N: Integer; - TRDiv, TRMod: TTestResult; - Dividend, Divisor, Quotient, Remainder, CheckQ, CheckR: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[J]; - TRDiv := DivisionResults[N]; - TRMod := ModulusResults[N]; - Inc(N); - try - Quotient := 0; - Remainder := 0; - BigInteger.DivMod(Dividend, Divisor, Quotient, Remainder); - except - on E: EZeroDivide do - begin - Check(TRDiv.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); - Continue; - end; - on E: Exception do - Error('Unexpected ' + E.ClassName + ' exception: ''' + E.Message + ''''); - end; - Check(TRDiv.info = triOK, Format('%d,%d: Expected an exception for %s div %s', [I, J, Dividend.ToString, Divisor.ToString])); - CheckQ := TRDiv.val; - CheckR := TRMod.val; - Check(Quotient = CheckQ, Format('(%d,%d) %s div %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Quotient.ToString(16), CheckQ.ToString(16)])); - Check(Remainder = CheckR, Format('(%d,%d) %s mod %s = "%s" ("%s")', [I, J, Dividend.ToString(16), Divisor.ToString(16), Remainder.ToString(16), CheckR.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestDivModKnuth; -var - I, J, N: Integer; - TRDiv, TRMod: TTestResult; - Dividend, Divisor, Quotient, Remainder, CheckQ, CheckR: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[J]; - TRDiv := DivisionResults[N]; - TRMod := ModulusResults[N]; - Inc(N); - try - Quotient := 0; - Remainder := 0; - BigInteger.DivModKnuth(Dividend, Divisor, Quotient, Remainder); - except - on E: EZeroDivide do - begin - Check(TRDiv.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); - Continue; - end; - on E: Exception do - Error('Unexpected ' + E.ClassName + ' exception: ''' + E.Message + ''''); - end; - Check(TRDiv.info = triOK, Format('%d,%d: Expected an exception for %s div %s', [I, J, Dividend.ToString, Divisor.ToString])); - CheckQ := TRDiv.val; - CheckR := TRMod.val; - Check(Quotient = CheckQ, Format('(%d,%d) %s div %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Quotient.ToString(16), CheckQ.ToString(16)])); - Check(Remainder = CheckR, Format('(%d,%d) %s mod %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Remainder.ToString(16), CheckR.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestDivMod16; -var - I, J: Integer; - U16: UInt16; - Dividend, Divisor, U16Equiv, U16OpResult, BigIntOpResult: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[I]; - U16 := UInt16(Divisor); - U16Equiv := U16; - if U16 = 0 then - Continue; - U16OpResult := BigInteger.Divide(Dividend, U16); - BigIntOpResult := BigInteger.Divide(Dividend, U16Equiv); - Check(BigIntOpResult = U16OpResult, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16OpResult.ToString(16), BigIntOpResult.ToString(16)])); - U16OpResult := BigInteger.Remainder(Dividend, U16); - BigIntOpResult := BigInteger.Remainder(Dividend, U16Equiv); - Check(BigIntOpResult = U16OpResult, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16OpResult.ToString(16), BigIntOpResult.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestDivMod32; -var - I, J: Integer; - U32: UInt32; - Dividend, Divisor, U32Equiv, U32OpResult, BigIntOpResult: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - Dividend := Arguments[I]; - for J := 0 to High(Arguments) do - begin - Divisor := Arguments[I]; - U32 := UInt32(Divisor); - U32Equiv := U32; - if U32 = 0 then - Continue; - U32OpResult := BigInteger.Divide(Dividend, U32); - BigIntOpResult := BigInteger.Divide(Dividend, U32Equiv); - Check(BigIntOpResult = U32OpResult, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32OpResult.ToString(16), BigIntOpResult.ToString(16)])); - U32OpResult := BigInteger.Remainder(Dividend, U32); - BigIntOpResult := BigInteger.Remainder(Dividend, U32Equiv); - Check(BigIntOpResult = U32OpResult, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32OpResult.ToString(16), BigIntOpResult.ToString(16)])); - end; - end; -end; - -procedure TTestBigInteger.TestDivModBurnikelZiegler; -var - I: Integer; - R: IRandom; - Threshold: Integer; - DendSize, DorSize: Integer; - Dividend, Divisor, KnuthQ, KnuthR, BZQ, BZR: BigInteger; -begin - R := TDelphiRandom.Create($1234567); - for I := 1 to 20 do - begin - Threshold := 160; - DendSize := Threshold * 145; - Dividend := BigInteger.Create(DendSize, R); - DorSize := Threshold * 65; - Divisor := BigInteger.Create(DorSize, R); - BigInteger.DivModKnuth(Dividend, Divisor, KnuthQ, KnuthR); - BigInteger.DivModBurnikelZiegler(Dividend, Divisor, BZQ, BZR); - Check(KnuthQ = BZQ, Format('%d: %s div %s = %s (%s)', [I, Dividend.ToString(16), Divisor.ToString(16), BZQ.ToString(16), KnuthQ.ToString(16)])); // Check quotients - Check(KnuthR = BZR, Format('%d: %s mod %s = %s (%s)', [I, Dividend.ToString(16), Divisor.ToString(16), BZR.ToString(16), KnuthR.ToString(16)])); // Check remainders - end; -end; - -//procedure TestTBigInteger.TestAbs; -//begin -//end; -// -procedure TTestBigInteger.TestBitLength; -var - I: Integer; - Value: BigInteger; -begin - Value := 1; - for I := 1 to 1000 do - begin - Check(Value.BitLength = I); - Value := Value + Value; - end; - Value := 1; - for I := 1 to 1000 do - begin - Check(Value.BitLength = I); - Value := Value + Value + BigInteger.One; - end; -end; - -procedure TTestBigInteger.TestGreatestCommonDivisor; -var - I, J, N: Integer; - A, B, GCD, CheckGCD: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - for J := 0 to High(Arguments) do - begin - B := Arguments[J]; - GCD := BigInteger.GreatestCommonDivisor(A, B); - CheckGCD := GCDResults[N].val; - - Check(GCD = CheckGCD); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestLn; -var - I: Integer; - D1, D2: Double; - A: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - D1 := BigInteger.Ln(A); - D2 := LnResults[I]; - if IsInfinite(D1) then - Check(IsInfinite(D2)) - else if IsNan(D1) then - Check(IsNan(D2)) - else - Check(SameValue(D1, D2), Format('%d: Ln(%s) = %0.15f (%0.15f)', [I, A.ToString, D1, D2])); - end; - A := BigInteger.Pow(1000, 1000); - D1 := BigInteger.Ln(A); - Check(SameValue(D1, Ln_1000_1000, 1e-10), Format('Ln(Pow(1000, 1000)): %.15f (%.15f)', [D1, 0.0 + Ln_1000_1000])); - D1 := BigInteger.Log10(A); - Check(SameValue(D1, Log10_1000_1000, 1e-10), Format('Log10(Pow(1000, 1000)): %.15f (%.15f)', [D1, 0.0 + Log10_1000_1000])); - D1 := BigInteger.Log2(A); - Check(SameValue(D1, Log2_1000_1000, 1e-10), Format('Log2(Pow(1000, 1000)): %.15f (%.15f)', [D1, 0.0 + Log2_1000_1000])); -end; - -procedure TTestBigInteger.TestMax; -var - I, J, N: Integer; - A, B, Maximum, CheckMax: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - for J := 0 to High(Arguments) do - begin - B := Arguments[J]; - Maximum := BigInteger.Max(A, B); - CheckMax := MaxResults[N].val; - Inc(N); - Check(Maximum = CheckMax); - end; - end; -end; - -procedure TTestBigInteger.TestMin; -var - I, J, N: Integer; - A, B, Mimimum, CheckMin: BigInteger; -begin - N := 0; - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - - for J := 0 to High(Arguments) do - begin - B := Arguments[J]; - - Mimimum := BigInteger.Min(A, B); - CheckMin := MinResults[N].val; - Inc(N); - Check(Mimimum = CheckMin); - end; - end; -end; - -// How to test this properly? ModPow() has 3 parameters, so which ones to choose? -// Note that PowerResults already has 1600 entries. Choosing bit shifts for the -// 3rd parameter would produce 1600 * 40 = 64000 entries. -// So what to do? Taking only every third argument would reduce this to 2197 entries. - -procedure TTestBigInteger.TestModPow; -var - Base, Exponent, Modulus, ModPower: BigInteger; - I, J, K, N: Integer; - TR: TTestResult; - HadException: Boolean; -begin - N := 0; - I := 2; - while I < High(Arguments) do - begin - Base := BigInteger(Arguments[I]); - Base := BigInteger.Abs(Base); - J := 0; - while J < High(Arguments) do - begin - Exponent := BigInteger(Arguments[J]); - Exponent := BigInteger.Abs(Exponent); - K := 1; - while K < High(Arguments) do - begin - Modulus := BigInteger(Arguments[K]); - Modulus := BigInteger.Abs(Modulus); - - TR := ModPowResults[N]; - - HadException := False; - try - ModPower := BigInteger.ModPow(Base, Exponent, Modulus); - except - on E: Exception do - begin - Check(TR.Info <> triOk, Format('%d: Unexpect exception on ModPow(%s, %s, %s): %s -- %s', [N, string(Base), string(Exponent), string(Modulus), E.ClassName, E.Message])); - HadException := True; - end; - end; - - if not HadException then - begin - Check(TR.Info = triOk, Format('%d: ModPos(%s, %s, %s) has Java error: %s', [N, string(Base), string(Exponent), string(Modulus), TR.Val])); - Check(BigInteger(TR.Val) = ModPower, Format('(%d,%d,%d,%d): ModPow(%s, %s, %s) = %s (%s)', [I, J, K, N, string(Base), string(Exponent), string(Modulus), string(ModPower), TR.Val])); - end; - Inc(N); - Inc(K, 5); - end; - Inc(J, 5); - end; - Inc(I, 5); - end; -end; - -procedure TTestBigInteger.TestParse; -var - I: Integer; - ParseString, StringResult: string; - Value: BigInteger; -begin - for I := High(MultiplyResults) downto 0 do - begin - ParseString := MultiplyResults[I].val; - try - Value := ParseString; - except - on E: Exception do - begin - Error(Format('%s, MultiplyResults[%d]: %s'#13#10'val = %s', [E.ClassName, I, E.Message, MultiplyResults[I].val])); - end; - end; - try - StringResult := Value.ToString(10); - except - on E: Exception do - begin - Error(Format('(%d) Error %s with message: %s', [I, E.ClassName, E.Message])); - raise; - end; - end; - Check(ParseString = StringResult, Format('MultiplyResults[%d]: ''%s'' --> %s (%s), classic: %s', [I, ParseString, StringResult, ParseString, Value.ToStringClassic(10)])); - end; -end; - -procedure TTestBigInteger.TestPow; -var - I, J, N, Exponent: Integer; - Base, Power, CheckPower: BigInteger; -begin - N := 0; - for I := 0 to High(BitShifts) do - begin - Base := BitShifts[I]; - for J := 0 to High(BitShifts) do - begin - Exponent := BitShifts[J]; - Power := BigInteger.Pow(Base, Exponent); - CheckPower := PowerResults[N].val; - Check(Power = CheckPower, Format('(%d,%d) Pow(%s, %d) = %s (%s)', [I, J, Base.ToString, Exponent, Power.ToString, CheckPower.ToString])); - Inc(N); - end; - end; -end; - -procedure TTestBigInteger.TestPred; -var - Value, Predecessor, ValueMinusOne: BigInteger; - I: Integer; -begin - for I := 0 to High(Arguments) do - begin - Value := Arguments[I]; - Predecessor := Value.Pred; - ValueMinusOne := Value - BigInteger.One; - Check(Predecessor = ValueMinusOne, Format('(%d) Pred(%s) = %s (%s)', [I, string(Value), string(Predecessor), string(ValueMinusOne)])); - end; -end; - -procedure TTestBigInteger.TestToByteArray; -var - I, J: Integer; - S1, S2: string; - Bytes: TArray; - A: BigInteger; -begin - for I := 0 to High(Arguments) do - begin - A := Arguments[I]; - Bytes := A.ToByteArray; - S1 := ''; - for J := 0 to High(Bytes) do - S1 := S1 + Format('%.2X', [Bytes[J]]); - S2 := ByteArrayResults[I].val; - Check(S1 = S2, Format('%d: %s --> %s (%s)', [I, A.ToString(16), S1, S2])); - end; -end; - -initialization - // Register any test cases with the test runner - RegisterTest(TTestBigInteger.Suite); -end. - - - +unit TestBigIntegers; + +//////////////////////////////////////////////////////////////////////////////////////// +// // +// Delphi DUnit Test Case // +// ---------------------- // +// This unit contains a skeleton test case class generated by the Test Case Wizard. // +// Modify the generated code to correctly setup and call the methods from the unit // +// being tested. // +// // +//////////////////////////////////////////////////////////////////////////////////////// + +interface + +uses + TestFramework, + System.Types, + System.Generics.Defaults, + System.SysUtils, + System.Math, + Velthuis.BigIntegers, + Velthuis.RandomNumbers; + +{$IF BigInteger.Immutable} +{$DEFINE IMMUTABLE} +{$IFEND} + +{$IF RTLVersion >= 29.0} +{$DEFINE HASINVARIANT} +{$IFEND} + +{ $DEFINE TESTPARTIALFLAGCODE} + +type + // Test methods for BigInteger records. + TTestBigInteger = class(TTestCase) +// strict private +// A, B, C, D, E, F: BigInteger; + public + procedure Error(const Msg: string); + procedure SetUp; override; + procedure TearDown; override; + published + procedure TestParse; + procedure TestTryParse; + procedure TestCreateBytes; + procedure TestCreateRandom; + procedure TestCreateDouble; + procedure TestIsZero; + procedure TestIsPositive; + procedure TestIsEven; + procedure TestIsPowerOfTwo; + procedure TestIsOne; + procedure TestToString; + procedure TestToHex; + procedure TestTestBit; + procedure TestSetBit; + procedure TestClearBit; + procedure TestFlipBit; + procedure TestAdd; +{$IFNDEF IMMUTABLE} + procedure TestAddFunction; + procedure TestInc; + procedure TestDec; +{$ENDIF} + procedure TestSubtract; + procedure TestMultiply; + procedure TestMultiplyKaratsuba; + procedure TestMultiplyToomCook3; + procedure TestIntDivide; + procedure TestIntDivide16; + procedure TestIntDivide32; + procedure TestModulus; + procedure TestModulus16; + procedure TestModulus32; + procedure TestSquare; + procedure TestNegative; + procedure TestBitwiseAnd; + procedure TestBitwiseOr; + procedure TestBitwiseXor; + procedure TestLogicalNot; + procedure TestLeftShift; + procedure TestRightShift; + procedure TestEqual; + procedure TestNotEqual; + procedure TestGreaterThan; + procedure TestGreaterThanOrEqual; + procedure TestLessThan; + procedure TestLessThanOrEqual; + procedure TestAsDouble; + procedure TestAsInteger; + procedure TestAsCardinal; + procedure TestAsInt64; + procedure TestAsUInt64; + procedure TestDivMod; + procedure TestDivModKnuth; + procedure TestDivModBurnikelZiegler; + procedure TestDivMod16; + procedure TestDivMod32; +// procedure TestAbs; + procedure TestBitLength; + procedure TestGreatestCommonDivisor; + procedure TestLn; + procedure TestMax; + procedure TestMin; + procedure TestModPow; + procedure TestPow; + procedure TestNthRoot; + procedure TestSqrt; + procedure TestToByteArray; + procedure TestModInverse; + procedure TestFactorial; + procedure TestPred; + procedure TestSucc; + end; + +implementation + +{$IFDEF MSWINDOWS} +uses + Winapi.Windows; +{$ENDIF} + +{$I 'BigIntegerTestResults.inc'} +{$I 'BigIntegerArithmeticResults.inc'} +{$I 'BigIntegerBitwiseResults.inc'} +{$I 'BigIntegerConvertResults.inc'} +{$I 'BigIntegerMathResults.inc'} + +procedure TTestBigInteger.Error(const Msg: string); +begin +{$IFDEF MSWINDOWS} + OutputDebugString(PChar(Msg)); +{$ELSE} + {$IFDEF CONSOLE} + Writeln(ErrOutput, Msg); + {$ENDIF} +{$ENDIF} +end; + +procedure TTestBigInteger.SetUp; +begin +{$IF HASINVARIANT} + Status(Format('Compiler version: %0.1f', [System.CompilerVersion], TFormatSettings.Invariant)); +{$ELSE} + Status(Format('Compiler version: %0.1f', [System.CompilerVersion])); +{$ENDIF} +{$IFDEF WIN64} + Status('Win64'); +{$ENDIF} +{$IFDEF WIN32} + Status('Win32'); +{$ENDIF} + if Velthuis.BigIntegers.PurePascal then + Status('PUREPASCAL') + else + begin + if BigInteger.StallAvoided then + Status('Asssembler: partial flag stall code used') + else + Status('Assembler: plain code'); + end; +{$IFDEF TESTPARTIALFLAGCODE} + BigInteger.AvoidPartialFlagsStall(True); +{$ENDIF} +end; + +procedure TTestBigInteger.TearDown; +begin +end; + +procedure TTestBigInteger.TestIsZero; +var + MinusOne, One, Zero: BigInteger; +begin + MinusOne := '-1'; + One := '1'; + Zero := '0'; + + Check(not MinusOne.IsZero); + Check(not One.IsZero); + Check(Zero.IsZero); +end; + +procedure TTestBigInteger.TestIsPositive; +var + MinusOne, One, Zero: BigInteger; +begin + MinusOne := '-1'; + One := '1'; + Zero := '0'; + + Check(not MinusOne.IsPositive); + Check(One.IsPositive); + Check(not Zero.IsPositive); +end; + +procedure TTestBigInteger.TestIsEven; +var + A, B, C, D, E: BigInteger; +begin + A := -1234; + B := -1233; + C := 0; + D := 1233; + E := 1234; + + CheckTrue(A.IsEven); + CheckFalse(B.IsEven); + CheckTrue(C.IsEven); + CheckFalse(D.IsEven); + CheckTrue(E.IsEven); +end; + +procedure TTestBigInteger.TestIsPowerOfTwo; +var + I: Integer; + Value, MinusValue, ValueMinusOne, ValuePlusOne, MinusValueMinusOne, MinusValuePlusOne: BigInteger; + + function Msg(const S: string; const Int: BigInteger): string; + begin + Result := Format('(%d) Value = %s (hex), A = %s (hex), Info: %s', [I, Int.ToString(16), Value.ToString(16), S]); + end; + +begin + Value := 4; + for I := 4 to 100 do + begin + Value := Value shl 1; + MinusValue := -Value; + ValueMinusOne := Value - BigInteger.One; + ValuePlusOne := Value + BigInteger.One; + MinusValueMinusOne := MinusValue - BigInteger.One; + MinusValuePlusOne := MinusValue + BigInteger.One; + + CheckTrue(Value.IsPowerOfTwo, Msg('A', Value)); + CheckTrue(MinusValue.IsPowerOfTwo, Msg('-A', MinusValue)); + CheckFalse(ValueMinusOne.IsPowerOfTwo, Msg('A - 1', ValueMinusOne)); + CheckFalse(ValuePlusOne.IsPowerOfTwo, Msg('A + 1', ValuePlusOne)); + CheckFalse(MinusValueMinusOne.IsPowerOfTwo, Msg('-A - 1', MinusValueMinusOne)); + CheckFalse(MinusValuePlusOne.IsPowerOfTwo, Msg('-A + 1', MinusValuePlusOne)); + end; +end; + +procedure TTestBigInteger.TestIsOne; +var + MinusOne, One, Zero: BigInteger; +begin + MinusOne := BigInteger.MinusOne; + One := BigInteger.One; + Zero := '0'; + + CheckFalse(MinusOne.IsOne); + CheckTrue(One.IsOne); + CheckFalse(Zero.IsOne); +end; + +procedure TTestBigInteger.TestToString; +var + I: Integer; + ValueStr, CheckStr: string; + Value: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + BigInteger.Decimal; + Value := Arguments[I]; + ValueStr := Value.ToString; + CheckStr := Arguments[I]; + Check(ValueStr = CheckStr); + BigInteger.Hexadecimal; + ValueStr := Value.ToString; + CheckStr := HexResults[I].val; + Check(ValueStr = CheckStr); + BigInteger.Decimal; + end; +end; + +procedure TTestBigInteger.TestTryParse; +var + I: Integer; + Res: TTryParseResult; + Value: BigInteger; +begin + for I := Low(TryParseResults) to High(TryParseResults) do + begin + Res := TryParseResults[I]; + Check(BigInteger.TryParse(Res.Str, Res.Base, Value) = Res.Result); + if Res.Result then + Check(Value.ToString(10) = Res.Str10); + end; +end; + +procedure TTestBigInteger.TestToHex; +var + I: Integer; + S1, S2: string; + Value: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + S1 := Value.ToHexString; + S2 := HexResults[i].val; + Check(S1 = S2); + end; +end; + +procedure TTestBigInteger.TestAdd; +var + I, J, N: Integer; + Left, Right, Sum, CheckSum: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + try + Sum := Left + Right; + except + on E: Exception do + Error(E.ClassName + ': ' + E.Message); + end; + CheckSum := AddResults[N].val; + Check(Sum = CheckSum, Format('(%d,%d) %s + %s = %s (%s, diff=%s)', [I, J, Left.ToString(16), Right.ToString(16), Sum.ToString(16), CheckSum.ToString(16), (Sum - CheckSum).ToString(16)])); + Inc(N); + end; + end; +end; + +{$IF not BigInteger.Immutable} +procedure TTestBigInteger.TestAddFunction; +var + I, J, N: Integer; + A, B, C, D: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + for J := 0 to High(Arguments) do + begin + B := Arguments[J]; + try + C := A; + C.Add(B); + except + on E: Exception do + Error(E.ClassName + ': ' + E.Message); + end; + D := AddResults[N].val; + Check(C = D, Format('(%d,%d) %s + %s = %s (%s)', [I, J, A.ToString(16), B.ToString(16), C.ToString(16), D.ToString(16)])); + Inc(N); + end; + end; +end; +{$ENDIF} + +procedure TTestBigInteger.TestSetBit; +var + I, J, N, Bit: Integer; + Value, BitSet: BigInteger; + TR: TTestResult; +begin + N := Length(bits); + for I := 1 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to High(Bits) do + begin + Bit := Bits[J]; + TR := SetBitResults[N]; + Inc(N); + BitSet := Value.SetBit(Bit); + Check(BitSet = BigInteger(TR.Val), Format('(%d,%d): $%s.SetBit(%d) = $%s ($%s)', [I, J, Value.ToString(16), Bit, BitSet.ToString(16), BigInteger(TR.val).ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestClearBit; +var + I, J, N, Bit: Integer; + Value, Cleared: BigInteger; + TR: TTestResult; +begin + N := Length(bits); + for I := 1 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to High(Bits) do + begin + Bit := Bits[J]; + TR := ClearBitResults[N]; + Inc(N); + Cleared := Value.ClearBit(Bit); + Check(Cleared = BigInteger(TR.Val), Format('(%d,%d): $%s.ClearBit(%d) = $%s ($%s)', [I, J, Value.ToString(16), Bit, Cleared.ToString(16), BigInteger(TR.val).ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestFactorial; +var + I, N: Integer; + Value, CheckValue: BigInteger; +begin + for I := 0 to High(BitShifts) do + begin + N := BitShifts[I]; + Value := BigInteger.Factorial(N); + CheckValue := FactorialResults[I].Val; + Check(Value = CheckValue); + end; +end; + +procedure TTestBigInteger.TestFlipBit; +var + I, J, N, Bit: Integer; + Value, Flipped: BigInteger; + TR: TTestResult; +begin + N := Length(bits); + for I := 1 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to High(Bits) do + begin + Bit := Bits[J]; + TR := FlipBitResults[N]; + Inc(N); + Flipped := Value.FlipBit(Bit); + Check(Flipped = BigInteger(TR.Val), Format('(%d,%d): $%s.FlipBit(%d) = $%s ($%s)', [I, J, Value.ToString(16), Bit, Flipped.ToString(16), BigInteger(TR.val).ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestSqrt; +var + I, Exp: Integer; + Base, Arg, Root, RootSquared, RootPlusOneSquared: BigInteger; +begin + for I := 10 to High(BitShifts) do + begin + Base := BitShifts[I]; + for Exp := 2 to 100 do + begin + Arg := BigInteger.Pow(Base, Exp) + BigInteger.Pow(Base, Exp - 1); + Root := BigInteger.Sqrt(Arg); + RootSquared := Root * Root; + RootPlusOneSquared := (Root + 1) * (Root + 1); + Check((RootSquared <= Arg) and (Arg < RootPlusOneSquared), Format('(%d,%d) Sqrt(%s) = %s (%s not in [%s..%s])', [I, Exp, Arg.ToString(16), Root.ToString(16), Arg.ToString(16), RootSquared.ToString(16), RootPlusOneSquared.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestSquare; +var + I: Integer; + Value, Square, CheckSquare: BigInteger; +begin + for I := 0 to High(MultiplyResults) do + begin + Value := MultiplyResults[I].val; + Square := BigInteger.Sqr(Value); + CheckSquare := Value * Value; + Check(Square = CheckSquare, Format('(%d) Sqr(%s) = %s (%s)', [I, Value.ToString(16), Square.ToString(16), CheckSquare.ToString(16)])); + end; +end; + +procedure TTestBigInteger.TestSubtract; +var + I, J, N: Integer; + Minuend, Subtrahend, Difference, CheckDifference: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Minuend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Subtrahend := Arguments[J]; + try + Difference := Minuend - Subtrahend; + except + on E: Exception do + Error(E.ClassName + ': ' + E.Message); + end; + CheckDifference := SubtractResults[N].val; + Check(Difference = CheckDifference, Format('(%d,%d) %s - %s = %s (%s)', [I, J, Minuend.ToString, Subtrahend.ToString, Difference.ToString, CheckDifference.ToString])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestSucc; +var + Value, Successor, ValuePlusOne: BigInteger; + I: Integer; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + Successor := Value.Succ; + ValuePlusOne := Value + BigInteger.One; + Check(Successor = ValuePlusOne, Format('(%d) Pred(%s) = %s (%s)', [I, string(Value), string(Successor), string(ValuePlusOne)])); + end; +end; + +procedure TTestBigInteger.TestMultiply; +var + I, J, N: Integer; + S, ErrorMsg: string; + Left, Right, Product, CheckProduct: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + S := MultiplyResults[N].val; + CheckProduct := S; + try + Product := BigInteger.Multiply(Left, Right); + except + on E: Exception do + Error('Multiplication error, ' + E.ClassName + ': ' + E.Message); + end; + ErrorMsg := Format('(%d,%d,%d) %s * %s = %s (%s, diff = %s)', [I, J, N, Left.ToString(16), Right.ToString(16), Product.ToString(16), CheckProduct.ToString(16), (CheckProduct - Product).ToString(16)]); + Check(Product = CheckProduct, ErrorMsg); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestMultiplyKaratsuba; +var + I: Integer; + R: IRandom; + BaseFactor, Factor, Product, BaseCaseProduct: BigInteger; +begin + R := TDelphiRandom.Create($123456); + BaseFactor := BigInteger.Create((BigInteger.KaratsubaThreshold + Random(100)) * 32, R); + for I := 1 to 20 do + begin + Factor := BigInteger.Create((BigInteger.KaratsubaThreshold + Random(100)) * 32, R); + BigInteger.MultiplyKaratsuba(BaseFactor, Factor, Product); + + // It is safe to assume that result given by MultiplyBaseCase is correct. + BigInteger.MultiplyBaseCase(BaseFactor, Factor, BaseCaseProduct); + + Check(Product = BaseCaseProduct, Format('(%d x %d): %s * %s = %s (%s), diff = %s', [BaseFactor.Size, Factor.Size, BaseFactor.ToString(16), Factor.ToString(16), Product.ToString(16), BaseCaseProduct.ToString(16), (Product - BaseCaseProduct).ToString(16)])); + BaseFactor := Factor; + end; +end; + +procedure TTestBigInteger.TestMultiplyToomCook3; +var + I: Integer; + R: IRandom; + BaseFactor, Factor, Product, BaseCaseProduct: BigInteger; +begin + R := TDelphiRandom.Create($123456); + BaseFactor := BigInteger.Create((BigInteger.ToomCook3Threshold + Random(100)) * 32, R); + for I := 1 to 20 do + begin + Factor := BigInteger.Create((BigInteger.ToomCook3Threshold + Random(100)) * 32, R); + Product := BigInteger.MultiplyToomCook3(BaseFactor, Factor); + + // It is safe to assume that result given by MultiplyBaseCase is correct. + BigInteger.MultiplyBaseCase(BaseFactor, Factor, BaseCaseProduct); + + Check(Product = BaseCaseProduct, Format('(%d x %d): %s * %s = %s (%s), diff = %s', [BaseFactor.Size, Factor.Size, BaseFactor.ToString(16), Factor.ToString(16), Product.ToString(16), BaseCaseProduct.ToString(16), (Product - BaseCaseProduct).ToString(16)])); + BaseFactor := Factor; + end; +end; + +{$IFNDEF IMMUTABLE} +procedure TTestBigInteger.TestInc; +var + I: Integer; + Value, SuccValue, IncValue: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + SuccValue := Value + 1; + IncValue := Value; + Inc(IncValue); + Check(IncValue = SuccValue, Format('(%d) %s --> %s (%s)', [I, Value.ToString(16), IncValue.ToString(16), SuccValue.ToString(16)])); + end; +end; +{$ENDIF} + +procedure TTestBigInteger.TestIntDivide; +var + I, J, N: Integer; + TR: TTestResult; + Dividend, Divisor, Quotient, CheckQuotient: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[J]; + TR := DivisionResults[N]; + Inc(N); + try + Quotient := Dividend div Divisor; + except + on E: EZeroDivide do + begin + Check(TR.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); + Continue; + end; + on E: Exception do + Error('TestIntDivide: Unexpected ' + E.ClassName + ' exception: ''' + E.Message + ''''); + end; + Check(TR.info = triOk, Format('(%d,%d) Expected an exception', [I, J])); + CheckQuotient := TR.val; + Check(Quotient = CheckQuotient, Format('(%d,%d) %s div %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Quotient.ToString(16), CheckQuotient.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestIntDivide16; +var + I, J: Integer; + U16: UInt16; + Dividend, Divisor, U16Equiv, U16Quotent, U16EquivQuotient: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[I]; + U16 := UInt16(Divisor); + U16Equiv := U16; + if U16 = 0 then + Continue; + U16Quotent := Dividend div U16; + U16EquivQuotient := Dividend div U16Equiv; + Check(U16EquivQuotient = U16Quotent, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16Quotent.ToString(16), U16EquivQuotient.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestIntDivide32; +var + I, J: Integer; + U32: UInt16; + Dividend, Divisor, U32Equiv, U32Quotient, U32EquivQuotient: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[I]; + U32 := UInt32(Divisor); + U32Equiv := U32; + if U32 = 0 then + Continue; + U32Quotient := Dividend div U32; + U32EquivQuotient := Dividend div U32Equiv; + Check(U32EquivQuotient = U32Quotient, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32Quotient.ToString(16), U32EquivQuotient.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestModInverse; +var + I, J, N: Integer; + TR: TTestResult; + Value, Modulus, Inverse: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Modulus := Arguments[J]; + TR := InvModResults[N]; + Inc(N); + // Only test if B <> 0 and A, B are coprime. + if Modulus.IsZero or (BigInteger.GreatestCommonDivisor(Value, Modulus) <> BigInteger.One) then + Continue; + try + Inverse := BigInteger.Zero; + Inverse := BigInteger.ModInverse(Value, Modulus); + except + on E: Exception do + begin + Check(TR.Info <> triOk, Format('(%d,%d,%d): Unexpected exception %s: %s', [I, J, N - 1, E.ClassName, E.Message])); + Continue; + end; + end; + Check(TR.Info = triOk, Format('(%d,%d,%d): Unexpected error ''%s''', [I, J, N - 1, TR.Val])); + Check(Inverse = BigInteger(TR.Val), Format('(%d,%d): ModInverse: %s * %s mod %s = %s', [I, J, Value.ToString, Inverse.ToString, Modulus.ToString, (Value * Inverse mod Modulus).ToString])); + end; + end; +end; + +procedure TTestBigInteger.TestModulus; +var + I, J, N: Integer; + TR: TTestResult; + Dividend, Divisor, Modulus, CheckModulus: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[J]; + TR := ModulusResults[N]; + Inc(N); + try + Modulus := Dividend mod Divisor; + except + on E: EZeroDivide do + begin + Check(TR.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); + Continue; + end; + on E: Exception do + Error('TestModulus: Unexpected ' + E.ClassName + ' exception: ' + E.Message); + end; + Check(TR.info = triOk, Format('(%d,%d) Expected exception did not occur', [I, J])); + CheckModulus := TR.Val; + Check(Modulus = CheckModulus, Format('(%d,%d) %s mod %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Modulus.ToString(16), CheckModulus.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestModulus16; +var + I, J: Integer; + U16: UInt16; + Dividend, Divisor, U16Equiv, U16Quot, U16EquivQuot: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[I]; + U16 := UInt16(Divisor); + U16Equiv := U16; + if U16 = 0 then + Continue; + U16Quot := Dividend mod U16; + U16EquivQuot := Dividend mod U16Equiv; + Check(U16EquivQuot = U16Quot, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16Quot.ToString(16), U16EquivQuot.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestModulus32; +var + I, J: Integer; + U32: UInt32; + Dividend, Divisor, U32Equiv, U32Mod, U32EquivMod: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[I]; + U32 := UInt32(Divisor); + U32Equiv := U32; + if U32 = 0 then + Continue; + U32Mod := Dividend mod U32; + U32EquivMod := Dividend mod U32Equiv; + Check(U32EquivMod = U32Mod, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32Mod.ToString(16), U32EquivMod.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestNegative; +var + I: Integer; + Value, Negated, CheckNegated: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + Negated := -Value; + CheckNegated := NegationResults[I].val; + Check(Negated = CheckNegated); + end; +end; + +procedure TTestBigInteger.TestBitwiseAnd; +var + I, J, N: Integer; + Left, Right, Anded, CheckAnded: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + try + Anded := Left and Right; + except + on E: Exception do + Error(E.ClassName + ': ' + E.Message); + end; + CheckAnded := BitwiseAndResults[N].val; + Check(Anded = CheckAnded, Format('(%d,%d) %s and %s = %s (%s)', [I, J, Left.ToString(16), Right.ToString(16), Anded.ToString(16), CheckAnded.ToString(16)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestBitwiseOr; +var + I, J, N: Integer; + Left, Right, Ored, CheckOred: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + try + Ored := Left or Right; + except + on E: Exception do + Error(E.ClassName + ': ' + E.Message); + end; + CheckOred := BitwiseOrResults[N].val; + Check(Ored = CheckOred, Format('(%d,%d) %s or %s = %s (%s)', [I, J, Left.ToString(16), Right.ToString(16), Ored.ToString(16), CheckOred.ToString(16)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestBitwiseXor; +var + I, J, N: Integer; + Left, Right, Xored, CheckXored: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + try + Xored := Left xor Right; + except + on E: Exception do + Error(E.ClassName + ': ' + E.Message); + end; + CheckXored := BitwiseXorResults[N].val; + Check(Xored = CheckXored, Format('(%d,%d) %s xor %s = %s (%s)', [I, J, Left.ToString(16), Right.ToString(16), Xored.ToString(16), CheckXored.ToString(16)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestCreateBytes; +var + I: Integer; + Bytes: TArray; + Value, FromBytes: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + Bytes := Value.ToByteArray; + FromBytes := BigInteger.Create(Bytes); + Check(Value = FromBytes, Format('(%d), Create(%s.ToByteArray) = %s', [I, Value.ToString(16), FromBytes.ToString(16)])); + end; +end; + +procedure TTestBigInteger.TestCreateDouble; +var + I: Integer; + Value, CheckValue: BigInteger; +begin + BigInteger.RoundingMode := BigInteger.TRoundingMode.rmTruncate; + for I := 0 to High(Doubles) do + begin + Value := BigInteger.Create(Doubles[I]); + CheckValue := CreateDoubleResults[I].val; + Check(Value = CheckValue, Format('(%d) BigInteger.Create(%f) = %s (%s)', [I, Doubles[I], Value.ToString(16), CheckValue.ToString(16)])); + end; +end; + +procedure TTestBigInteger.TestCreateRandom; +var + I, NumBits: Integer; + ARandom: IRandom; + Value: BigInteger; +begin + ARandom := TDelphiRandom.Create; + for I := 0 to 1000 do + begin + NumBits := I; + Value := BigInteger.Create(NumBits, ARandom); + Check(Value.BitLength <= NumBits, Format('%s (bits = %d), Numbits = %d', [Value.ToString(16), Value.BitLength, NumBits])); + end; +end; + +procedure TTestBigInteger.TestLogicalNot; +var + I: Integer; + Value, NotValue, CheckNotValue: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + NotValue := not Value; + CheckNotValue := LogicalNotResults[I].val; + Check(NotValue = CheckNotValue, Format('(%d) not %s = %s (%s)', [I, Value.ToString(16), NotValue.ToString(16), CheckNotValue.ToString(16)])); + end; +end; + +procedure TTestBigInteger.TestLeftShift; +var + I, J, N, Shift: Integer; + Value, Shifted, CheckShifted: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to High(BitShifts) do + begin + Shift := BitShifts[J]; + Shifted := Value shl Shift; + CheckShifted := LeftShiftResults[N].val; + Check(Shifted = CheckShifted, Format('(%d,%d) %s shl %d = %s (%s)', [I, J, Value.ToString(16), Shift, Shifted.ToString(16), CheckShifted.ToString(16)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestRightShift; +var + I, J, N, Shift: Integer; + Value, Shifted, CheckShifted: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to High(BitShifts) do + begin + Shift := BitShifts[J]; + Shifted := Value shr Shift; + CheckShifted := RightShiftResults[N].val; + Check(Shifted = CheckShifted, Format('(%d,%d) %s shr %d = %s (%s)', [I, J, Value.ToString(16), Shift, Shifted.ToString(16), CheckShifted.ToString(16)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestEqual; +var + I, J, N: Integer; + Comp, CheckComp: Boolean; + Left, Right: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + Comp := Left = Right; + CheckComp := ComparisonResults[N, crEqual]; + Check(Comp = CheckComp, Format('%d,%d: %s = %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestNotEqual; +var + I, J, N: Integer; + Comp, CheckComp: Boolean; + Left, Right: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + Comp := Left <> Right; + CheckComp := ComparisonResults[N, crNotEqual]; + Check(Comp = CheckComp, Format('%d,%d: %s <> %s: %s (%s)', [I, j, Arguments[I], Arguments[j], BoolToStr(Comp), BoolToStr(CheckComp)])); + Inc(N); + end; + end; +end; + +// Seems to have become slower since the code change. Is the old method (binary search) better for the relatively small values tested here? +procedure TTestBigInteger.TestNthRoot; +var + I, Exponent: Integer; + Value, TestValue, Root, PowerOfRoot, PowerOfRootPlusOne: BigInteger; +begin + for I := 0 to High(BitShifts) do + begin + Value := BitShifts[I]; + Exponent := 2; + while Exponent <= 100 do + begin + TestValue := BigInteger.Pow(Value, Exponent) + BigInteger.Pow(Value, Exponent - 1); + Root := BigInteger.NthRoot(TestValue, Exponent); + PowerOfRoot := BigInteger.Pow(Root, Exponent); + PowerOfRootPlusOne := BigInteger.Pow(Root.Succ, Exponent); + if not ((PowerOfRoot <= TestValue) and (TestValue < PowerOfRootPlusOne)) then + Writeln(Format('(%d,%d) NthRoot(%s, %d) = %s (%s)', [I, Exponent, TestValue.ToString(16), Exponent, Root.ToString(16), Value.ToString(16)])); + Inc(Exponent, 5); + end; + end; +end; + +procedure TTestBigInteger.TestTestBit; +var + I, J: Integer; + BitIsSet, CheckBitIsSet: Boolean; + Rand: Integer; + Value, ShiftedValue: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + for J := 0 to 19 do + begin + Rand := System.Random(Value.BitLength + 4 * SizeOf(TLimb)); + ShiftedValue := BigInteger.One shl Rand; + BitIsSet := Value.TestBit(Rand); + CheckBitIsSet := (ShiftedValue and Value) <> 0; + Check(BitIsSet = CheckBitIsSet, Format('%d,%d: %s.TestBit(%d): %s (%s) <-- %s (%s)', [I, J, Value.ToString(16), Rand, BoolToStr(BitIsSet), BoolToStr(CheckBitIsSet), Value.ToString(16), ShiftedValue.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestGreaterThan; +var + I, J, N: Integer; + Comp, CheckComp: Boolean; + Left, Right: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + Comp := Left > Right; + CheckComp := ComparisonResults[N, crGreater]; + Check(Comp = CheckComp, Format('%d,%d: %s > %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestGreaterThanOrEqual; +var + I, J, N: Integer; + Comp, CheckComp: Boolean; + Left, Right: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + Comp := Left >= Right; + CheckComp := ComparisonResults[N, crGreaterEqual]; + Check(Comp = CheckComp, Format('%d,%d: %s >= %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestLessThan; +var + I, J, N: Integer; + Comp, CheckComp: Boolean; + Left, Right: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + Comp := Left < Right; + CheckComp := ComparisonResults[N, crLess]; + Check(Comp = CheckComp, Format('%d,%d: %s < %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestLessThanOrEqual; +var + I, J, N: Integer; + Comp, CheckComp: Boolean; + Left, Right: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Left := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Right := Arguments[J]; + Comp := Left <= Right; + CheckComp := ComparisonResults[N, crLessEqual]; + Check(Comp = CheckComp, Format('%d,%d: %s <= %s: %s (%s)', [I, J, Arguments[I], Arguments[J], BoolToStr(Comp), BoolToStr(CheckComp)])); + Inc(N); + end; + end; +end; + +function Dbl2Hex(const D: Double): string; +begin + Result := Format('%.8X', [PUInt64(@D)^]); +end; + +procedure TTestBigInteger.TestAsDouble; +var + I: Integer; + D1, D2: Double; + Value: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + D1 := Value.AsDouble; + D2 := DoubleResults[I]; + if IsInfinite(D1) then + Check(IsInfinite(D2)) + else if IsNan(D1) then + Check(IsNan(D2)) + else + Check(SameValue(D1, D2), Format('(%d): Double(%s) = %0.15f # $%s (%0.15f # $%s)', [I, Value.ToString, D1, Dbl2Hex(D1), D2, Dbl2Hex(D2)])); + end; +end; + +procedure TTestBigInteger.TestAsInteger; +var + I, Int1, Int2: Integer; + A: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + try + Int1 := A.AsInteger; + Int2 := StrToInt(AsIntegerResults[I].val); + Check(Int1 = Int2); + except + on E: EConvertError do + Check(AsIntegerResults[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); + on E: Exception do + Error('TestAsInteger: Unexpected exception: ' + E.ClassName + ': ' + E.Message); + end; + end; +end; + +procedure TTestBigInteger.TestAsCardinal; +var + I: Integer; + Card1, Card2: Cardinal; + A: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + try + Card1 := A.AsCardinal; + Card2 := StrToInt(AsCardinalResults[I].val); + Check(Card1 = Card2, Format('%d: %d (%d)', [I, Card1, Card2])); + except + on E: EConvertError do + Check(AsCardinalResults[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); + on E: Exception do + Error('TestAsCardinal: Unexpected exception: ' + E.ClassName + ': ' + E.Message); + end; + end; +end; + +procedure TTestBigInteger.TestAsInt64; +var + I: Integer; + Int1, Int2: Int64; + Value: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + try + Int1 := Value.AsInt64; + Int2 := StrToInt64(AsInt64Results[I].val); + Check(Int1 = Int2); + except + on E: EConvertError do + Check(AsInt64Results[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); + on E: Exception do + Error('TestAsInt64: Unexpected exception: ' + E.ClassName + ': ' + E.Message); + end; + end; +end; + +procedure TTestBigInteger.TestAsUInt64; +var + I: Integer; + UInt1: UInt64; + S1, S2: string; + Value: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + try + // Must use string comparison, because on some versions there is no suitable StrToUInt64, so + // there is no way to compare UInt64s. + UInt1 := Value.AsUInt64; + S1 := Format('%u', [UInt1]); + except + on E: EConvertError do + begin + Check(AsUInt64Results[I].info = triOverflow, Format('%d: EConvertError not expected', [I])); + Continue; + end; + on E: Exception do + Error('TestAsUInt64: Unexpected exception: ' + E.ClassName + ': ' + E.Message); + end; + S2 := AsUInt64Results[I].val; + Check(S1 = S2, Format('%d: %s.ToUInt64 = %s (%s)', [I, Value.ToString, S1, S2])); + end; +end; + +{$IFNDEF IMMUTABLE} +procedure TTestBigInteger.TestDec; +var + I: Integer; + Value, PredValue, DecValue: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + PredValue := Value - 1; + DecValue := Value; + Dec(DecValue); + Check(DecValue = PredValue, Format('(%d) %s --> %s (%s)', [I, Value.ToString, DecValue.ToString, PredValue.ToString])); + Check(Value = PredValue + 1); + end; +end; +{$ENDIF} + +procedure TTestBigInteger.TestDivMod; +var + I, J, N: Integer; + TRDiv, TRMod: TTestResult; + Dividend, Divisor, Quotient, Remainder, CheckQ, CheckR: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[J]; + TRDiv := DivisionResults[N]; + TRMod := ModulusResults[N]; + Inc(N); + try + Quotient := 0; + Remainder := 0; + BigInteger.DivMod(Dividend, Divisor, Quotient, Remainder); + except + on E: EZeroDivide do + begin + Check(TRDiv.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); + Continue; + end; + on E: Exception do + Error('Unexpected ' + E.ClassName + ' exception: ''' + E.Message + ''''); + end; + Check(TRDiv.info = triOK, Format('%d,%d: Expected an exception for %s div %s', [I, J, Dividend.ToString, Divisor.ToString])); + CheckQ := TRDiv.val; + CheckR := TRMod.val; + Check(Quotient = CheckQ, Format('(%d,%d) %s div %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Quotient.ToString(16), CheckQ.ToString(16)])); + Check(Remainder = CheckR, Format('(%d,%d) %s mod %s = "%s" ("%s")', [I, J, Dividend.ToString(16), Divisor.ToString(16), Remainder.ToString(16), CheckR.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestDivModKnuth; +var + I, J, N: Integer; + TRDiv, TRMod: TTestResult; + Dividend, Divisor, Quotient, Remainder, CheckQ, CheckR: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[J]; + TRDiv := DivisionResults[N]; + TRMod := ModulusResults[N]; + Inc(N); + try + Quotient := 0; + Remainder := 0; + BigInteger.DivModKnuth(Dividend, Divisor, Quotient, Remainder); + except + on E: EZeroDivide do + begin + Check(TRDiv.info = triDivideByZero, Format('(%d,%d) Unexpected EZeroDivide exception occurred', [I, J])); + Continue; + end; + on E: Exception do + Error('Unexpected ' + E.ClassName + ' exception: ''' + E.Message + ''''); + end; + Check(TRDiv.info = triOK, Format('%d,%d: Expected an exception for %s div %s', [I, J, Dividend.ToString, Divisor.ToString])); + CheckQ := TRDiv.val; + CheckR := TRMod.val; + Check(Quotient = CheckQ, Format('(%d,%d) %s div %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Quotient.ToString(16), CheckQ.ToString(16)])); + Check(Remainder = CheckR, Format('(%d,%d) %s mod %s = %s (%s)', [I, J, Dividend.ToString(16), Divisor.ToString(16), Remainder.ToString(16), CheckR.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestDivMod16; +var + I, J: Integer; + U16: UInt16; + Dividend, Divisor, U16Equiv, U16OpResult, BigIntOpResult: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[I]; + U16 := UInt16(Divisor); + U16Equiv := U16; + if U16 = 0 then + Continue; + U16OpResult := BigInteger.Divide(Dividend, U16); + BigIntOpResult := BigInteger.Divide(Dividend, U16Equiv); + Check(BigIntOpResult = U16OpResult, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16OpResult.ToString(16), BigIntOpResult.ToString(16)])); + U16OpResult := BigInteger.Remainder(Dividend, U16); + BigIntOpResult := BigInteger.Remainder(Dividend, U16Equiv); + Check(BigIntOpResult = U16OpResult, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U16, U16OpResult.ToString(16), BigIntOpResult.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestDivMod32; +var + I, J: Integer; + U32: UInt32; + Dividend, Divisor, U32Equiv, U32OpResult, BigIntOpResult: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + Dividend := Arguments[I]; + for J := 0 to High(Arguments) do + begin + Divisor := Arguments[I]; + U32 := UInt32(Divisor); + U32Equiv := U32; + if U32 = 0 then + Continue; + U32OpResult := BigInteger.Divide(Dividend, U32); + BigIntOpResult := BigInteger.Divide(Dividend, U32Equiv); + Check(BigIntOpResult = U32OpResult, Format('(%d, %d) %s div %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32OpResult.ToString(16), BigIntOpResult.ToString(16)])); + U32OpResult := BigInteger.Remainder(Dividend, U32); + BigIntOpResult := BigInteger.Remainder(Dividend, U32Equiv); + Check(BigIntOpResult = U32OpResult, Format('(%d, %d) %s mod %x = %s (%s)', [I, J, Dividend.ToString(16), U32, U32OpResult.ToString(16), BigIntOpResult.ToString(16)])); + end; + end; +end; + +procedure TTestBigInteger.TestDivModBurnikelZiegler; +var + I: Integer; + R: IRandom; + Threshold: Integer; + DendSize, DorSize: Integer; + Dividend, Divisor, KnuthQ, KnuthR, BZQ, BZR: BigInteger; +begin + R := TDelphiRandom.Create($1234567); + for I := 1 to 20 do + begin + Threshold := 160; + DendSize := Threshold * 145; + Dividend := BigInteger.Create(DendSize, R); + DorSize := Threshold * 65; + Divisor := BigInteger.Create(DorSize, R); + BigInteger.DivModKnuth(Dividend, Divisor, KnuthQ, KnuthR); + BigInteger.DivModBurnikelZiegler(Dividend, Divisor, BZQ, BZR); + Check(KnuthQ = BZQ, Format('%d: %s div %s = %s (%s)', [I, Dividend.ToString(16), Divisor.ToString(16), BZQ.ToString(16), KnuthQ.ToString(16)])); // Check quotients + Check(KnuthR = BZR, Format('%d: %s mod %s = %s (%s)', [I, Dividend.ToString(16), Divisor.ToString(16), BZR.ToString(16), KnuthR.ToString(16)])); // Check remainders + end; +end; + +//procedure TestTBigInteger.TestAbs; +//begin +//end; +// +procedure TTestBigInteger.TestBitLength; +var + I: Integer; + Value: BigInteger; +begin + Value := 1; + for I := 1 to 1000 do + begin + Check(Value.BitLength = I); + Value := Value + Value; + end; + Value := 1; + for I := 1 to 1000 do + begin + Check(Value.BitLength = I); + Value := Value + Value + BigInteger.One; + end; +end; + +procedure TTestBigInteger.TestGreatestCommonDivisor; +var + I, J, N: Integer; + A, B, GCD, CheckGCD: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + for J := 0 to High(Arguments) do + begin + B := Arguments[J]; + GCD := BigInteger.GreatestCommonDivisor(A, B); + CheckGCD := GCDResults[N].val; + + Check(GCD = CheckGCD); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestLn; +var + I: Integer; + D1, D2: Double; + A: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + D1 := BigInteger.Ln(A); + D2 := LnResults[I]; + if IsInfinite(D1) then + Check(IsInfinite(D2)) + else if IsNan(D1) then + Check(IsNan(D2)) + else + Check(SameValue(D1, D2), Format('%d: Ln(%s) = %0.15f (%0.15f)', [I, A.ToString, D1, D2])); + end; + A := BigInteger.Pow(1000, 1000); + D1 := BigInteger.Ln(A); + Check(SameValue(D1, Ln_1000_1000, 1e-10), Format('Ln(Pow(1000, 1000)): %.15f (%.15f)', [D1, 0.0 + Ln_1000_1000])); + D1 := BigInteger.Log10(A); + Check(SameValue(D1, Log10_1000_1000, 1e-10), Format('Log10(Pow(1000, 1000)): %.15f (%.15f)', [D1, 0.0 + Log10_1000_1000])); + D1 := BigInteger.Log2(A); + Check(SameValue(D1, Log2_1000_1000, 1e-10), Format('Log2(Pow(1000, 1000)): %.15f (%.15f)', [D1, 0.0 + Log2_1000_1000])); +end; + +procedure TTestBigInteger.TestMax; +var + I, J, N: Integer; + A, B, Maximum, CheckMax: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + for J := 0 to High(Arguments) do + begin + B := Arguments[J]; + Maximum := BigInteger.Max(A, B); + CheckMax := MaxResults[N].val; + Inc(N); + Check(Maximum = CheckMax); + end; + end; +end; + +procedure TTestBigInteger.TestMin; +var + I, J, N: Integer; + A, B, Mimimum, CheckMin: BigInteger; +begin + N := 0; + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + + for J := 0 to High(Arguments) do + begin + B := Arguments[J]; + + Mimimum := BigInteger.Min(A, B); + CheckMin := MinResults[N].val; + Inc(N); + Check(Mimimum = CheckMin); + end; + end; +end; + +// How to test this properly? ModPow() has 3 parameters, so which ones to choose? +// Note that PowerResults already has 1600 entries. Choosing bit shifts for the +// 3rd parameter would produce 1600 * 40 = 64000 entries. +// So what to do? Taking only every third argument would reduce this to 2197 entries. + +procedure TTestBigInteger.TestModPow; +var + Base, Exponent, Modulus, ModPower: BigInteger; + I, J, K, N: Integer; + TR: TTestResult; + HadException: Boolean; +begin + N := 0; + I := 2; + while I < High(Arguments) do + begin + Base := BigInteger(Arguments[I]); + Base := BigInteger.Abs(Base); + J := 0; + while J < High(Arguments) do + begin + Exponent := BigInteger(Arguments[J]); + Exponent := BigInteger.Abs(Exponent); + K := 1; + while K < High(Arguments) do + begin + Modulus := BigInteger(Arguments[K]); + Modulus := BigInteger.Abs(Modulus); + + TR := ModPowResults[N]; + + HadException := False; + try + ModPower := BigInteger.ModPow(Base, Exponent, Modulus); + except + on E: Exception do + begin + Check(TR.Info <> triOk, Format('%d: Unexpect exception on ModPow(%s, %s, %s): %s -- %s', [N, string(Base), string(Exponent), string(Modulus), E.ClassName, E.Message])); + HadException := True; + end; + end; + + if not HadException then + begin + Check(TR.Info = triOk, Format('%d: ModPos(%s, %s, %s) has Java error: %s', [N, string(Base), string(Exponent), string(Modulus), TR.Val])); + Check(BigInteger(TR.Val) = ModPower, Format('(%d,%d,%d,%d): ModPow(%s, %s, %s) = %s (%s)', [I, J, K, N, string(Base), string(Exponent), string(Modulus), string(ModPower), TR.Val])); + end; + Inc(N); + Inc(K, 5); + end; + Inc(J, 5); + end; + Inc(I, 5); + end; +end; + +procedure TTestBigInteger.TestParse; +var + I: Integer; + ParseString, StringResult: string; + Value: BigInteger; +begin + for I := High(MultiplyResults) downto 0 do + begin + ParseString := MultiplyResults[I].val; + try + Value := ParseString; + except + on E: Exception do + begin + Error(Format('%s, MultiplyResults[%d]: %s'#13#10'val = %s', [E.ClassName, I, E.Message, MultiplyResults[I].val])); + end; + end; + try + StringResult := Value.ToString(10); + except + on E: Exception do + begin + Error(Format('(%d) Error %s with message: %s', [I, E.ClassName, E.Message])); + raise; + end; + end; + Check(ParseString = StringResult, Format('MultiplyResults[%d]: ''%s'' --> %s (%s), classic: %s', [I, ParseString, StringResult, ParseString, Value.ToStringClassic(10)])); + end; +end; + +procedure TTestBigInteger.TestPow; +var + I, J, N, Exponent: Integer; + Base, Power, CheckPower: BigInteger; +begin + N := 0; + for I := 0 to High(BitShifts) do + begin + Base := BitShifts[I]; + for J := 0 to High(BitShifts) do + begin + Exponent := BitShifts[J]; + Power := BigInteger.Pow(Base, Exponent); + CheckPower := PowerResults[N].val; + Check(Power = CheckPower, Format('(%d,%d) Pow(%s, %d) = %s (%s)', [I, J, Base.ToString, Exponent, Power.ToString, CheckPower.ToString])); + Inc(N); + end; + end; +end; + +procedure TTestBigInteger.TestPred; +var + Value, Predecessor, ValueMinusOne: BigInteger; + I: Integer; +begin + for I := 0 to High(Arguments) do + begin + Value := Arguments[I]; + Predecessor := Value.Pred; + ValueMinusOne := Value - BigInteger.One; + Check(Predecessor = ValueMinusOne, Format('(%d) Pred(%s) = %s (%s)', [I, string(Value), string(Predecessor), string(ValueMinusOne)])); + end; +end; + +procedure TTestBigInteger.TestToByteArray; +var + I, J: Integer; + S1, S2: string; + Bytes: TArray; + A: BigInteger; +begin + for I := 0 to High(Arguments) do + begin + A := Arguments[I]; + Bytes := A.ToByteArray; + S1 := ''; + for J := 0 to High(Bytes) do + S1 := S1 + Format('%.2X', [Bytes[J]]); + S2 := ByteArrayResults[I].val; + Check(S1 = S2, Format('%d: %s --> %s (%s)', [I, A.ToString(16), S1, S2])); + end; +end; + +initialization + // Register any test cases with the test runner + RegisterTest(TTestBigInteger.Suite); +end. + + + diff --git a/Tests/BigRationals/BigRationalDevelopmentTests.dproj b/Tests/BigRationals/BigRationalDevelopmentTests.dproj index 467c4e3..679f83a 100644 --- a/Tests/BigRationals/BigRationalDevelopmentTests.dproj +++ b/Tests/BigRationals/BigRationalDevelopmentTests.dproj @@ -1,7 +1,7 @@  {BCA851BB-A137-43FC-BCB8-1A8B89013254} - 18.4 + 18.5 None True Debug @@ -13,26 +13,6 @@ true - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - true Base @@ -75,85 +55,6 @@ false false - - $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png - true - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png - Debug - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= - $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png - $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png - true - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png - true - true - true - true - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png - true - true - $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png - android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar - true - true - - - iPhoneAndiPad - $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png - $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png - $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png - $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png - $(MSBuildProjectName) - CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera - $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png - $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png - Debug - $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png - true - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png - $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png - - - iPhoneAndiPad - $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png - $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png - $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png - $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png - $(MSBuildProjectName) - CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera - $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png - $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png - Debug - $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png - true - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png - $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png - - - $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png - iPhoneAndiPad - $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png - $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png - $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png - $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png - CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera - $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png - $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png - true - $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png - $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png - vcldbx;TeeDB;Rave100VCL;vclib;Tee;inetdbbde;DBXOdbcDriver;svnui;ibxpress;DBXSybaseASEDriver;vclimg;intrawebdb_120_160;fmi;vclactnband;FMXTee;vcldb;TeeUI;bindcompvcl;vcldsnap;vclie;vcltouch;Intraweb_120_160;DBXDb2Driver;websnap;vclribbon;VclSmp;vcl;DataSnapConnectors;CloudService;DBXMSSQLDriver;CodeSiteExpressPkg;FmxTeeUI;dsnapcon;vclx;webdsnap;svn;bdertl;adortl;$(DCC_UsePackage) Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) @@ -248,12 +149,22 @@ true + + + true + + + + + true + + true - + true @@ -280,7 +191,6 @@ 1 - Contents\MacOS 0 @@ -290,6 +200,12 @@ 1 + + + res\xml + 1 + + library\lib\armeabi-v7a @@ -326,6 +242,12 @@ 1 + + + res\values-v21 + 1 + + res\drawable @@ -402,6 +324,10 @@ 1 .framework + + 1 + .framework + 0 @@ -411,6 +337,10 @@ 1 .dylib + + 1 + .dylib + 0 .dll;.bpl @@ -433,6 +363,10 @@ 1 .dylib + + 1 + .dylib + 0 .bpl @@ -454,6 +388,9 @@ 0 + + 0 + 0 @@ -564,6 +501,7 @@ 1 + @@ -571,6 +509,10 @@ Contents\Resources 1 + + Contents\Resources + 1 + @@ -592,6 +534,9 @@ 1 + + 1 + 0 @@ -631,15 +576,11 @@ + - False - False - False - False False - False True False diff --git a/Visualizers/BigNumVisualizers.dpk b/Visualizers/BigNumVisualizers.dpk index 5c41776..40cfc58 100644 --- a/Visualizers/BigNumVisualizers.dpk +++ b/Visualizers/BigNumVisualizers.dpk @@ -26,9 +26,7 @@ package BigNumVisualizers; {$DEFINE DEBUG} {$ENDIF IMPLICITBUILDING} {$DESCRIPTION 'Velthuis Debug Visualizers for BigInteger and BigDecimal types'} - -{$INCLUDE 'LibSuffixes.inc'} - +{$LIBSUFFIX '260'} {$DESIGNONLY} {$IMPLICITBUILD ON} diff --git a/Visualizers/BigNumVisualizers.dproj b/Visualizers/BigNumVisualizers.dproj index 2e75958..18552a0 100644 --- a/Visualizers/BigNumVisualizers.dproj +++ b/Visualizers/BigNumVisualizers.dproj @@ -4,45 +4,20 @@ BigNumVisualizers.dpk True Debug - 1153 + 129 Package None - 18.4 + 18.5 Win32 true - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - true Base true - - true - Base - true - true Base @@ -63,12 +38,6 @@ Base true - - true - Cfg_2 - true - true - true Cfg_2 @@ -92,27 +61,9 @@ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) - - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= - Debug - android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar - rtl;$(DCC_UsePackage) - - - rtl;$(DCC_UsePackage) - - - rtl;BigNumbers;$(DCC_UsePackage) - - - rtl;$(DCC_UsePackage) - rtl;BigNumbers;$(DCC_UsePackage) - - rtl;$(DCC_UsePackage) - Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) Debug @@ -135,14 +86,11 @@ false true - - Debug - true 1033 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) - 250 + 260 Velthuis Debug Visualizers for BigInteger and BigDecimal types @@ -181,12 +129,7 @@ - False - False - True - False True - False True False @@ -196,8 +139,14 @@ true - - + + + BigNumVisualizers.bpl + true + + + + true @@ -206,14 +155,18 @@ true - - + + true - - - BigNumVisualizers.bpl + + + true + + + + true @@ -222,7 +175,6 @@ 1 - Contents\MacOS 0 @@ -232,6 +184,12 @@ 1 + + + res\xml + 1 + + library\lib\armeabi-v7a @@ -268,6 +226,12 @@ 1 + + + res\values-v21 + 1 + + res\drawable @@ -344,6 +308,10 @@ 1 .framework + + 1 + .framework + 0 @@ -353,6 +321,10 @@ 1 .dylib + + 1 + .dylib + 0 .dll;.bpl @@ -375,6 +347,10 @@ 1 .dylib + + 1 + .dylib + 0 .bpl @@ -396,6 +372,9 @@ 0 + + 0 + 0 @@ -506,6 +485,7 @@ 1 + @@ -513,6 +493,10 @@ Contents\Resources 1 + + Contents\Resources + 1 + @@ -534,6 +518,9 @@ 1 + + 1 + 0 @@ -573,6 +560,7 @@ + diff --git a/Visualizers/BigNumberVisualizers.dproj b/Visualizers/BigNumberVisualizers.dproj index 97e520f..6db6a6b 100644 --- a/Visualizers/BigNumberVisualizers.dproj +++ b/Visualizers/BigNumberVisualizers.dproj @@ -1,7 +1,7 @@  {82F7D428-1B82-4DC7-A2A3-E6FC570D13D4} - 18.4 + 18.5 None BigNumberVisualizers.dpr True @@ -13,11 +13,6 @@ true - - true - Base - true - true Base @@ -66,9 +61,6 @@ false false - - DataSnapServerMidas;FireDACMSSQLDriver;bindcompfmx;inetdb;emsedge;FireDACIBDriver;fmxdae;FireDACCommon;soapserver;bindengine;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;FireDACCommonDriver;inet;bindcompdbx;fmxFireDAC;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;soaprtl;ibxpress;DataSnapServer;soapmidas;DataSnapNativeClient;fmxobj;ibxbindings;bindcomp;dbxcds;FireDACODBCDriver;DataSnapProviderClient;inetdbxpress;FireDACMongoDBDriver;fmxase;$(DCC_UsePackage) - (None) C:\Users\Administrator\Documents\GitHub\BigNumbers\Source;$(DCC_UnitSearchPath) @@ -146,8 +138,20 @@ true - - + + + BigNumberVisualizers.dll + true + + + + + BigNumberVisualizers.dll + true + + + + true @@ -156,20 +160,18 @@ true - - + + true - - - BigNumberVisualizers.dll + + true - - - BigNumberVisualizers.dll + + true @@ -182,7 +184,6 @@ 1 - Contents\MacOS 0 @@ -192,6 +193,12 @@ 1 + + + res\xml + 1 + + library\lib\armeabi-v7a @@ -228,6 +235,12 @@ 1 + + + res\values-v21 + 1 + + res\drawable @@ -306,6 +319,11 @@ 1 .framework + + Contents\MacOS + 1 + .framework + 0 @@ -328,6 +346,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .dll;.bpl @@ -351,6 +374,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .bpl @@ -373,6 +401,10 @@ Contents\Resources\StartUp\ 0 + + Contents\Resources\StartUp\ + 0 + 0 @@ -509,23 +541,41 @@ 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + ..\ 1 + + ..\ + 1 + Contents 1 + + Contents + 1 + Contents\Resources 1 + + Contents\Resources + 1 + @@ -548,6 +598,10 @@ Contents\MacOS 1 + + Contents\MacOS + 1 + 0 @@ -587,10 +641,10 @@ + - False True False diff --git a/Visualizers/BigNumbers.dpk b/Visualizers/BigNumbers.dpk index 575f2ff..b0d9078 100644 --- a/Visualizers/BigNumbers.dpk +++ b/Visualizers/BigNumbers.dpk @@ -26,9 +26,7 @@ package BigNumbers; {$DEFINE DEBUG} {$ENDIF IMPLICITBUILDING} {$DESCRIPTION 'Velthuis BigInteger and BigDecimal for Delphi'} - -{$INCLUDE 'LibSuffixes.inc'} - +{$LIBSUFFIX '260'} {$IMPLICITBUILD ON} requires diff --git a/Visualizers/BigNumbers.dproj b/Visualizers/BigNumbers.dproj index e903bce..44b2fe8 100644 --- a/Visualizers/BigNumbers.dproj +++ b/Visualizers/BigNumbers.dproj @@ -4,45 +4,20 @@ BigNumbers.dpk True Debug - 1153 + 129 Package None - 18.4 + 18.5 Win32 true - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - true Base true - - true - Base - true - true Base @@ -63,12 +38,6 @@ Base true - - true - Cfg_2 - true - true - true Cfg_2 @@ -90,27 +59,9 @@ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) - - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= - Debug - android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar - rtl;$(DCC_UsePackage) - - - rtl;$(DCC_UsePackage) - - - rtl;$(DCC_UsePackage) - - - rtl;$(DCC_UsePackage) - rtl;$(DCC_UsePackage) - - rtl;$(DCC_UsePackage) - Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) Debug @@ -133,14 +84,11 @@ false true - - Debug - true 1033 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) - 250 + 260 Velthuis BigInteger and BigDecimal for Delphi @@ -188,12 +136,7 @@ - False - False - True - False True - False True False @@ -203,8 +146,14 @@ true - - + + + BigNumbers.bpl + true + + + + true @@ -213,14 +162,18 @@ true - - + + true - - - BigNumbers.bpl + + + true + + + + true @@ -229,7 +182,6 @@ 1 - Contents\MacOS 0 @@ -239,6 +191,12 @@ 1 + + + res\xml + 1 + + library\lib\armeabi-v7a @@ -275,6 +233,12 @@ 1 + + + res\values-v21 + 1 + + res\drawable @@ -351,6 +315,10 @@ 1 .framework + + 1 + .framework + 0 @@ -360,6 +328,10 @@ 1 .dylib + + 1 + .dylib + 0 .dll;.bpl @@ -382,6 +354,10 @@ 1 .dylib + + 1 + .dylib + 0 .bpl @@ -403,6 +379,9 @@ 0 + + 0 + 0 @@ -513,6 +492,7 @@ 1 + @@ -520,6 +500,10 @@ Contents\Resources 1 + + Contents\Resources + 1 + @@ -541,6 +525,9 @@ 1 + + 1 + 0 @@ -580,6 +567,7 @@ +