Social Icons

воскресенье, 4 августа 2013 г.

Numerics для Delphi & FPC (работа с большими числами)

Сергей Касандров выпустил довольно интересный модуль для работы с большими числами в Delphi и FreePascal (сделано на чистом Паскале, без оптимизаций) - новость и архив. В архиве содержится исходный код модуля, а также тестовый проект и скомпилированные dll (32- и 64-битные).

Для предварительного ознакомления с реализацией код модуля (из архива) приведен ниже.
{ *********************************************************** }
{ *       Numerics(32/64).dll import for Pascal             * }
{ * ------------------------------------------------------- * }
{ *       set const LibName = 'numerics32.dll'              * }
{ *         to import numerics32.dll;                       * }
{ *       set const LibName = 'numerics64.dll'              * }
{ *         to import numerics64.dll;                       * }
{ *********************************************************** }

{
  Copyright (c) 2013 Sergey Kasandrov

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
}

unit Numerics;

{$IFDEF FPC}
  {$mode delphi}
{$ENDIF}

interface

uses Windows, SysUtils;

type
  TF_RESULT = LongInt;

const
                                              // = common microsoft codes =
  TF_S_OK           = TF_RESULT(0);           // Operation successful
  TF_S_FALSE        = TF_RESULT(1);           // Operation successful
  TF_E_FAIL         = TF_RESULT($80004005);   // Unspecified failure
  TF_E_INVALIDARG   = TF_RESULT($80070057);   // One or more arguments are not valid
  TF_E_NOINTERFACE  = TF_RESULT($80004002);   // No such interface supported
  TF_E_NOTIMPL      = TF_RESULT($80004001);   // Not implemented
  TF_E_OUTOFMEMORY  = TF_RESULT($8007000E);   // Failed to allocate necessary memory
  TF_E_UNEXPECTED   = TF_RESULT($8000FFFF);   // Unexpected failure

                                              // = TFL specific codes =
  TF_E_NOMEMORY     = TF_RESULT($A0000003);   // specific TFL memory error
  TF_E_LOADERROR    = TF_RESULT($A0000004);   // Error loading dll

{$IFDEF FPC}
type
  TBytes = array of Byte;
{$ENDIF}

type
  IBigNumber = interface

    function GetIsEven: Boolean; stdcall;
    function GetIsOne: Boolean; stdcall;
    function GetIsPowerOfTwo: Boolean; stdcall;
    function GetIsZero: Boolean; stdcall;
    function GetSign: Integer; stdcall;
    function GetSize: Integer; stdcall;

    function CompareNumber(Num: IBigNumber): Integer; stdcall;
    function CompareNumberU(Num: IBigNumber): Integer; stdcall;

    function AddNumber(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function AddNumberU(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function SubNumber(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function SubNumberU(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function MulNumber(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function MulNumberU(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function DivRemNumber(Num: IBigNumber; var Q, R: IBigNumber): TF_RESULT; stdcall;
    function DivRemNumberU(Num: IBigNumber; var Q, R: IBigNumber): TF_RESULT; stdcall;

    function AndNumber(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function AndNumberU(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function OrNumber(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function OrNumberU(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;
    function XorNumber(Num: IBigNumber; var Res: IBigNumber): TF_RESULT; stdcall;

    function ShlNumber(Shift: Cardinal; var Res: IBigNumber): TF_RESULT; stdcall;
    function ShrNumber(Shift: Cardinal; var Res: IBigNumber): TF_RESULT; stdcall;

    function AssignNumber(var Res: IBigNumber): TF_RESULT; stdcall;
    function AbsNumber(var Res: IBigNumber): TF_RESULT; stdcall;
    function NegateNumber(var Res: IBigNumber): TF_RESULT; stdcall;
    function Pow(Value: Cardinal; var IRes: IBigNumber): TF_RESULT; stdcall;
    function PowU(Value: Cardinal; var IRes: IBigNumber): TF_RESULT; stdcall;
    function PowerMod(IExp, IMod: IBigNumber; var IRes: IBigNumber): TF_RESULT; stdcall;
    function SqrtNumber(var IRes: IBigNumber): TF_RESULT; stdcall;

    function ToLimb(var Value: UInt32): TF_RESULT; stdcall;
    function ToIntLimb(var Value: Int32): TF_RESULT; stdcall;
    function ToDec(P: PByte; var L: Integer): TF_RESULT; stdcall;
    function ToHex(P: PByte; var L: Integer; TwoCompl: Boolean): TF_RESULT; stdcall;
    function ToPByte(P: PByte; var L: Cardinal): TF_RESULT; stdcall;

    function CompareToLimb(B: UInt32): Integer; stdcall;
    function CompareToLimbU(B: UInt32): Integer; stdcall;
    function CompareToIntLimb(B: Int32): Integer; stdcall;
    function CompareToIntLimbU(B: Int32): Integer; stdcall;

    function AddLimb(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function AddLimbU(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function AddIntLimb(Limb: LongInt; var Res: IBigNumber): TF_RESULT; stdcall;

    function SubLimb(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function SubLimb2(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function SubLimbU(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function SubLimbU2(Limb: LongWord; var Res: LongWord): TF_RESULT; stdcall;
    function SubIntLimb(Limb: LongInt; var Res: IBigNumber): TF_RESULT; stdcall;
    function SubIntLimb2(Limb: LongInt; var Res: IBigNumber): TF_RESULT; stdcall;

    function MulLimb(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function MulLimbU(Limb: LongWord; var Res: IBigNumber): TF_RESULT; stdcall;
    function MulIntLimb(Limb: LongInt; var Res: IBigNumber): TF_RESULT; stdcall;

    function DivRemLimb(Limb: LongWord; var Q: IBigNumber; var R: IBigNumber): TF_RESULT; stdcall;
    function DivRemLimb2(Limb: LongWord; var Q: IBigNumber; var R: LongWord): TF_RESULT; stdcall;
    function DivRemLimbU(Limb: LongWord; var Q: IBigNumber; var R: LongWord): TF_RESULT; stdcall;
    function DivRemLimbU2(Limb: LongWord; var Q: LongWord; var R: LongWord): TF_RESULT; stdcall;
    function DivRemIntLimb(Limb: LongInt; var Q: IBigNumber; var R: LongInt): TF_RESULT; stdcall;
    function DivRemIntLimb2(Limb: LongInt; var Q: LongInt; var R: LongInt): TF_RESULT; stdcall;

    function ToDblLimb(var Value: UInt64): TF_RESULT; stdcall;
    function ToDblIntLimb(var Value: Int64): TF_RESULT; stdcall;
    function CompareToDblLimb(B: UInt64): Integer; stdcall;
    function CompareToDblLimbU(B: UInt64): Integer; stdcall;
    function CompareToDblIntLimb(B: Int64): Integer; stdcall;
    function CompareToDblIntLimbU(B: Int64): Integer; stdcall;
  end;

type
  BigCardinal = record
  private
    FNumber: IBigNumber;
  public
    function ToString: string;
    function ToHexString(Digits: Integer = 0; const Prefix: string = '';
                         TwoCompl: Boolean = False): string;
    function ToBytes: TBytes;
    function TryParse(const S: string; TwoCompl: Boolean = False): Boolean;
    procedure Free;

    class function Compare(const A, B: BigCardinal): Integer; static;
    function CompareTo(const B: BigCardinal): Integer; overload;

    class function Pow(const Base: BigCardinal; Value: Cardinal): BigCardinal; static;
    class function DivRem(const Dividend, Divisor: BigCardinal;
                          var Remainder: BigCardinal): BigCardinal; overload; static;

    class operator Explicit(const Value: BigCardinal): Cardinal;
    class operator Explicit(const Value: BigCardinal): Integer;
    class operator Explicit(const Value: BigCardinal): UInt64;
    class operator Explicit(const Value: BigCardinal): Int64;
    class operator Implicit(const Value: Cardinal): BigCardinal;
    class operator Implicit(const Value: UInt64): BigCardinal;
    class operator Explicit(const Value: Integer): BigCardinal;
    class operator Explicit(const Value: Int64): BigCardinal;
    class operator Explicit(const Value: TBytes): BigCardinal;
    class operator Explicit(const Value: string): BigCardinal;

    class operator Equal(const A, B: BigCardinal): Boolean; inline;
    class operator NotEqual(const A, B: BigCardinal): Boolean; inline;
    class operator GreaterThan(const A, B: BigCardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A, B: BigCardinal): Boolean; inline;
    class operator LessThan(const A, B: BigCardinal): Boolean; inline;
    class operator LessThanOrEqual(const A, B: BigCardinal): Boolean; inline;

    class operator Add(const A, B: BigCardinal): BigCardinal;
    class operator Subtract(const A, B: BigCardinal): BigCardinal;
    class operator Multiply(const A, B: BigCardinal): BigCardinal;
    class operator IntDivide(const A, B: BigCardinal): BigCardinal;
    class operator Modulus(const A, B: BigCardinal): BigCardinal;

    class operator LeftShift(const A: BigCardinal; Shift: Cardinal): BigCardinal;
    class operator RightShift(const A: BigCardinal; Shift: Cardinal): BigCardinal;

    class operator BitwiseAnd(const A, B: BigCardinal): BigCardinal;
    class operator BitwiseOr(const A, B: BigCardinal): BigCardinal;

    function CompareToCard(const B: Cardinal): Integer;
    function CompareToInt(const B: Integer): Integer;
    function CompareTo(const B: Cardinal): Integer; overload; inline;
    function CompareTo(const B: Integer): Integer; overload; inline;

    class operator Equal(const A: BigCardinal; const B: Cardinal): Boolean; inline;
    class operator Equal(const A: Cardinal; const B: BigCardinal): Boolean; inline;
    class operator Equal(const A: BigCardinal; const B: Integer): Boolean; inline;
    class operator Equal(const A: Integer; const B: BigCardinal): Boolean; inline;
    class operator NotEqual(const A: BigCardinal; const B: Cardinal): Boolean; inline;
    class operator NotEqual(const A: Cardinal; const B: BigCardinal): Boolean; inline;
    class operator NotEqual(const A: BigCardinal; const B: Integer): Boolean; inline;
    class operator NotEqual(const A: Integer; const B: BigCardinal): Boolean; inline;
    class operator GreaterThan(const A: BigCardinal; const B: Cardinal): Boolean; inline;
    class operator GreaterThan(const A: Cardinal; const B: BigCardinal): Boolean; inline;
    class operator GreaterThan(const A: BigCardinal; const B: Integer): Boolean; inline;
    class operator GreaterThan(const A: Integer; const B: BigCardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigCardinal; const B: Cardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: Cardinal; const B: BigCardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigCardinal; const B: Integer): Boolean; inline;
    class operator GreaterThanOrEqual(const A: Integer; const B: BigCardinal): Boolean; inline;
    class operator LessThan(const A: BigCardinal; const B: Cardinal): Boolean; inline;
    class operator LessThan(const A: Cardinal; const B: BigCardinal): Boolean; inline;
    class operator LessThan(const A: BigCardinal; const B: Integer): Boolean; inline;
    class operator LessThan(const A: Integer; const B: BigCardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: BigCardinal; const B: Cardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: Cardinal; const B: BigCardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: BigCardinal; const B: Integer): Boolean; inline;
    class operator LessThanOrEqual(const A: Integer; const B: BigCardinal): Boolean; inline;

    function CompareToUInt64(const B: UInt64): Integer;
    function CompareToInt64(const B: Int64): Integer;
    function CompareTo(const B: UInt64): Integer; overload; inline;
    function CompareTo(const B: Int64): Integer; overload; inline;

    class operator Equal(const A: BigCardinal; const B: UInt64): Boolean; inline;
    class operator Equal(const A: UInt64; const B: BigCardinal): Boolean; inline;
    class operator Equal(const A: BigCardinal; const B: Int64): Boolean; inline;
    class operator Equal(const A: Int64; const B: BigCardinal): Boolean; inline;
    class operator NotEqual(const A: BigCardinal; const B: UInt64): Boolean; inline;
    class operator NotEqual(const A: UInt64; const B: BigCardinal): Boolean; inline;
    class operator NotEqual(const A: BigCardinal; const B: Int64): Boolean; inline;
    class operator NotEqual(const A: Int64; const B: BigCardinal): Boolean; inline;
    class operator GreaterThan(const A: BigCardinal; const B: UInt64): Boolean; inline;
    class operator GreaterThan(const A: UInt64; const B: BigCardinal): Boolean; inline;
    class operator GreaterThan(const A: BigCardinal; const B: Int64): Boolean; inline;
    class operator GreaterThan(const A: Int64; const B: BigCardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigCardinal; const B: UInt64): Boolean; inline;
    class operator GreaterThanOrEqual(const A: UInt64; const B: BigCardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigCardinal; const B: Int64): Boolean; inline;
    class operator GreaterThanOrEqual(const A: Int64; const B: BigCardinal): Boolean; inline;
    class operator LessThan(const A: BigCardinal; const B: UInt64): Boolean; inline;
    class operator LessThan(const A: UInt64; const B: BigCardinal): Boolean; inline;
    class operator LessThan(const A: BigCardinal; const B: Int64): Boolean; inline;
    class operator LessThan(const A: Int64; const B: BigCardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: BigCardinal; const B: UInt64): Boolean; inline;
    class operator LessThanOrEqual(const A: UInt64; const B: BigCardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: BigCardinal; const B: Int64): Boolean; inline;
    class operator LessThanOrEqual(const A: Int64; const B: BigCardinal): Boolean; inline;

    class function DivRem(const Dividend: BigCardinal; Divisor: Cardinal;
                          var Remainder: Cardinal): BigCardinal; overload; static;
    class function DivRem(const Dividend: Cardinal; Divisor: BigCardinal;
                          var Remainder: Cardinal): Cardinal; overload; static;

    class operator Add(const A: BigCardinal; const B: Cardinal): BigCardinal;
    class operator Add(const A: Cardinal; const B: BigCardinal): BigCardinal;
    class operator Subtract(const A: BigCardinal; const B: Cardinal): BigCardinal;
    class operator Subtract(const A: Cardinal; const B: BigCardinal): Cardinal;
    class operator Multiply(const A: BigCardinal; const B: Cardinal): BigCardinal;
    class operator Multiply(const A: Cardinal; const B: BigCardinal): BigCardinal;
    class operator IntDivide(const A: BigCardinal; const B: Cardinal): BigCardinal;
    class operator IntDivide(const A: Cardinal; const B: BigCardinal): Cardinal;
    class operator Modulus(const A: BigCardinal; const B: Cardinal): Cardinal;
    class operator Modulus(const A: Cardinal; const B: BigCardinal): Cardinal;
  end;

  BigInteger = record
  private
    FNumber: IBigNumber;
    function GetSign: Integer;
  public
    function ToString: string;
    function ToHexString(Digits: Integer = 0; const Prefix: string = '';
                         TwoCompl: Boolean = False): string;
    function ToBytes: TBytes;
    function TryParse(const S: string; TwoCompl: Boolean = False): Boolean;
    procedure Free;

    property Sign: Integer read GetSign;

    class function Compare(const A, B: BigInteger): Integer; overload; static;
    class function Compare(const A: BigInteger; const B: BigCardinal): Integer; overload; static;
    class function Compare(const A: BigCardinal; const B: BigInteger): Integer; overload; static;
    function CompareTo(const B: BigInteger): Integer; overload; inline;
    function CompareTo(const B: BigCardinal): Integer; overload; inline;

    class function Abs(const A: BigInteger): BigInteger; static;
    class function Pow(const Base: BigInteger; Value: Cardinal): BigInteger; static;
    class function DivRem(const Dividend, Divisor: BigCardinal;
                          var Remainder: BigCardinal): BigCardinal; overload; static;

    class operator Implicit(const Value: BigCardinal): BigInteger; inline;
    class operator Explicit(const Value: BigInteger): BigCardinal; inline;

    class operator Explicit(const Value: BigInteger): Cardinal;
    class operator Explicit(const Value: BigInteger): UInt64;
    class operator Explicit(const Value: BigInteger): Integer;
    class operator Explicit(const Value: BigInteger): Int64;
    class operator Implicit(const Value: UInt32): BigInteger;
    class operator Implicit(const Value: UInt64): BigInteger;
    class operator Implicit(const Value: Int32): BigInteger;
    class operator Implicit(const Value: Int64): BigInteger;
    class operator Explicit(const Value: TBytes): BigInteger;
    class operator Explicit(const Value: string): BigInteger;

    class operator Equal(const A, B: BigInteger): Boolean; inline;
    class operator Equal(const A: BigInteger; const B: BigCardinal): Boolean; inline;
    class operator Equal(const A: BigCardinal; const B: BigInteger): Boolean; inline;
    class operator NotEqual(const A, B: BigInteger): Boolean; inline;
    class operator NotEqual(const A: BigInteger; const B: BigCardinal): Boolean; inline;
    class operator NotEqual(const A: BigCardinal; const B: BigInteger): Boolean; inline;
    class operator GreaterThan(const A, B: BigInteger): Boolean; inline;
    class operator GreaterThan(const A: BigInteger; const B: BigCardinal): Boolean; inline;
    class operator GreaterThan(const A: BigCardinal; const B: BigInteger): Boolean; inline;
    class operator GreaterThanOrEqual(const A, B: BigInteger): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigInteger; const B: BigCardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigCardinal; const B: BigInteger): Boolean; inline;
    class operator LessThan(const A, B: BigInteger): Boolean; inline;
    class operator LessThan(const A: BigInteger; const B: BigCardinal): Boolean; inline;
    class operator LessThan(const A: BigCardinal; const B: BigInteger): Boolean; inline;
    class operator LessThanOrEqual(const A, B: BigInteger): Boolean; inline;
    class operator LessThanOrEqual(const A: BigInteger; const B: BigCardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: BigCardinal; const B: BigInteger): Boolean; inline;

    class operator Add(const A, B: BigInteger): BigInteger;
    class operator Subtract(const A, B: BigInteger): BigInteger;
    class operator Multiply(const A, B: BigInteger): BigInteger;
    class operator IntDivide(const A, B: BigInteger): BigInteger;
    class operator Modulus(const A, B: BigInteger): BigInteger;

    class operator LeftShift(const A: BigInteger; Shift: Cardinal): BigInteger;
    class operator RightShift(const A: BigInteger; Shift: Cardinal): BigInteger;

    class operator BitwiseAnd(const A, B: BigInteger): BigInteger;
    class operator BitwiseOr(const A, B: BigInteger): BigInteger;
    class operator BitwiseXor(const A, B: BigInteger): BigInteger;

    function CompareToCard(const B: Cardinal): Integer;
    function CompareToInt(const B: Integer): Integer;
    function CompareTo(const B: Cardinal): Integer; overload; inline;
    function CompareTo(const B: Integer): Integer; overload; inline;
    class operator Equal(const A: BigInteger; const B: Cardinal): Boolean; inline;
    class operator Equal(const A: Cardinal; const B: BigInteger): Boolean; inline;
    class operator Equal(const A: BigInteger; const B: Integer): Boolean; inline;
    class operator Equal(const A: Integer; const B: BigInteger): Boolean; inline;
    class operator NotEqual(const A: BigInteger; const B: Cardinal): Boolean; inline;
    class operator NotEqual(const A: Cardinal; const B: BigInteger): Boolean; inline;
    class operator NotEqual(const A: BigInteger; const B: Integer): Boolean; inline;
    class operator NotEqual(const A: Integer; const B: BigInteger): Boolean; inline;
    class operator GreaterThan(const A: BigInteger; const B: Cardinal): Boolean; inline;
    class operator GreaterThan(const A: Cardinal; const B: BigInteger): Boolean; inline;
    class operator GreaterThan(const A: BigInteger; const B: Integer): Boolean; inline;
    class operator GreaterThan(const A: Integer; const B: BigInteger): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigInteger; const B: Cardinal): Boolean; inline;
    class operator GreaterThanOrEqual(const A: Cardinal; const B: BigInteger): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigInteger; const B: Integer): Boolean; inline;
    class operator GreaterThanOrEqual(const A: Integer; const B: BigInteger): Boolean; inline;
    class operator LessThan(const A: BigInteger; const B: Cardinal): Boolean; inline;
    class operator LessThan(const A: Cardinal; const B: BigInteger): Boolean; inline;
    class operator LessThan(const A: BigInteger; const B: Integer): Boolean; inline;
    class operator LessThan(const A: Integer; const B: BigInteger): Boolean; inline;
    class operator LessThanOrEqual(const A: BigInteger; const B: Cardinal): Boolean; inline;
    class operator LessThanOrEqual(const A: Cardinal; const B: BigInteger): Boolean; inline;
    class operator LessThanOrEqual(const A: BigInteger; const B: Integer): Boolean; inline;
    class operator LessThanOrEqual(const A: Integer; const B: BigInteger): Boolean; inline;

    function CompareToDoubleUInt(const B: UInt64): Integer;
    function CompareToDoubleInt(const B: Int64): Integer;
    function CompareTo(const B: UInt64): Integer; overload; inline;
    function CompareTo(const B: Int64): Integer; overload; inline;

    class operator Equal(const A: BigInteger; const B: UInt64): Boolean; inline;
    class operator Equal(const A: UInt64; const B: BigInteger): Boolean; inline;
    class operator Equal(const A: BigInteger; const B: Int64): Boolean; inline;
    class operator Equal(const A: Int64; const B: BigInteger): Boolean; inline;
    class operator NotEqual(const A: BigInteger; const B: UInt64): Boolean; inline;
    class operator NotEqual(const A: UInt64; const B: BigInteger): Boolean; inline;
    class operator NotEqual(const A: BigInteger; const B: Int64): Boolean; inline;
    class operator NotEqual(const A: Int64; const B: BigInteger): Boolean; inline;
    class operator GreaterThan(const A: BigInteger; const B: UInt64): Boolean; inline;
    class operator GreaterThan(const A: UInt64; const B: BigInteger): Boolean; inline;
    class operator GreaterThan(const A: BigInteger; const B: Int64): Boolean; inline;
    class operator GreaterThan(const A: Int64; const B: BigInteger): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigInteger; const B: UInt64): Boolean; inline;
    class operator GreaterThanOrEqual(const A: UInt64; const B: BigInteger): Boolean; inline;
    class operator GreaterThanOrEqual(const A: BigInteger; const B: Int64): Boolean; inline;
    class operator GreaterThanOrEqual(const A: Int64; const B: BigInteger): Boolean; inline;
    class operator LessThan(const A: BigInteger; const B: UInt64): Boolean; inline;
    class operator LessThan(const A: UInt64; const B: BigInteger): Boolean; inline;
    class operator LessThan(const A: BigInteger; const B: Int64): Boolean; inline;
    class operator LessThan(const A: Int64; const B: BigInteger): Boolean; inline;
    class operator LessThanOrEqual(const A: BigInteger; const B: UInt64): Boolean; inline;
    class operator LessThanOrEqual(const A: UInt64; const B: BigInteger): Boolean; inline;
    class operator LessThanOrEqual(const A: BigInteger; const B: Int64): Boolean; inline;
    class operator LessThanOrEqual(const A: Int64; const B: BigInteger): Boolean; inline;

    class function DivRem(const Dividend: BigInteger; const Divisor: Cardinal;
                          var Remainder: BigInteger): BigInteger; overload; static;
    class function DivRem(const Dividend: Cardinal; const Divisor: BigInteger;
                          var Remainder: Cardinal): BigInteger; overload; static;
    class function DivRem(const Dividend: BigInteger; const Divisor: Integer;
                          var Remainder: Integer): BigInteger; overload; static;
    class function DivRem(const Dividend: Integer; const Divisor: BigInteger;
                          var Remainder: Integer): Integer; overload; static;

    class operator Add(const A: BigInteger; const B: Cardinal): BigInteger;
    class operator Add(const A: Cardinal; const B: BigInteger): BigInteger;
    class operator Add(const A: BigInteger; const B: Integer): BigInteger;
    class operator Add(const A: Integer; const B: BigInteger): BigInteger;
    class operator Subtract(const A: BigInteger; const B: Cardinal): BigInteger;
    class operator Subtract(const A: Cardinal; const B: BigInteger): BigInteger;
    class operator Subtract(const A: BigInteger; const B: Integer): BigInteger;
    class operator Subtract(const A: Integer; const B: BigInteger): BigInteger;
    class operator Multiply(const A: BigInteger; const B: Cardinal): BigInteger;
    class operator Multiply(const A: Cardinal; const B: BigInteger): BigInteger;
    class operator Multiply(const A: BigInteger; const B: Integer): BigInteger;
    class operator Multiply(const A: Integer; const B: BigInteger): BigInteger;
  end;

type
  EBigNumberError = class(Exception)
  private
    FCode: TF_RESULT;
  public
    constructor Create(ACode: TF_RESULT; const Msg: string);
    property Code: TF_RESULT read FCode;
  end;

procedure BigNumberError(ACode: TF_RESULT; const Msg: string);

implementation

type
  TBigNumberFromUInt32 = function(var A: IBigNumber; Value: UInt32): TF_RESULT; stdcall;
  TBigNumberFromUInt64 = function(var A: IBigNumber; Value: UInt64): TF_RESULT; stdcall;
  TBigNumberFromInt32 = function(var A: IBigNumber; Value: Int32): TF_RESULT; stdcall;
  TBigNumberFromInt64 = function(var A: IBigNumber; Value: Int64): TF_RESULT; stdcall;
  TBigNumberFromPChar = function(var A: IBigNumber; P: PByte; L: Integer;
           CharSize: Integer; AllowNegative: Boolean; TwoCompl: Boolean): TF_RESULT; stdcall;
  TBigNumberFromPByte = function(var A: IBigNumber;
    P: PByte; L: Cardinal; AllowNegative: Boolean): TF_RESULT; stdcall;

var
  BigNumberFromUInt32: TBigNumberFromUInt32;
  BigNumberFromUInt64: TBigNumberFromUInt64;
  BigNumberFromInt32: TBigNumberFromInt32;
  BigNumberFromInt64: TBigNumberFromInt64;
  BigNumberFromPChar: TBigNumberFromPChar;
  BigNumberFromPByte: TBigNumberFromPByte;

{ EBigNumberError }

constructor EBigNumberError.Create(ACode: TF_RESULT; const Msg: string);
begin
  inherited Create(Msg);
  FCode:= ACode;
end;

procedure BigNumberError(ACode: TF_RESULT; const Msg: string);
begin
  raise EBigNumberError.Create(ACode, Msg);
end;

procedure HResCheck(Value: TF_RESULT; const ErrMsg: string); inline;
begin
  if Value <> S_OK then
    BigNumberError(Value, ErrMsg);
end;

{ BigCardinal }

function BigCardinal.ToString: string;
var
  BytesUsed: Integer;
  L, L1: Integer;
  P, P1: PByte;
  I: Integer;
  HR: TF_RESULT;

begin
  BytesUsed:= FNumber.GetSize;
// log(256) approximated from above by 41/17
  L:= (BytesUsed * 41) div 17 + 1;
  GetMem(P, L);
  try
    L1:= L;
    HR:= FNumber.ToDec(P, L1);
// -- kludge
    if HR = TF_E_INVALIDARG then begin
      FreeMem(P);
      L:= L1;
      GetMem(P, L);
      HR:= FNumber.ToDec(P, L1);
    end;
// -- end of kludge
    HResCheck(HR, 'BigCardinal -> string conversion error');
    SetLength(Result, L1);
    P1:= P;
    for I:= 1 to L1 do begin
      Result[I]:= Char(P1^);
      Inc(P1);
    end;
  finally
    FreeMem(P);
  end;
end;

function BigCardinal.ToHexString(Digits: Integer; const Prefix: string;
                         TwoCompl: Boolean): string;

var
  L, L1: Integer;
  P, P1: PByte;
  HR: TF_RESULT;
  I: Integer;

begin
  HR:= FNumber.ToHex(nil, L, TwoCompl);
  if HR = TF_E_INVALIDARG then begin
    GetMem(P, L);
    try
      L1:= L;
      HResCheck(FNumber.ToHex(P, L1, TwoCompl),
                       'BigCardinal -> hex string conversion error');
      if Digits < L1 then Digits:= L1;
      Inc(Digits, Length(Prefix));
      SetLength(Result, Digits);
      Move(Pointer(Prefix)^, Pointer(Result)^, Length(Prefix) * SizeOf(Char));
      P1:= P;
      I:= Length(Prefix);
      while I + L1 < Digits do begin
        Inc(I);
        Result[I]:= '0';
      end;
      while I < Digits do begin
        Inc(I);
        Result[I]:= Char(P1^);
        Inc(P1);
      end;
    finally
      FreeMem(P);
    end;
  end
  else
    BigNumberError(HR, 'BigCardinal -> hex string conversion error');
end;

function BigCardinal.ToBytes: TBytes;
var
  HR: TF_RESULT;
  L: Cardinal;

begin
  L:= 0;
  HR:= FNumber.ToPByte(nil, L);
  if (HR = TF_E_INVALIDARG) and (L > 0) then begin
    SetLength(Result, L);
    HR:= FNumber.ToPByte(Pointer(Result), L);
  end;
  HResCheck(HR, 'BigCardinal -> TBytes conversion error');
end;

function BigCardinal.TryParse(const S: string; TwoCompl: Boolean): Boolean;
begin
  Result:= BigNumberFromPChar(FNumber, Pointer(S), Length(S),
                              SizeOf(Char), False, TwoCompl) = TF_S_OK;
end;

procedure BigCardinal.Free;
begin
  FNumber:= nil;
end;

class function BigCardinal.Compare(const A, B: BigCardinal): Integer;
begin
  Result:= A.FNumber.CompareNumberU(B.FNumber);
end;

function BigCardinal.CompareTo(const B: BigCardinal): Integer;
begin
  Result:= Compare(Self, B);
end;

class function BigCardinal.Pow(const Base: BigCardinal; Value: Cardinal): BigCardinal;
begin
  HResCheck(Base.FNumber.PowU(Value, Result.FNumber), 'BigCardinal.Power');
end;

class function BigCardinal.DivRem(const Dividend, Divisor: BigCardinal;
                                  var Remainder: BigCardinal): BigCardinal;
begin
  HResCheck(Dividend.FNumber.DivRemNumberU(Divisor.FNumber,
            Result.FNumber, Remainder.FNumber),
            'BigCardinal.DivRem');
end;

class operator BigCardinal.Explicit(const Value: BigCardinal): Cardinal;
begin
  HResCheck(Value.FNumber.ToLimb(Result),
    'BigCardinal -> Cardinal conversion error');
end;

class operator BigCardinal.Explicit(const Value: BigCardinal): Integer;
begin
  HResCheck(Value.FNumber.ToIntLimb(Result),
    'BigCardinal -> Integer conversion error');
end;

class operator BigCardinal.Explicit(const Value: BigCardinal): UInt64;
begin
  HResCheck(Value.FNumber.ToDblLimb(Result),
    'BigCardinal -> UInt64 conversion error');
end;

class operator BigCardinal.Explicit(const Value: BigCardinal): Int64;
begin
  HResCheck(Value.FNumber.ToDblIntLimb(Result),
    'BigCardinal -> Int64 conversion error');
end;

class operator BigCardinal.Implicit(const Value: Cardinal): BigCardinal;
begin
  HResCheck(BigNumberFromUInt32(Result.FNumber, Value),
            'BigNumberFromLimb');
end;

class operator BigCardinal.Implicit(const Value: UInt64): BigCardinal;
begin
  HResCheck(BigNumberFromUInt64(Result.FNumber, Value),
            'BigNumberFromDblLimb');
end;

class operator BigCardinal.Explicit(const Value: Integer): BigCardinal;
begin
  if Value < 0 then
    BigNumberError(TF_E_INVALIDARG,
      'Integer -> BigCardinal conversion error')
  else begin
    HResCheck(BigNumberFromInt32(Result.FNumber, Value),
            'TBigNumber.FromInteger');
  end;
end;

class operator BigCardinal.Explicit(const Value: Int64): BigCardinal;
begin
  if Value < 0 then
    BigNumberError(TF_E_INVALIDARG,
      'Int64 -> BigCardinal conversion error')
  else begin
    HResCheck(BigNumberFromInt64(Result.FNumber, Value),
            'BigNumberFromDblIntLimb');
  end;
end;

class operator BigCardinal.Explicit(const Value: TBytes): BigCardinal;
begin
  HResCheck(BigNumberFromPByte(Result.FNumber,
            Pointer(Value), Length(Value), False),
    'TBytes -> BigCardinal conversion error');
end;

class operator BigCardinal.Explicit(const Value: string): BigCardinal;
begin
  HResCheck(BigNumberFromPChar(Result.FNumber, Pointer(Value), Length(Value),
                               SizeOf(Char), False, False),
    'string -> BigCardinal conversion error');
end;

class operator BigCardinal.Equal(const A, B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) = 0;
end;

class operator BigCardinal.NotEqual(const A, B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) <> 0;
end;

class operator BigCardinal.GreaterThan(const A, B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) > 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A, B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) >= 0;
end;

class operator BigCardinal.LessThan(const A, B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) < 0;
end;

class operator BigCardinal.LessThanOrEqual(const A, B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) <= 0;
end;

class operator BigCardinal.Add(const A, B: BigCardinal): BigCardinal;
begin
  HResCheck(A.FNumber.AddNumberU(B.FNumber, Result.FNumber),
            'BigCardinal.Add');
end;

class operator BigCardinal.Subtract(const A, B: BigCardinal): BigCardinal;
begin
  HResCheck(A.FNumber.SubNumberU(B.FNumber, Result.FNumber),
            'BigCardinal.Subtract');
end;

class operator BigCardinal.Multiply(const A, B: BigCardinal): BigCardinal;
begin
  HResCheck(A.FNumber.MulNumberU(B.FNumber, Result.FNumber),
            'BigCardinal.Multiply');
end;

class operator BigCardinal.IntDivide(const A, B: BigCardinal): BigCardinal;
var
  Remainder: IBigNumber;

begin
  HResCheck(A.FNumber.DivRemNumberU(B.FNumber, Result.FNumber, Remainder),
            'BigCardinal.IntDivide');
end;

class operator BigCardinal.Modulus(const A, B: BigCardinal): BigCardinal;
var
  Quotient: IBigNumber;

begin
  HResCheck(A.FNumber.DivRemNumberU(B.FNumber, Quotient, Result.FNumber),
            'BigCardinal.Modulus');
end;


class operator BigCardinal.LeftShift(const A: BigCardinal; Shift: Cardinal): BigCardinal;
begin
  HResCheck(A.FNumber.ShlNumber(Shift, Result.FNumber),
            'BigCardinal.Shl');
end;

class operator BigCardinal.RightShift(const A: BigCardinal; Shift: Cardinal): BigCardinal;
begin
  HResCheck(A.FNumber.ShrNumber(Shift, Result.FNumber),
            'BigCardinal.Shr');
end;

class operator BigCardinal.BitwiseAnd(const A, B: BigCardinal): BigCardinal;
begin
  HResCheck(A.FNumber.AndNumberU(B.FNumber, Result.FNumber),
            'BigCardinal.And');
end;

class operator BigCardinal.BitwiseOr(const A, B: BigCardinal): BigCardinal;
begin
  HResCheck(A.FNumber.OrNumberU(B.FNumber, Result.FNumber),
            'BigCardinal.Or');
end;

function BigCardinal.CompareToCard(const B: Cardinal): Integer;
begin
  Result:= FNumber.CompareToLimbU(B);
end;

function BigCardinal.CompareToInt(const B: Integer): Integer;
begin
  Result:= FNumber.CompareToIntLimbU(B);
end;

function BigCardinal.CompareTo(const B: Cardinal): Integer;
begin
  Result:= CompareToCard(B);
end;

function BigCardinal.CompareTo(const B: Integer): Integer;
begin
  Result:= CompareToInt(B);
end;

class operator BigCardinal.Equal(const A: BigCardinal; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) = 0;
end;

class operator BigCardinal.Equal(const A: Cardinal; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToCard(A) = 0;
end;

class operator BigCardinal.Equal(const A: BigCardinal; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) = 0;
end;

class operator BigCardinal.Equal(const A: Integer; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt(A) = 0;
end;

class operator BigCardinal.NotEqual(const A: BigCardinal; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) <> 0;
end;

class operator BigCardinal.NotEqual(const A: Cardinal; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToCard(A) <> 0;
end;

class operator BigCardinal.NotEqual(const A: BigCardinal; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) <> 0;
end;

class operator BigCardinal.NotEqual(const A: Integer; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt(A) <> 0;
end;

class operator BigCardinal.GreaterThan(const A: BigCardinal; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) > 0;
end;

class operator BigCardinal.GreaterThan(const A: Cardinal; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToCard(A) < 0;
end;

class operator BigCardinal.GreaterThan(const A: BigCardinal; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) > 0;
end;

class operator BigCardinal.GreaterThan(const A: Integer; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt(A) < 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: BigCardinal; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) >= 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: Cardinal; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToCard(A) <= 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: BigCardinal; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) >= 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: Integer; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt(A) <= 0;
end;

class operator BigCardinal.LessThan(const A: BigCardinal; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) < 0;
end;

class operator BigCardinal.LessThan(const A: Cardinal; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToCard(A) > 0;
end;

class operator BigCardinal.LessThan(const A: BigCardinal; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) < 0;
end;

class operator BigCardinal.LessThan(const A: Integer; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt(A) > 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: BigCardinal; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) <= 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: Cardinal; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToCard(A) >= 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: BigCardinal; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) <= 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: Integer; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt(A) >= 0;
end;

{--- Comparison with 64-bit integers ---}

function BigCardinal.CompareToUInt64(const B: UInt64): Integer;
begin
  Result:= FNumber.CompareToDblLimbU(B);
end;

function BigCardinal.CompareToInt64(const B: Int64): Integer;
begin
  Result:= FNumber.CompareToDblIntLimbU(B);
end;

function BigCardinal.CompareTo(const B: UInt64): Integer;
begin
  Result:= CompareToUInt64(B);
end;

function BigCardinal.CompareTo(const B: Int64): Integer;
begin
  Result:= CompareToInt64(B);
end;

class operator BigCardinal.Equal(const A: BigCardinal; const B: UInt64): Boolean;
begin
  Result:= A.CompareToUInt64(B) = 0;
end;

class operator BigCardinal.Equal(const A: UInt64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToUInt64(A) = 0;
end;

class operator BigCardinal.Equal(const A: BigCardinal; const B: Int64): Boolean;
begin
  Result:= A.CompareToInt64(B) = 0;
end;

class operator BigCardinal.Equal(const A: Int64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt64(A) = 0;
end;

class operator BigCardinal.NotEqual(const A: BigCardinal; const B: UInt64): Boolean;
begin
  Result:= A.CompareToUInt64(B) <> 0;
end;

class operator BigCardinal.NotEqual(const A: UInt64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToUInt64(A) <> 0;
end;

class operator BigCardinal.NotEqual(const A: BigCardinal; const B: Int64): Boolean;
begin
  Result:= A.CompareToInt64(B) <> 0;
end;

class operator BigCardinal.NotEqual(const A: Int64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt64(A) <> 0;
end;

class operator BigCardinal.GreaterThan(const A: BigCardinal; const B: UInt64): Boolean;
begin
  Result:= A.CompareToUInt64(B) > 0;
end;

class operator BigCardinal.GreaterThan(const A: UInt64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToUInt64(A) < 0;
end;

class operator BigCardinal.GreaterThan(const A: BigCardinal; const B: Int64): Boolean;
begin
  Result:= A.CompareToInt64(B) > 0;
end;

class operator BigCardinal.GreaterThan(const A: Int64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt64(A) < 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: BigCardinal; const B: UInt64): Boolean;
begin
  Result:= A.CompareToUInt64(B) >= 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: UInt64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToUInt64(A) <= 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: BigCardinal; const B: Int64): Boolean;
begin
  Result:= A.CompareToInt64(B) >= 0;
end;

class operator BigCardinal.GreaterThanOrEqual(const A: Int64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt64(A) <= 0;
end;

class operator BigCardinal.LessThan(const A: BigCardinal; const B: UInt64): Boolean;
begin
  Result:= A.CompareToUInt64(B) < 0;
end;

class operator BigCardinal.LessThan(const A: UInt64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToUInt64(A) > 0;
end;

class operator BigCardinal.LessThan(const A: BigCardinal; const B: Int64): Boolean;
begin
  Result:= A.CompareToInt64(B) < 0;
end;

class operator BigCardinal.LessThan(const A: Int64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt64(A) > 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: BigCardinal; const B: UInt64): Boolean;
begin
  Result:= A.CompareToUInt64(B) <= 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: UInt64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToUInt64(A) >= 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: BigCardinal; const B: Int64): Boolean;
begin
  Result:= A.CompareToInt64(B) <= 0;
end;

class operator BigCardinal.LessThanOrEqual(const A: Int64; const B: BigCardinal): Boolean;
begin
  Result:= B.CompareToInt64(A) >= 0;
end;



class operator BigCardinal.Add(const A: BigCardinal; const B: Cardinal): BigCardinal;
begin
  HResCheck(A.FNumber.AddLimbU(B, Result.FNumber),
            'BigCardinal.AddLimbU');
end;

class operator BigCardinal.Add(const A: Cardinal; const B: BigCardinal): BigCardinal;
begin
  HResCheck(B.FNumber.AddLimbU(A, Result.FNumber),
            'BigCardinal.AddLimbU');
end;

class operator BigCardinal.Subtract(const A: BigCardinal; const B: Cardinal): BigCardinal;
begin
  HResCheck(A.FNumber.SubLimbU(B, Result.FNumber),
            'BigCardinal.SubLimbU');
end;

class operator BigCardinal.Subtract(const A: Cardinal; const B: BigCardinal): Cardinal;
begin
  HResCheck(B.FNumber.SubLimbU2(A, Result),
            'BigCardinal.SubLimbU2');
end;

class operator BigCardinal.Multiply(const A: BigCardinal; const B: Cardinal): BigCardinal;
begin
  HResCheck(A.FNumber.MulLimbU(B, Result.FNumber),
            'BigCardinal.MulLimbU');
end;

class operator BigCardinal.Multiply(const A: Cardinal; const B: BigCardinal): BigCardinal;
begin
  HResCheck(B.FNumber.MulLimbU(A, Result.FNumber),
            'BigCardinal.MulLimbU');
end;


class function BigCardinal.DivRem(const Dividend: BigCardinal;
               Divisor: Cardinal; var Remainder: Cardinal): BigCardinal;
begin
  HResCheck(Dividend.FNumber.DivRemLimbU(Divisor, Result.FNumber, Remainder),
            'BigCardinal.DivRemLimbU');
end;

class function BigCardinal.DivRem(const Dividend: Cardinal;
               Divisor: BigCardinal; var Remainder: Cardinal): Cardinal;
begin
  HResCheck(Divisor.FNumber.DivRemLimbU2(Dividend, Result, Remainder),
            'BigCardinal.DivRemLimbU2');
end;

class operator BigCardinal.IntDivide(const A: BigCardinal; const B: Cardinal): BigCardinal;
var
  Remainder: Cardinal;

begin
  HResCheck(A.FNumber.DivRemLimbU(B, Result.FNumber, Remainder),
            'BigCardinal.IntDivide');
end;

class operator BigCardinal.IntDivide(const A: Cardinal; const B: BigCardinal): Cardinal;
var
  Remainder: Cardinal;

begin
  HResCheck(B.FNumber.DivRemLimbU2(A, Result, Remainder),
            'BigCardinal.IntDivide');
end;

class operator BigCardinal.Modulus(const A: BigCardinal; const B: Cardinal): Cardinal;
var
  Quotient: IBigNumber;

begin
  HResCheck(A.FNumber.DivRemLimbU(B, Quotient, Result),
            'BigCardinal.Modulus');
end;


class operator BigCardinal.Modulus(const A: Cardinal; const B: BigCardinal): Cardinal;
var
  Quotient: Cardinal;

begin
  HResCheck(B.FNumber.DivRemLimbU2(A, Quotient, Result),
            'BigCardinal.Modulus');
end;

{ -------------------------- BigInteger -------------------------- }

function BigInteger.GetSign: Integer;
begin
  Result:= FNumber.GetSign;
end;

function BigInteger.ToString: string;
var
  BytesUsed: Integer;
  L, L1: Integer;
  P, P1: PByte;
  I: Integer;
  IsMinus: Boolean;
  HR: TF_RESULT;

begin
  BytesUsed:= FNumber.GetSize;
// log(256) approximated from above by 41/17
  L:= (BytesUsed * 41) div 17 + 1;
  GetMem(P, L);
  try
    L1:= L;
    HR:= FNumber.ToDec(P, L1);
// -- kludge
    if HR = TF_E_INVALIDARG then begin
      FreeMem(P);
      L:= L1;
      GetMem(P, L);
      HR:= FNumber.ToDec(P, L1);
    end;
// -- end of kludge
    HResCheck(HR, 'BigInteger -> string conversion error');
    IsMinus:= GetSign < 0;
    if IsMinus then Inc(L1);
    SetLength(Result, L1);
    I:= 1;
    if IsMinus then begin
      Result[1]:= '-';
      Inc(I);
    end;
    P1:= P;
    while I <= L1 do begin
      Result[I]:= Char(P1^);
      Inc(P1);
      Inc(I);
    end;
  finally
    FreeMem(P);
  end;
end;

function BigInteger.ToHexString(Digits: Integer; const Prefix: string;
                                TwoCompl: Boolean): string;
const
  ASCII_8 = 56;   // Ord('8')

var
  L, L1: Integer;
  P, P1: PByte;
  HR: TF_RESULT;
  Filler: Char;
  I: Integer;

begin
  Result:= '';
  HR:= FNumber.ToHex(nil, L, TwoCompl);
  if HR = TF_E_INVALIDARG then begin
    GetMem(P, L);
    try
      L1:= L;
      HResCheck(FNumber.ToHex(P, L1, TwoCompl),
                       'BigInteger -> hex string conversion error');
      if Digits < L1 then Digits:= L1;
      I:= 1;
      if (FNumber.GetSign < 0) and not TwoCompl then begin
        Inc(I);
        SetLength(Result, Digits + Length(Prefix) + 1);
        Result[1]:= '-';
      end
      else
        SetLength(Result, Digits + Length(Prefix));
      Move(Pointer(Prefix)^, Result[I], Length(Prefix) * SizeOf(Char));
      Inc(I, Length(Prefix));
      if Digits > L1 then begin
        if TwoCompl and (P[L1] >= ASCII_8) then Filler:= 'F'
        else Filler:= '0';
        while I + L1 <= Length(Result) do begin
          Result[I]:= Filler;
          Inc(I);
        end;
      end;
      P1:= P;
      while I <= Length(Result) do begin
        Result[I]:= Char(P1^);
        Inc(I);
        Inc(P1);
      end;
    finally
      FreeMem(P);
    end;
  end
  else
    BigNumberError(HR, 'BigInteger -> hex string conversion error');
end;

function BigInteger.ToBytes: TBytes;
var
  HR: TF_RESULT;
  L: Cardinal;

begin
  L:= 0;
  HR:= FNumber.ToPByte(nil, L);
  if (HR = TF_E_INVALIDARG) and (L > 0) then begin
    SetLength(Result, L);
    HR:= FNumber.ToPByte(Pointer(Result), L);
  end;
  HResCheck(HR, 'BigInteger -> TBytes conversion error');
end;

function BigInteger.TryParse(const S: string; TwoCompl: Boolean): Boolean;
begin
  Result:= BigNumberFromPChar(FNumber, Pointer(S), Length(S),
                              SizeOf(Char), True, TwoCompl) = TF_S_OK;
//  Result:= BigNumberFromPWideChar(FNumber, Pointer(S), Length(S),
//              True) = TF_S_OK;
end;

procedure BigInteger.Free;
begin
  FNumber:= nil;
end;

class function BigInteger.Compare(const A, B: BigInteger): Integer;
begin
  Result:= A.FNumber.CompareNumber(B.FNumber);
end;

class function BigInteger.Compare(const A: BigInteger; const B: BigCardinal): Integer;
begin
  Result:= A.FNumber.CompareNumber(B.FNumber);
end;

class function BigInteger.Compare(const A: BigCardinal; const B: BigInteger): Integer;
begin
  Result:= A.FNumber.CompareNumber(B.FNumber);
end;

function BigInteger.CompareTo(const B: BigInteger): Integer;
begin
  Result:= Compare(Self, B);
end;

function BigInteger.CompareTo(const B: BigCardinal): Integer;
begin
  Result:= Compare(Self, B);
end;

class function BigInteger.Abs(const A: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.AbsNumber(Result.FNumber), 'BigInteger.Abs');
end;

class function BigInteger.Pow(const Base: BigInteger; Value: Cardinal): BigInteger;
begin
  HResCheck(Base.FNumber.Pow(Value, Result.FNumber),
                        'BigInteger.Power');
end;

class function BigInteger.DivRem(const Dividend, Divisor: BigCardinal;
               var Remainder: BigCardinal): BigCardinal;
begin
  HResCheck(Dividend.FNumber.DivRemNumber(Divisor.FNumber,
            Result.FNumber, Remainder.FNumber),
            'BigInteger.DivRem');
end;

class operator BigInteger.Implicit(const Value: BigCardinal): BigInteger;
begin
  Result.FNumber:= Value.FNumber;
end;

class operator BigInteger.Explicit(const Value: BigInteger): BigCardinal;
begin
  if (Value.FNumber.GetSign < 0) then
      BigNumberError(TF_E_INVALIDARG, 'Negative value');
  Result.FNumber:= Value.FNumber;
end;

class operator BigInteger.Explicit(const Value: BigInteger): Cardinal;
begin
  HResCheck(Value.FNumber.ToLimb(Result),
    'BigInteger -> UInt32 conversion error');
end;

class operator BigInteger.Explicit(const Value: BigInteger): UInt64;
begin
  HResCheck(Value.FNumber.ToDblLimb(Result),
    'BigInteger -> UInt64 conversion error');
end;

class operator BigInteger.Explicit(const Value: BigInteger): Integer;
begin
  HResCheck(Value.FNumber.ToIntLimb(Result),
    'BigInteger -> Int32 conversion error');
end;

class operator BigInteger.Explicit(const Value: BigInteger): Int64;
begin
  HResCheck(Value.FNumber.ToDblIntLimb(Result),
    'BigInteger -> Int64 conversion error');
end;

class operator BigInteger.Implicit(const Value: UInt32): BigInteger;
begin
  HResCheck(BigNumberFromUInt32(Result.FNumber, Value),
            'BigNumberFromLimb');
end;

class operator BigInteger.Implicit(const Value: UInt64): BigInteger;
begin
  HResCheck(BigNumberFromUInt64(Result.FNumber, Value),
            'BigNumberFromDblLimb');
end;

class operator BigInteger.Implicit(const Value: Int32): BigInteger;
begin
  HResCheck(BigNumberFromInt32(Result.FNumber, Value),
            'BigNumberFromIntLimb');
end;

class operator BigInteger.Implicit(const Value: Int64): BigInteger;
begin
  HResCheck(BigNumberFromInt64(Result.FNumber, Value),
            'BigNumberFromDblIntLimb');
end;

class operator BigInteger.Explicit(const Value: TBytes): BigInteger;
begin
  HResCheck(BigNumberFromPByte(Result.FNumber,
            Pointer(Value), Length(Value), True),
            'TBytes -> BigInteger conversion error');
end;

class operator BigInteger.Explicit(const Value: string): BigInteger;
begin
//  HResCheck(BigNumberFromPWideChar(Result.FNumber, Pointer(Value),
//            Length(Value), True),
  HResCheck(BigNumberFromPChar(Result.FNumber, Pointer(Value), Length(Value),
                               SizeOf(Char), True, False),
            'string -> BigInteger conversion error');
end;

class operator BigInteger.Equal(const A, B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) = 0;
end;

class operator BigInteger.Equal(const A: BigCardinal; const B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) = 0;
end;

class operator BigInteger.Equal(const A: BigInteger; const B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) = 0;
end;

class operator BigInteger.NotEqual(const A, B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) <> 0;
end;

class operator BigInteger.NotEqual(const A: BigCardinal; const B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) <> 0;
end;

class operator BigInteger.NotEqual(const A: BigInteger; const B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) <> 0;
end;

class operator BigInteger.GreaterThan(const A, B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) > 0;
end;

class operator BigInteger.GreaterThan(const A: BigInteger; const B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) > 0;
end;

class operator BigInteger.GreaterThan(const A: BigCardinal; const B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) > 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A, B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) >= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: BigInteger; const B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) >= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: BigCardinal; const B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) >= 0;
end;

class operator BigInteger.LessThan(const A, B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) < 0;
end;

class operator BigInteger.LessThan(const A: BigInteger; const B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) < 0;
end;

class operator BigInteger.LessThan(const A: BigCardinal; const B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) < 0;
end;

class operator BigInteger.LessThanOrEqual(const A, B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) <= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: BigInteger; const B: BigCardinal): Boolean;
begin
  Result:= Compare(A, B) <= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: BigCardinal; const B: BigInteger): Boolean;
begin
  Result:= Compare(A, B) <= 0;
end;

class operator BigInteger.Add(const A, B: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.AddNumber(B.FNumber, Result.FNumber), 'BigInteger.Add');
end;

class operator BigInteger.Subtract(const A, B: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.SubNumber(B.FNumber, Result.FNumber), 'BigInteger.Subtract');
end;

class operator BigInteger.Multiply(const A, B: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.MulNumber(B.FNumber, Result.FNumber), 'BigInteger.Multiply');
end;

class operator BigInteger.IntDivide(const A, B: BigInteger): BigInteger;
var
  Remainder: IBigNumber;

begin
  HResCheck(A.FNumber.DivRemNumber(B.FNumber, Result.FNumber, Remainder),
            'BigInteger.IntDivide');
end;

class operator BigInteger.Modulus(const A, B: BigInteger): BigInteger;
var
  Quotient: IBigNumber;

begin
  HResCheck(A.FNumber.DivRemNumber(B.FNumber, Quotient, Result.FNumber),
            'BigInteger.Modulus');
end;

class operator BigInteger.LeftShift(const A: BigInteger; Shift: Cardinal): BigInteger;
begin
  HResCheck(A.FNumber.ShlNumber(Shift, Result.FNumber),
   'BigInteger.Shl');
end;

class operator BigInteger.RightShift(const A: BigInteger; Shift: Cardinal): BigInteger;
begin
  HResCheck(A.FNumber.ShrNumber(Shift, Result.FNumber),
   'BigInteger.Shr');
end;

class operator BigInteger.BitwiseAnd(const A, B: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.AndNumber(B.FNumber, Result.FNumber),
                       'BigInteger.And');
end;

class operator BigInteger.BitwiseOr(const A, B: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.OrNumber(B.FNumber, Result.FNumber),
                       'BigInteger.Or');
end;

class operator BigInteger.BitwiseXor(const A, B: BigInteger): BigInteger;
begin
  HResCheck(A.FNumber.XorNumber(B.FNumber, Result.FNumber),
                       'BigInteger.Xor');
end;

function BigInteger.CompareToCard(const B: Cardinal): Integer;
begin
  Result:= FNumber.CompareToLimb(B);
end;

function BigInteger.CompareToInt(const B: Integer): Integer;
begin
  Result:= FNumber.CompareToIntLimb(B);
end;

function BigInteger.CompareTo(const B: Cardinal): Integer;
begin
  Result:= CompareToCard(B);
end;

function BigInteger.CompareTo(const B: Integer): Integer;
begin
  Result:= CompareToInt(B);
end;

class operator BigInteger.Equal(const A: BigInteger; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) = 0;
end;

class operator BigInteger.Equal(const A: Cardinal; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToCard(A) = 0;
end;

class operator BigInteger.Equal(const A: BigInteger; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) = 0;
end;

class operator BigInteger.Equal(const A: Integer; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToInt(A) = 0;
end;

class operator BigInteger.NotEqual(const A: BigInteger; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) <> 0;
end;

class operator BigInteger.NotEqual(const A: Cardinal; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToCard(A) <> 0;
end;

class operator BigInteger.NotEqual(const A: BigInteger; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) <> 0;
end;

class operator BigInteger.NotEqual(const A: Integer; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToInt(A) <> 0;
end;

class operator BigInteger.GreaterThan(const A: BigInteger; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) > 0;
end;

class operator BigInteger.GreaterThan(const A: Cardinal; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToCard(A) < 0;
end;

class operator BigInteger.GreaterThan(const A: BigInteger; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) > 0;
end;

class operator BigInteger.GreaterThan(const A: Integer; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToInt(A) < 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: BigInteger; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) >= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: Cardinal; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToCard(A) <= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: BigInteger; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) >= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: Integer; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToInt(A) <= 0;
end;

class operator BigInteger.LessThan(const A: BigInteger; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) < 0;
end;

class operator BigInteger.LessThan(const A: Cardinal; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToCard(A) > 0;
end;

class operator BigInteger.LessThan(const A: BigInteger; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) < 0;
end;

class operator BigInteger.LessThan(const A: Integer; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToInt(A) > 0;
end;

class operator BigInteger.LessThanOrEqual(const A: BigInteger; const B: Cardinal): Boolean;
begin
  Result:= A.CompareToCard(B) <= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: Cardinal; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToCard(A) >= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: BigInteger; const B: Integer): Boolean;
begin
  Result:= A.CompareToInt(B) <= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: Integer; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToInt(A) >= 0;
end;


function BigInteger.CompareToDoubleUInt(const B: UInt64): Integer;
begin
  Result:= FNumber.CompareToDblLimb(B);
end;

function BigInteger.CompareToDoubleInt(const B: Int64): Integer;
begin
  Result:= FNumber.CompareToDblIntLimb(B);
end;

function BigInteger.CompareTo(const B: UInt64): Integer;
begin
  Result:= CompareToDoubleUInt(B);
end;

function BigInteger.CompareTo(const B: Int64): Integer;
begin
  Result:= CompareToDoubleInt(B);
end;

class operator BigInteger.Equal(const A: BigInteger; const B: UInt64): Boolean;
begin
  Result:= A.CompareToDoubleUInt(B) = 0;
end;

class operator BigInteger.Equal(const A: UInt64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleUInt(A) = 0;
end;

class operator BigInteger.Equal(const A: BigInteger; const B: Int64): Boolean;
begin
  Result:= A.CompareToDoubleInt(B) = 0;
end;

class operator BigInteger.Equal(const A: Int64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleInt(A) = 0;
end;

class operator BigInteger.NotEqual(const A: BigInteger; const B: UInt64): Boolean;
begin
  Result:= A.CompareToDoubleUInt(B) <> 0;
end;

class operator BigInteger.NotEqual(const A: UInt64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleUInt(A) <> 0;
end;

class operator BigInteger.NotEqual(const A: BigInteger; const B: Int64): Boolean;
begin
  Result:= A.CompareToDoubleInt(B) <> 0;
end;

class operator BigInteger.NotEqual(const A: Int64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleInt(A) <> 0;
end;

class operator BigInteger.GreaterThan(const A: BigInteger; const B: UInt64): Boolean;
begin
  Result:= A.CompareToDoubleUInt(B) > 0;
end;

class operator BigInteger.GreaterThan(const A: UInt64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleUInt(A) < 0;
end;

class operator BigInteger.GreaterThan(const A: BigInteger; const B: Int64): Boolean;
begin
  Result:= A.CompareToDoubleInt(B) > 0;
end;

class operator BigInteger.GreaterThan(const A: Int64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleInt(A) < 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: BigInteger; const B: UInt64): Boolean;
begin
  Result:= A.CompareToDoubleUInt(B) >= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: UInt64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleUInt(A) <= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: BigInteger; const B: Int64): Boolean;
begin
  Result:= A.CompareToDoubleInt(B) >= 0;
end;

class operator BigInteger.GreaterThanOrEqual(const A: Int64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleInt(A) <= 0;
end;

class operator BigInteger.LessThan(const A: BigInteger; const B: UInt64): Boolean;
begin
  Result:= A.CompareToDoubleUInt(B) < 0;
end;

class operator BigInteger.LessThan(const A: UInt64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleUInt(A) > 0;
end;

class operator BigInteger.LessThan(const A: BigInteger; const B: Int64): Boolean;
begin
  Result:= A.CompareToDoubleInt(B) < 0;
end;

class operator BigInteger.LessThan(const A: Int64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleInt(A) > 0;
end;

class operator BigInteger.LessThanOrEqual(const A: BigInteger; const B: UInt64): Boolean;
begin
  Result:= A.CompareToDoubleUInt(B) <= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: UInt64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleUInt(A) >= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: BigInteger; const B: Int64): Boolean;
begin
  Result:= A.CompareToDoubleInt(B) <= 0;
end;

class operator BigInteger.LessThanOrEqual(const A: Int64; const B: BigInteger): Boolean;
begin
  Result:= B.CompareToDoubleInt(A) >= 0;
end;

class function BigInteger.DivRem(const Dividend: BigInteger;
               const Divisor: Cardinal; var Remainder: BigInteger): BigInteger;
begin
  HResCheck(Dividend.FNumber.DivRemLimb(Divisor, Result.FNumber, Remainder.FNumber),
            'BigCardinal.DivRemLimb');
end;

class function BigInteger.DivRem(const Dividend: Cardinal;
               const Divisor: BigInteger; var Remainder: Cardinal): BigInteger;
begin
  HResCheck(Divisor.FNumber.DivRemLimb2(Dividend, Result.FNumber, Remainder),
            'BigCardinal.DivRemLimb2');
end;

class function BigInteger.DivRem(const Dividend: BigInteger;
               const Divisor: Integer; var Remainder: Integer): BigInteger;
begin
  HResCheck(Dividend.FNumber.DivRemIntLimb(Divisor, Result.FNumber, Remainder),
            'BigCardinal.DivRemIntLimb');
end;

class function BigInteger.DivRem(const Dividend: Integer;
               const Divisor: BigInteger; var Remainder: Integer): Integer;
begin
  HResCheck(Divisor.FNumber.DivRemIntLimb2(Dividend, Result, Remainder),
            'BigCardinal.DivRemIntLimb2');
end;


class operator BigInteger.Add(const A: BigInteger; const B: Cardinal): BigInteger;
begin
  HResCheck(A.FNumber.AddLimb(B, Result.FNumber),
            'BigCardinal.AddLimb');
end;

class operator BigInteger.Add(const A: Cardinal; const B: BigInteger): BigInteger;
begin
  HResCheck(B.FNumber.AddLimb(A, Result.FNumber),
            'BigCardinal.AddLimb');
end;

class operator BigInteger.Add(const A: BigInteger; const B: Integer): BigInteger;
begin
  HResCheck(A.FNumber.AddIntLimb(B, Result.FNumber),
           'BigInteger.AddIntLimb');
end;

class operator BigInteger.Add(const A: Integer; const B: BigInteger): BigInteger;
begin
  HResCheck(B.FNumber.AddIntLimb(A, Result.FNumber),
            'BigInteger.AddIntLimb');
end;

class operator BigInteger.Subtract(const A: BigInteger; const B: Cardinal): BigInteger;
begin
  HResCheck(A.FNumber.SubLimb(B, Result.FNumber),
            'BigInteger.Subtract');
end;

class operator BigInteger.Subtract(const A: Cardinal; const B: BigInteger): BigInteger;
begin
  HResCheck(B.FNumber.SubLimb2(A, Result.FNumber),
            'BigInteger.Subtract');
end;

class operator BigInteger.Subtract(const A: BigInteger; const B: Integer): BigInteger;
begin
  HResCheck(A.FNumber.SubIntLimb(B, Result.FNumber),
            'BigInteger.Subtract');
end;

class operator BigInteger.Subtract(const A: Integer; const B: BigInteger): BigInteger;
begin
  HResCheck(B.FNumber.SubIntLimb2(A, Result.FNumber),
            'BigInteger.Subtract');
end;

class operator BigInteger.Multiply(const A: BigInteger; const B: Cardinal): BigInteger;
begin
  HResCheck(A.FNumber.MulLimb(B, Result.FNumber),
            'BigInteger.MulLimb');
end;

class operator BigInteger.Multiply(const A: Cardinal; const B: BigInteger): BigInteger;
begin
  HResCheck(B.FNumber.MulLimb(A, Result.FNumber),
            'BigInteger.MulLimb');
end;

class operator BigInteger.Multiply(const A: BigInteger; const B: Integer): BigInteger;
begin
  HResCheck(A.FNumber.MulIntLimb(B, Result.FNumber),
            'BigInteger.MulIntLimb');
end;

class operator BigInteger.Multiply(const A: Integer; const B: BigInteger): BigInteger;
begin
  HResCheck(B.FNumber.MulIntLimb(A, Result.FNumber),
            'BigInteger.MulIntLimb');
end;


// -------------------------------------------------------------- //

function BigNumberFrom32Stub(var A: IBigNumber; Value: UInt32): TF_RESULT; stdcall;
begin
  Result:= TF_E_LOADERROR;
end;

function BigNumberFrom64Stub(var A: IBigNumber; Value: UInt64): TF_RESULT; stdcall;
begin
  Result:= TF_E_LOADERROR;
end;

function BigNumberFromPCharStub(var A: IBigNumber; P: PByte; L: Integer;
           CharSize: Integer; AllowNegative: Boolean; TwoCompl: Boolean): TF_RESULT; stdcall;
begin
  Result:= TF_E_LOADERROR;
end;

function BigNumberFromPByteStub(var A: IBigNumber;
           P: PByte; L: Cardinal; AllowNegative: Boolean): TF_RESULT; stdcall;
begin
  Result:= TF_E_LOADERROR;
end;

const
{$IFDEF WIN64}
  LibName = 'numerics64.dll';
{$ELSE}
  LibName = 'numerics32.dll';
{$ENDIF}

var
  LibHandle: THandle = 0;

function LoadLib: Boolean;
begin
  if LibHandle <> 0 then begin
    Result:= True;
    Exit;
  end;
  Result:= False;
  LibHandle:= LoadLibrary(LibName);
  if LibHandle <> 0 then begin
    @BigNumberFromUInt32:= GetProcAddress(LibHandle, 'BigNumberFromLimb');
    @BigNumberFromUInt64:= GetProcAddress(LibHandle, 'BigNumberFromDblLimb');
    @BigNumberFromInt32:= GetProcAddress(LibHandle, 'BigNumberFromIntLimb');
    @BigNumberFromInt64:= GetProcAddress(LibHandle, 'BigNumberFromDblIntLimb');
    @BigNumberFromPChar:= GetProcAddress(LibHandle, 'BigNumberFromPChar');
    @BigNumberFromPByte:= GetProcAddress(LibHandle, 'BigNumberFromPByte');
    Result:= (@BigNumberFromUInt32 <> nil)
             and (@BigNumberFromUInt64 <> nil)
             and (@BigNumberFromInt32 <> nil)
             and (@BigNumberFromInt64 <> nil)
             and (@BigNumberFromPChar <> nil)
             and (@BigNumberFromPByte <> nil)
  end;
  if not Result then begin
    @BigNumberFromUInt32:= @BigNumberFrom32Stub;
    @BigNumberFromUInt64:= @BigNumberFrom64Stub;
    @BigNumberFromInt32:= @BigNumberFrom32Stub;
    @BigNumberFromInt64:= @BigNumberFrom64Stub;
    @BigNumberFromPChar:= @BigNumberFromPCharStub;
    @BigNumberFromPByte:= @BigNumberFromPByteStub;
  end;
end;

initialization
  LoadLib;

end.

Комментариев нет:

Отправить комментарий

Поделитесь с друзьями!

 

Подписчики

Статистика