See More

unit uIntX; {$I ..\Include\IntXLib.inc} interface uses Math, SysUtils, {$IFDEF DEBUG} SyncObjs, {$ENDIF DEBUG} uIntXGlobalSettings, uIntXSettings, uEnums, uStrings, uIntXLibTypes; type ///

/// numeric record which represents arbitrary-precision integers. /// TIntX = record /// /// big integer digits. /// _digits: TIntXLibUInt32Array; /// /// big integer digits length. /// _length: UInt32; /// /// big integer sign ("-" if true). /// _negative: Boolean; /// /// used to check if was Zero Initialized. /// _zeroinithelper: Boolean; class var /// /// instance of . /// _globalSettings: TIntXGlobalSettings; /// /// instance of . /// _settings: TIntXSettings; /// /// used in . /// _FS: TFormatSettings; {$IFDEF DEBUG} /// /// Critical Section for maximal error during FHT rounding (debug-mode only). /// _maxFhtRoundErrorCriticalSection: TCriticalSection; /// /// Maximal error during FHT rounding (debug-mode only). /// MaxFhtRoundError: Double; {$ENDIF DEBUG} strict private /// /// instance settings getter and setter. /// function GetSettings: TIntXSettings; procedure SetSettings(value: TIntXSettings); /// /// isodd getter. /// function GetIsOdd: Boolean; /// /// isNegative getter. /// function GetIsNegative: Boolean; /// /// isZero getter. /// function GetIsZero: Boolean; /// /// isOne getter. /// function GetIsOne: Boolean; /// /// IsPowerOfTwo getter. /// function GetIsPowerOfTwo: Boolean; /// /// Getter function for /// function GetClone: TIntX; /// /// Getter function for /// class function GetZero: TIntX; static; /// /// Getter function for /// class function GetOne: TIntX; static; /// /// Getter function for /// class function GetMinusOne: TIntX; static; /// /// Getter function for /// class function GetTen: TIntX; static; /// /// Getter function for /// class function GetGlobalSettings: TIntXGlobalSettings; static; /// /// Initializes record instance from zero. /// For internal use. /// procedure InitFromZero(); /// /// Initializes record instance from value. /// Doesn't initialize sign. /// For internal use. /// /// Unsigned Int64 value. procedure InitFromUlong(value: UInt64); /// /// Initializes record instance from another value. /// For internal use. /// /// TIntX value. procedure InitFromIntX(value: TIntX); /// /// Initializes record instance from digits array. /// For internal use. /// /// Big integer digits. /// Big integer sign. /// Big integer length. procedure InitFromDigits(digits: TIntXLibUInt32Array; negative: Boolean; mlength: UInt32); public /// /// instance settings property. /// property Settings: TIntXSettings read GetSettings write SetSettings; /// /// Gets flag indicating if big integer is odd. /// property IsOdd: Boolean read GetIsOdd; /// /// Gets flag indicating if big integer is negative. /// property IsNegative: Boolean read GetIsNegative; /// /// Gets flag indicating if big integer is zero. /// property IsZero: Boolean read GetIsZero; /// /// Gets flag indicating if big integer is one. /// property IsOne: Boolean read GetIsOne; /// /// Gets flag indicating if big integer is a power of two. /// property IsPowerOfTwo: Boolean read GetIsPowerOfTwo; /// /// Returns a copy of the current , with a unique copy of the data. /// property Clone: TIntX read GetClone; /// /// A Zero. /// class property Zero: TIntX read GetZero; /// /// A Positive One. /// class property One: TIntX read GetOne; /// /// A Negative One. /// class property MinusOne: TIntX read GetMinusOne; /// /// A Ten. /// class property Ten: TIntX read GetTen; /// /// global settings. /// class property GlobalSettings: TIntXGlobalSettings read GetGlobalSettings; // -- Class Constructor and Destructor -- class constructor Create(); class destructor Destroy(); // -- Constructors -- /// /// Creates new big integer from integer value. /// /// Integer value to create big integer from. constructor Create(value: Integer); overload; /// /// Creates new big integer from unsigned integer value. /// /// Unsigned integer value to create big integer from. constructor Create(value: UInt32); overload; /// /// Creates new big integer from Int64 value. /// /// Int64 value to create big integer from. constructor Create(value: Int64); overload; /// /// Creates new big integer from unsigned Int64 value. /// /// Unsigned Int64 value to create big integer from. constructor Create(value: UInt64); overload; /// /// Creates new big integer from a Double value. /// replicates Microsoft Double to BigInteger Implementation. /// /// /// Double value to create big integer from. /// constructor Create(value: Double); overload; /// /// Creates new big integer from array of it's "digits". /// Digit with lower index has less weight. /// /// Array of digits. /// True if this number is negative. /// is a null reference. constructor Create(digits: TIntXLibUInt32Array; negative: Boolean); overload; /// /// Creates new from string. /// /// Number as string. constructor Create(const value: String); overload; /// /// Creates new from string. /// /// Number as string. /// Number base. constructor Create(const value: String; numberBase: UInt32); overload; /// /// Copy constructor. /// /// Value to copy from. /// is a null reference. constructor Create(value: TIntX); overload; /// /// Creates new empty big integer with desired sign and length. /// /// For internal use. /// /// Desired digits length. /// Desired integer sign. constructor Create(mlength: UInt32; negative: Boolean); overload; /// /// Creates new big integer from array of it's "digits" but with given length. /// Digit with lower index has less weight. /// /// For internal use. /// /// Array of digits. /// True if this number is negative. /// Length to use for internal digits array. /// is a null reference. constructor Create(digits: TIntXLibUInt32Array; negative: Boolean; mlength: UInt32); overload; // -- Operators as functions and some other special mathematical functions -- /// /// Multiplies one object by another. /// /// First big integer. /// Second big integer. /// Multiply mode set explicitly. /// Multiply result. class function Multiply(int1: TIntX; int2: TIntX; mode: TMultiplyMode) : TIntX; static; /// /// Divides one object by another. /// /// First big integer. /// Second big integer. /// Divide mode. /// Division result. class function Divide(int1: TIntX; int2: TIntX; mode: TDivideMode) : TIntX; static; /// /// Divides one object by another and returns division modulo. /// /// First big integer. /// Second big integer. /// Divide mode. /// Modulo result. class function Modulo(int1: TIntX; int2: TIntX; mode: TDivideMode) : TIntX; static; /// /// Divides one object by another. /// Returns both divident and remainder /// /// First big integer. /// Second big integer. /// Remainder big integer. /// Division result. class function DivideModulo(int1: TIntX; int2: TIntX; out modRes: TIntX) : TIntX; overload; static; /// /// Divides one object by another. /// Returns both divident and remainder /// /// First big integer. /// Second big integer. /// Remainder big integer. /// Divide mode. /// Division result. class function DivideModulo(int1: TIntX; int2: TIntX; out modRes: TIntX; mode: TDivideMode): TIntX; overload; static; /// /// Returns a Non-Negative Random object using Pcg Random. /// /// Random TIntX value. class function Random(): TIntX; static; /// /// Returns a Non-Negative Random object using Pcg Random within the specified Range. (Max not Included) /// /// Minimum value. /// Maximum value (Max not Included) /// Random TIntX value. class function RandomRange(Min: UInt32; Max: UInt32): TIntX; static; /// /// Calculates absolute value of object. /// /// value to get absolute value of. /// Absolute value. /// is a null reference. class function AbsoluteValue(value: TIntX): TIntX; static; /// /// The base-10 logarithm of the value. /// /// The value. /// The base-10 logarithm of the value. /// Source : Microsoft .NET Reference on GitHub /// is a null reference. class function Log10(value: TIntX): Double; static; /// /// Calculates the natural logarithm of the value. /// /// /// The value. /// /// /// The natural logarithm. /// /// /// is a null reference. /// /// /// Source : Microsoft .NET Reference on GitHub /// class function Ln(value: TIntX): Double; static; /// /// Calculates Logarithm of a number object for a specified base. /// the largest power the base can be raised to that does not exceed the number. /// /// base. /// number to get log of. /// Log value. /// Source : Microsoft .NET Reference on GitHub /// is a null reference. class function LogN(base: Double; value: TIntX): Double; overload; static; /// /// Calculates Integer Logarithm of a number object for a specified base. /// the largest power the base can be raised to that does not exceed the number. /// /// base. /// number to get Integer log of. /// Integer Log. /// [IntegerLogN Implementation] /// is a null reference. /// is a null reference. /// or is an invalid argument. class function IntegerLogN(base: TIntX; number: TIntX): TIntX; overload; static; /// /// Calculates Square of object. /// /// /// value to get square of. /// /// /// Squared value. /// /// /// is a null reference. /// class function Square(value: TIntX): TIntX; static; /// /// Calculates Integer SquareRoot of object /// /// value to get Integer squareroot of. /// Integer SquareRoot. /// [IntegerSquareRoot Implementation] /// is a null reference. class function IntegerSquareRoot(value: TIntX): TIntX; static; /// /// Calculates Factorial of object. /// /// value to get factorial of. /// Factorial. /// is a null reference. class function Factorial(value: TIntX): TIntX; static; /// /// (Optimized GCD). /// Returns a specified big integer holding the GCD (Greatest common Divisor) of /// two big integers using Binary GCD (Stein's algorithm). /// /// First big integer. /// Second big integer. /// GCD number. /// [GCD Implementation] /// [GCD Implementation Optimizations] /// is a null reference. /// is a null reference. class function GCD(int1: TIntX; int2: TIntX): TIntX; static; /// /// (LCM). /// Returns a specified big integer holding the LCM (Least Common Multiple) of /// two big integers. /// /// First big integer. /// Second big integer. /// LCM number. /// is a null reference. /// is a null reference. class function LCM(int1: TIntX; int2: TIntX): TIntX; static; /// /// Calculate Modular Inverse for two objects using Euclids Extended Algorithm. /// returns Zero if no Modular Inverse Exists for the Inputs /// /// First big integer. /// Second big integer. /// Modular Inverse. /// [Modular Inverse Explanation] /// [Modular Inverse Implementation] /// is a null reference. /// is a null reference. /// or is an invalid argument. class function InvMod(int1: TIntX; int2: TIntX): TIntX; static; /// /// Calculates Calculates Modular Exponentiation of object. /// /// value to compute ModPow of. /// exponent to use. /// modulus to use. /// Computed value. /// [Modular Exponentiation Explanation] /// is a null reference. /// is a null reference. /// is a null reference. /// is an invalid argument. /// is an invalid argument. class function ModPow(value: TIntX; exponent: TIntX; modulus: TIntX) : TIntX; static; /// /// Calculates Bézoutsidentity for two objects using Euclids Extended Algorithm /// /// first value. /// second value. /// first bezout value. /// second bezout value. /// GCD (Greatest Common Divisor) value. /// [Bézout's identity Explanation] /// [Bézout's identity Pseudocode using Extended Euclidean algorithm] /// is a null reference. /// is a null reference. class function Bezoutsidentity(int1: TIntX; int2: TIntX; out bezOne: TIntX; out bezTwo: TIntX): TIntX; static; /// /// Checks if a object is Probably Prime using Miller–Rabin primality test. /// /// big integer to check primality. /// Accuracy parameter `k´ of the Miller-Rabin algorithm. Default is 5. The execution time is proportional to the value of the accuracy parameter. /// Boolean value. /// [Miller–Rabin primality test Explanation] /// [Miller–Rabin primality test Implementation in C] /// is a null reference. class function IsProbablyPrime(value: TIntX; Accuracy: Integer = 5) : Boolean; static; /// /// The Max Between Two values. /// /// /// left value. /// /// /// right value. /// /// /// The Maximum value. /// /// /// is a null reference. /// /// /// is a null reference. /// class function Max(left: TIntX; right: TIntX): TIntX; static; /// /// The Min Between Two values. /// /// left value. /// right value. /// The Minimum value. /// is a null reference. /// is a null reference. class function Min(left: TIntX; right: TIntX): TIntX; static; /// /// Returns a specified big integer raised to the specified power. /// /// Number to raise. /// Power. /// Number in given power. class function Pow(value: TIntX; power: UInt32): TIntX; overload; static; /// /// Returns a specified big integer raised to the specified power. /// /// Number to raise. /// Power. /// Multiply mode set explicitly. /// Number in given power. class function Pow(value: TIntX; power: UInt32; multiplyMode: TMultiplyMode) : TIntX; overload; static; // String output functions /// /// Returns decimal string representation of this object. /// /// Decimal number in string. function ToString(): String; overload; /// /// Returns string representation of this object in given base. /// /// Base of system in which to do output. /// Object string representation. function ToString(numberBase: UInt32): String; overload; /// /// Returns string representation of this object in given base. /// /// Base of system in which to do output. /// Use uppercase for bases from 11 to 16 (which use letters A-F). /// Object string representation. function ToString(numberBase: UInt32; UpperCase: Boolean): String; overload; /// /// Returns string representation of this object in given base using custom alphabet. /// /// Base of system in which to do output. /// Alphabet which contains chars used to represent big integer, char position is coresponding digit value. /// Object string representation. function ToString(numberBase: UInt32; const alphabet: String) : String; overload; // -- Conversion functions -- /// /// Converts the specified to a Double, if this is possible. returns Infinity (+ or -) if the /// value of the is too large or too small. /// uses method found in Microsoft BigInteger source on github. /// function AsDouble: Double; /// /// Converts the specified to an Integer, if this is possible. Raises an EOverFlowException if the /// value of the is too large. /// function AsInteger: Integer; /// /// Converts the specified to a UInt32, if this is possible. Raises an EOverFlowException if the /// value of the is too large or is negative. /// function AsUInt32: UInt32; /// /// Converts the specified to an Int64, if this is possible. Raises an EOverFlowException if the /// value of the is too large. /// function AsInt64: Int64; /// /// Converts the specified to a UInt64, if this is possible. Raises an EOverFlowException if the /// value of the is too large or is negative. /// function AsUInt64: UInt64; // String parsing functions /// /// Parses provided string representation of object in decimal base. /// If number starts from "0" then it's treated as octal; if number starts from "$" or "0x" /// then it's treated as hexadecimal. /// /// Number as string. /// Parsed TIntX object. class function Parse(const value: String): TIntX; overload; static; /// /// Parses provided string representation of object. /// /// Number as string. /// Number base. /// Parsed TIntX object. class function Parse(const value: String; numberBase: UInt32): TIntX; overload; static; /// /// Parses provided string representation of object using custom alphabet. /// /// Number as string. /// Number base. /// Alphabet which contains chars used to represent big integer, char position is coresponding digit value. /// Parsed TIntX object. class function Parse(const value: String; numberBase: UInt32; const alphabet: String): TIntX; overload; static; /// /// Parses provided string representation of object in decimal base. /// If number starts from "0" then it's treated as octal; if number starts from "$" or "0x" /// then it's treated as hexadecimal. /// /// Number as string. /// Parse mode. /// Parsed TIntX object. class function Parse(const value: String; mode: TParseMode): TIntX; overload; static; /// /// Parses provided string representation of object. /// /// Number as string. /// Number base. /// Parse mode. /// Parsed TIntX object. class function Parse(const value: String; numberBase: UInt32; mode: TParseMode): TIntX; overload; static; /// /// Parses provided string representation of object using custom alphabet. /// /// Number as string. /// Number base. /// Alphabet which contains chars used to represent big integer, char position is coresponding digit value. /// Parse mode. /// Parsed TIntX object. class function Parse(const value: String; numberBase: UInt32; const alphabet: String; mode: TParseMode): TIntX; overload; static; /// /// Returns equality of this with another big integer. /// /// Big integer to compare with. /// True if equals. function Equals(n: TIntX): Boolean; overload; /// /// Returns equality of this with another integer. /// /// Integer to compare with. /// True if equals. function Equals(n: Integer): Boolean; overload; /// /// Returns equality of this with another unsigned integer. /// /// Unsigned integer to compare with. /// True if equals. function Equals(n: UInt32): Boolean; overload; /// /// Returns equality of this with another Int64. /// /// Int64 to compare with. /// True if equals. function Equals(n: Int64): Boolean; overload; /// /// Returns equality of this with another unsigned Int64. /// /// unsigned Int64 to compare with. /// True if equals. function Equals(n: UInt64): Boolean; overload; /// /// Compares current object with another big integer. /// /// Big integer to compare with. /// 1 if object is bigger than , -1 if object is smaller than , 0 if they are equal. function CompareTo(n: TIntX): Integer; overload; /// /// Compares current object with another integer. /// /// Integer to compare with. /// 1 if object is bigger than , -1 if object is smaller than , 0 if they are equal. function CompareTo(n: Integer): Integer; overload; /// /// Compares current object with another unsigned integer. /// /// Unsigned integer to compare with. /// 1 if object is bigger than , -1 if object is smaller than , 0 if they are equal. function CompareTo(n: UInt32): Integer; overload; /// /// Compares current object with another Int64. /// /// Int64 to compare with. /// 1 if object is bigger than , -1 if object is smaller than , 0 if they are equal. function CompareTo(n: Int64): Integer; overload; /// /// Compares current object with another UInt64. /// /// UInt64 to compare with. /// 1 if object is bigger than , -1 if object is smaller than , 0 if they are equal. function CompareTo(n: UInt64): Integer; overload; /// /// Frees extra space not used by digits. /// procedure Normalize(); /// /// Retrieves this internal state as digits array and sign. /// Can be used for serialization and other purposes. /// Note: please use constructor instead to clone object. /// /// Digits array. /// Is negative integer. /// Is zero initialized?. procedure GetInternalState(out digits: TIntXLibUInt32Array; out negative: Boolean; out zeroinithelper: Boolean); /// /// Frees extra space not used by digits only if auto-normalize is set for the instance. /// procedure TryNormalize(); /// /// Compare two records to check if they are same. /// /// Record one to compare. /// Record two to compare. /// Boolean value (True if they contain the Same contents else False). class function CompareRecords(Rec1: TIntX; Rec2: TIntX): Boolean; static; inline; // -- Comparison operators -- /// /// Compares two objects and returns true if their internal state is equal. /// /// First big integer. /// Second big integer. /// True if equals. class operator Equal(int1: TIntX; int2: TIntX): Boolean; /// /// Compares object with integer and returns true if their internal state is equal. /// /// big integer. /// integer. /// True if equals. class operator Equal(int1: TIntX; int2: Integer): Boolean; /// /// Compares integer with object and returns true if their internal state is equal. /// /// integer. /// big integer. /// True if equals. class operator Equal(int1: Integer; int2: TIntX): Boolean; /// /// Compares object with unsigned integer and returns true if their internal state is equal. /// /// big integer. /// unsigned integer. /// True if equals. class operator Equal(int1: TIntX; int2: UInt32): Boolean; /// /// Compares unsigned integer with object and returns true if their internal state is equal. /// /// unsigned integer. /// big integer. /// True if equals. class operator Equal(int1: UInt32; int2: TIntX): Boolean; /// /// Compares object with Int64 and returns true if their internal state is equal. /// /// big integer. /// Int64. /// True if equals. class operator Equal(int1: TIntX; int2: Int64): Boolean; /// /// Compares Int64 with object and returns true if their internal state is equal. /// /// Int64. /// big integer. /// True if equals. class operator Equal(int1: Int64; int2: TIntX): Boolean; /// /// Compares object with UInt64 and returns true if their internal state is equal. /// /// big integer. /// UInt64. /// True if equals. class operator Equal(int1: TIntX; int2: UInt64): Boolean; /// /// Compares UInt64 with object and returns true if their internal state is equal. /// /// UInt64. /// big integer. /// True if equals. class operator Equal(int1: UInt64; int2: TIntX): Boolean; /// /// Compares two objects and returns true if their internal state is not equal. /// /// First big integer. /// Second big integer. /// True if not equals. class operator NotEqual(int1: TIntX; int2: TIntX): Boolean; /// /// Compares object with integer and returns true if their internal state is not equal. /// /// big integer. /// integer. /// True if not equals. class operator NotEqual(int1: TIntX; int2: Integer): Boolean; /// /// Compares integer with object and returns true if their internal state is not equal. /// /// integer. /// big integer. /// True if not equals. class operator NotEqual(int1: Integer; int2: TIntX): Boolean; /// /// Compares object with unsigned integer and returns true if their internal state is not equal. /// /// big integer. /// unsigned integer. /// True if not equals. class operator NotEqual(int1: TIntX; int2: UInt32): Boolean; /// /// Compares unsigned integer with object and returns true if their internal state is not equal. /// /// unsigned integer. /// big integer. /// True if not equals. class operator NotEqual(int1: UInt32; int2: TIntX): Boolean; /// /// Compares object with Int64 and returns true if their internal state is not equal. /// /// big integer. /// Int64. /// True if not equals. class operator NotEqual(int1: TIntX; int2: Int64): Boolean; /// /// Compares Int64 with object and returns true if their internal state is not equal. /// /// Int64. /// big integer. /// True if not equals. class operator NotEqual(int1: Int64; int2: TIntX): Boolean; /// /// Compares object with UInt64 and returns true if their internal state is not equal. /// /// big integer. /// UInt64. /// True if not equals. class operator NotEqual(int1: TIntX; int2: UInt64): Boolean; /// /// Compares UInt64 with object and returns true if their internal state is not equal. /// /// UInt64. /// big integer. /// True if not equals. class operator NotEqual(int1: UInt64; int2: TIntX): Boolean; /// /// Compares two objects and returns true if first is greater. /// /// First big integer. /// Second big integer. /// True if first is greater. class operator GreaterThan(int1: TIntX; int2: TIntX): Boolean; /// /// Compares object with integer and returns true if first is greater. /// /// big integer. /// integer. /// True if first is greater. class operator GreaterThan(int1: TIntX; int2: Integer): Boolean; /// /// Compares integer with object and returns true if first is greater. /// /// integer. /// big integer. /// True if first is greater. class operator GreaterThan(int1: Integer; int2: TIntX): Boolean; /// /// Compares object with unsigned integer and returns true if first is greater. /// /// big integer. /// unsigned integer. /// True if first is greater. class operator GreaterThan(int1: TIntX; int2: UInt32): Boolean; /// /// Compares unsigned integer with object and returns true if first is greater. /// /// unsigned integer. /// big integer. /// True if first is greater. class operator GreaterThan(int1: UInt32; int2: TIntX): Boolean; /// /// Compares object with Int64 and returns true if first is greater. /// /// big integer. /// Int64. /// True if first is greater. class operator GreaterThan(int1: TIntX; int2: Int64): Boolean; /// /// Compares Int64 with object and returns true if first is greater. /// /// Int64. /// big integer. /// True if first is greater. class operator GreaterThan(int1: Int64; int2: TIntX): Boolean; /// /// Compares object with UInt64 and returns true if first is greater. /// /// big integer. /// UInt64. /// True if first is greater. class operator GreaterThan(int1: TIntX; int2: UInt64): Boolean; /// /// Compares UInt64 with object and returns true if first is greater. /// /// UInt64. /// big integer. /// True if first is greater. class operator GreaterThan(int1: UInt64; int2: TIntX): Boolean; /// /// Compares two objects and returns true if first is greater or equal. /// /// First big integer. /// Second big integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: TIntX; int2: TIntX): Boolean; /// /// Compares object with integer and returns true if first is greater or equal. /// /// big integer. /// integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: TIntX; int2: Integer): Boolean; /// /// Compares integer with object and returns true if first is greater or equal. /// /// integer. /// big integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: Integer; int2: TIntX): Boolean; /// /// Compares object with unsigned integer and returns true if first is greater or equal. /// /// big integer. /// unsigned integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: TIntX; int2: UInt32): Boolean; /// /// Compares unsigned integer with object and returns true if first is greater or equal. /// /// unsigned integer. /// big integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: UInt32; int2: TIntX): Boolean; /// /// Compares object with Int64 and returns true if first is greater or equal. /// /// big integer. /// Int64. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: TIntX; int2: Int64): Boolean; /// /// Compares Int64 with object and returns true if first is greater or equal. /// /// Int64. /// big integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: Int64; int2: TIntX): Boolean; /// /// Compares object with UInt64 and returns true if first is greater or equal. /// /// big integer. /// UInt64. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: TIntX; int2: UInt64): Boolean; /// /// Compares UInt64 with object and returns true if first is greater or equal. /// /// UInt64. /// big integer. /// True if first is greater or equal. class operator GreaterThanOrEqual(int1: UInt64; int2: TIntX): Boolean; /// /// Compares two objects and returns true if first is lighter. /// /// First big integer. /// Second big integer. /// True if first is lighter. class operator LessThan(int1: TIntX; int2: TIntX): Boolean; /// /// Compares object with integer and returns true if first is lighter. /// /// big integer. /// integer. /// True if first is lighter. class operator LessThan(int1: TIntX; int2: Integer): Boolean; /// /// Compares integer with object and returns true if first is lighter. /// /// integer. /// big integer. /// True if first is lighter. class operator LessThan(int1: Integer; int2: TIntX): Boolean; /// /// Compares object with unsigned integer and returns true if first is lighter. /// /// big integer. /// unsigned integer. /// True if first is lighter. class operator LessThan(int1: TIntX; int2: UInt32): Boolean; /// /// Compares unsigned integer with object and returns true if first is lighter. /// /// unsigned integer. /// big integer. /// True if first is lighter. class operator LessThan(int1: UInt32; int2: TIntX): Boolean; /// /// Compares object with Int64 and returns true if first is lighter. /// /// big integer. /// Int64. /// True if first is lighter. class operator LessThan(int1: TIntX; int2: Int64): Boolean; /// /// Compares Int64 with object and returns true if first is lighter. /// /// Int64. /// big integer. /// True if first is lighter. class operator LessThan(int1: Int64; int2: TIntX): Boolean; /// /// Compares object with UInt64 and returns true if first is lighter. /// /// big integer. /// UInt64. /// True if first is lighter. class operator LessThan(int1: TIntX; int2: UInt64): Boolean; /// /// Compares UInt64 with object and returns true if first is lighter. /// /// UInt64. /// big integer. /// True if first is lighter. class operator LessThan(int1: UInt64; int2: TIntX): Boolean; /// /// Compares two objects and returns true if first is lighter or equal. /// /// First big integer. /// Second big integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: TIntX; int2: TIntX): Boolean; /// /// Compares object with integer and returns true if first is lighter or equal. /// /// big integer. /// integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: TIntX; int2: Integer): Boolean; /// /// Compares integer with object and returns true if first is lighter or equal. /// /// integer. /// big integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: Integer; int2: TIntX): Boolean; /// /// Compares object with unsigned integer and returns true if first is lighter or equal. /// /// big integer. /// unsigned integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: TIntX; int2: UInt32): Boolean; /// /// Compares unsigned integer with object and returns true if first is lighter or equal. /// /// unsigned integer. /// big integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: UInt32; int2: TIntX): Boolean; /// /// Compares object with Int64 and returns true if first is lighter or equal. /// /// big integer. /// Int64. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: TIntX; int2: Int64): Boolean; /// /// Compares Int64 with object and returns true if first is lighter or equal. /// /// Int64. /// big integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: Int64; int2: TIntX): Boolean; /// /// Compares object with UInt64 and returns true if first is lighter or equal. /// /// big integer. /// UInt64. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: TIntX; int2: UInt64): Boolean; /// /// Compares UInt64 with object and returns true if first is lighter or equal. /// /// UInt64. /// big integer. /// True if first is lighter or equal. class operator LessThanOrEqual(int1: UInt64; int2: TIntX): Boolean; // -- Arithmetic operators -- /// /// Adds one object to another. /// /// First big integer. /// Second big integer. /// Addition result. class operator Add(int1: TIntX; int2: TIntX): TIntX; /// /// Subtracts one object from another. /// /// First big integer. /// Second big integer. /// Subtraction result. class operator Subtract(int1: TIntX; int2: TIntX): TIntX; /// /// Multiplies one object by another. /// /// First big integer. /// Second big integer. /// Multiply result. class operator Multiply(int1: TIntX; int2: TIntX): TIntX; /// /// Divides one object by another. /// /// First big integer. /// Second big integer. /// Division result. class operator IntDivide(int1: TIntX; int2: TIntX): TIntX; /// /// Divides one object by another and returns division modulo. /// /// First big integer. /// Second big integer. /// Modulo result. class operator modulus(int1: TIntX; int2: TIntX): TIntX; /// /// Shifts object by selected bits count to the left. /// /// Big integer. /// Bits count. /// Shifting result. class operator LeftShift(IntX: TIntX; shift: Integer): TIntX; /// /// Shifts object by selected bits count to the right. /// /// Big integer. /// Bits count. /// Shifting result. class operator RightShift(IntX: TIntX; shift: Integer): TIntX; /// /// Returns the same value. /// /// Initial value. /// The same value, but new object. /// is a null reference. class operator Positive(value: TIntX): TIntX; /// /// Returns the same value, but with other sign. /// /// Initial value. /// The same value, but with other sign. /// is a null reference. class operator negative(value: TIntX): TIntX; /// /// Returns increased value. /// /// Initial value. /// Increased value. /// is a null reference. class operator Inc(value: TIntX): TIntX; /// /// Returns decreased value. /// /// Initial value. /// Decreased value. /// is a null reference. class operator Dec(value: TIntX): TIntX; // -- Logical and bitwise operators -- /// /// Performs bitwise OR for two big integers. /// /// First big integer. /// Second big integer. /// Resulting big integer. class operator BitwiseOr(int1: TIntX; int2: TIntX): TIntX; /// /// Performs bitwise AND for two big integers. /// /// First big integer. /// Second big integer. /// Resulting big integer. class operator BitwiseAnd(int1: TIntX; int2: TIntX): TIntX; /// /// Performs bitwise XOR for two big integers. /// /// First big integer. /// Second big integer. /// Resulting big integer. class operator BitwiseXor(int1: TIntX; int2: TIntX): TIntX; /// /// Performs bitwise NOT for big integer. /// /// Big integer. /// Resulting big integer. /// /// ** In Delphi, You cannot overload the bitwise not operator, as BitwiseNot is not /// supported by the compiler. You have to overload the logical 'not' operator /// instead. /// **A bitwise not might be An Integer XOR -1 (Not Sure Though)** /// /// [For more Information] class operator LogicalNot(value: TIntX): TIntX; // -- Implicit conversion operators -- /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: Byte): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: ShortInt): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: SmallInt): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: Word): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: Integer): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: UInt32): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: Int64): TIntX; /// /// Implicitly converts to . /// /// Value to convert. /// Conversion result. class operator Implicit(value: UInt64): TIntX; // -- Explicit conversion operators -- /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: Double): TIntX; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): Byte; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): ShortInt; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): SmallInt; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): Word; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): Integer; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. /// is a null reference. class operator Explicit(value: TIntX): UInt32; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): Int64; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): UInt64; /// /// Explicitly converts to . /// /// Value to convert. /// Conversion result. class operator Explicit(value: TIntX): Double; end; var /// /// Temporary Variable to Hold Zero. /// ZeroX: TIntX; /// /// Temporary Variable to Hold One. /// OneX: TIntX; /// /// Temporary Variable to Hold Minus One. /// MinusOneX: TIntX; /// /// Temporary Variable to Hold Ten . /// TenX: TIntX; implementation uses uConstants, uMultiplyManager, uDivideManager, uStringConvertManager, uParseManager, uDigitHelper, uOpHelper, uStrRepHelper; // static constructor class constructor TIntX.Create(); begin _globalSettings := TIntXGlobalSettings.Create; _settings := TIntXSettings.Create(TIntX.GlobalSettings); // Global FormatSettings {$IFDEF FPC} _FS := DefaultFormatSettings; {$ELSE} {$IFDEF DELPHIXE_UP} _FS := TFormatSettings.Create; {$ELSE} GetLocaleFormatSettings(0, _FS); {$ENDIF DELPHIXE_UP} {$ENDIF FPC} // Create a Zero TIntX (a big integer with value as Zero) ZeroX := TIntX.Create(0); // Create a One TIntX (a big integer with value as One) OneX := TIntX.Create(1); // Create a MinusOne TIntX (a big integer with value as Negative One) MinusOneX := TIntX.Create(-1); // Create a Ten TIntX (a big integer with value as Ten) TenX := TIntX.Create(10); {$IFDEF DEBUG} _maxFhtRoundErrorCriticalSection := TCriticalSection.Create; {$ENDIF DEBUG} end; class destructor TIntX.Destroy(); begin {$IFDEF DEBUG} _maxFhtRoundErrorCriticalSection.Free; {$ENDIF DEBUG} _globalSettings.Free; _settings.Free; end; class function TIntX.CompareRecords(Rec1: TIntX; Rec2: TIntX): Boolean; begin if Length(Rec1._digits) <> Length(Rec2._digits) then begin result := false; Exit; end; result := (CompareMem(Pointer(Rec1._digits), Pointer(Rec2._digits), Length(Rec1._digits) * SizeOf(UInt32)) and (Rec1._length = Rec2._length) and (Rec1._negative = Rec2._negative) and (Rec1._zeroinithelper = Rec2._zeroinithelper)); end; class function TIntX.GetZero: TIntX; begin result := ZeroX; end; class function TIntX.GetOne: TIntX; begin result := OneX; end; class function TIntX.GetMinusOne: TIntX; begin result := MinusOneX; end; class function TIntX.GetTen: TIntX; begin result := TenX; end; class function TIntX.GetGlobalSettings: TIntXGlobalSettings; begin result := _globalSettings; end; constructor TIntX.Create(value: Integer); begin if (value = 0) then begin // Very specific fast processing for zero values InitFromZero(); end else begin // Prepare internal fields _length := 1; SetLength(_digits, _length); // Fill the only big integer digit TDigitHelper.ToUInt32WithSign(value, _digits[0], _negative, _zeroinithelper); end; end; constructor TIntX.Create(value: UInt32); begin if (value = 0) then begin // Very specific fast processing for zero values InitFromZero(); end else begin // Prepare internal fields SetLength(_digits, 1); _digits[0] := value; _length := 1; // Initialized _negative to False by default since this type does not have // negative values. _negative := false; end; end; constructor TIntX.Create(value: Int64); var newValue: UInt64; begin if (value = 0) then begin // Very specific fast processing for zero values InitFromZero(); end else begin // Fill the only big integer digit TDigitHelper.ToUInt64WithSign(value, newValue, _negative, _zeroinithelper); InitFromUlong(newValue); end; end; constructor TIntX.Create(value: UInt64); begin if (value = 0) then begin // Very specific fast processing for zero values InitFromZero(); end else begin InitFromUlong(value); // Initialized _negative to False by default since this type does not have // negative values. _negative := false; end; end; constructor TIntX.Create(value: Double); begin // Exceptions if (IsInfinite(value)) then raise EOverflowException.Create(uStrings.Overflow_TIntXInfinity); if (IsNaN(value)) then raise EOverflowException.Create(uStrings.Overflow_NotANumber); _digits := Nil; TOpHelper.SetDigitsFromDouble(value, _digits, Self); end; constructor TIntX.Create(digits: TIntXLibUInt32Array; negative: Boolean); begin // Exception if (digits = Nil) then begin raise EArgumentNilException.Create('digits'); end; InitFromDigits(digits, negative, TDigitHelper.GetRealDigitsLength(digits, UInt32(Length(digits)))); end; constructor TIntX.Create(const value: String); var IntX: TIntX; begin IntX := Parse(value); InitFromIntX(IntX); end; constructor TIntX.Create(const value: String; numberBase: UInt32); var IntX: TIntX; begin IntX := Parse(value, numberBase); InitFromIntX(IntX); end; constructor TIntX.Create(value: TIntX); begin // Exception if (value = Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; InitFromIntX(value); end; constructor TIntX.Create(mlength: UInt32; negative: Boolean); begin _length := mlength; SetLength(_digits, _length); _negative := negative; end; constructor TIntX.Create(digits: TIntXLibUInt32Array; negative: Boolean; mlength: UInt32); begin // Exception if (digits = Nil) then begin raise EArgumentNilException.Create('digits'); end; InitFromDigits(digits, negative, mlength); end; function TIntX.GetSettings: TIntXSettings; begin result := _settings; end; procedure TIntX.SetSettings(value: TIntXSettings); begin _settings := value; end; function TIntX.GetIsOdd: Boolean; begin result := (_length > 0) and ((_digits[0] and 1) = 1); end; function TIntX.GetIsNegative: Boolean; begin result := _negative; end; function TIntX.GetIsZero: Boolean; begin result := Self.Equals(TIntX.Zero); end; function TIntX.GetIsOne: Boolean; begin result := Self.Equals(TIntX.One); end; function TIntX.GetIsPowerOfTwo: Boolean; var iu: Integer; begin if IsNegative then begin result := false; Exit; end; if Self <= TConstants.MaxUInt64Value then begin result := (not Self.IsZero) and (Self and (Self - 1) = 0); Exit; end; iu := Length(_digits) - 1; if ((_digits[iu] and (_digits[iu] - 1)) <> 0) then begin result := false; Exit; end; Dec(iu); while iu >= 0 do begin if (_digits[iu] <> 0) then begin result := false; Exit; end; Dec(iu); end; result := true; Exit; end; function TIntX.GetClone: TIntX; begin result._digits := Copy(Self._digits); result._length := Self._length; result._negative := Self._negative; result._zeroinithelper := Self._zeroinithelper; end; class operator TIntX.Equal(int1: TIntX; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int1, int2, false) = 0; end; class operator TIntX.Equal(int1: TIntX; int2: Integer): Boolean; begin result := TOpHelper.Cmp(int1, int2) = 0; end; class operator TIntX.Equal(int1: Integer; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) = 0; end; class operator TIntX.Equal(int1: TIntX; int2: UInt32): Boolean; begin result := TOpHelper.Cmp(int1, int2) = 0; end; class operator TIntX.Equal(int1: UInt32; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) = 0; end; class operator TIntX.Equal(int1: TIntX; int2: Int64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) = 0; end; class operator TIntX.Equal(int1: Int64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) = 0; end; class operator TIntX.Equal(int1: TIntX; int2: UInt64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) = 0; end; class operator TIntX.Equal(int1: UInt64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) = 0; end; class operator TIntX.NotEqual(int1: TIntX; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int1, int2, false) <> 0; end; class operator TIntX.NotEqual(int1: TIntX; int2: Integer): Boolean; begin result := TOpHelper.Cmp(int1, int2) <> 0; end; class operator TIntX.NotEqual(int1: Integer; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) <> 0; end; class operator TIntX.NotEqual(int1: TIntX; int2: UInt32): Boolean; begin result := TOpHelper.Cmp(int1, int2) <> 0; end; class operator TIntX.NotEqual(int1: UInt32; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) <> 0; end; class operator TIntX.NotEqual(int1: TIntX; int2: Int64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) <> 0; end; class operator TIntX.NotEqual(int1: Int64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) <> 0; end; class operator TIntX.NotEqual(int1: TIntX; int2: UInt64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) <> 0; end; class operator TIntX.NotEqual(int1: UInt64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) <> 0; end; class operator TIntX.GreaterThan(int1: TIntX; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int1, int2, true) > 0; end; class operator TIntX.GreaterThan(int1: TIntX; int2: Integer): Boolean; begin result := TOpHelper.Cmp(int1, int2) > 0; end; class operator TIntX.GreaterThan(int1: Integer; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) < 0; end; class operator TIntX.GreaterThan(int1: TIntX; int2: UInt32): Boolean; begin result := TOpHelper.Cmp(int1, int2) > 0; end; class operator TIntX.GreaterThan(int1: UInt32; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) < 0; end; class operator TIntX.GreaterThan(int1: TIntX; int2: Int64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) > 0; end; class operator TIntX.GreaterThan(int1: Int64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) < 0; end; class operator TIntX.GreaterThan(int1: TIntX; int2: UInt64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) > 0; end; class operator TIntX.GreaterThan(int1: UInt64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) < 0; end; class operator TIntX.GreaterThanOrEqual(int1: TIntX; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int1, int2, true) >= 0; end; class operator TIntX.GreaterThanOrEqual(int1: TIntX; int2: Integer): Boolean; begin result := TOpHelper.Cmp(int1, int2) >= 0; end; class operator TIntX.GreaterThanOrEqual(int1: Integer; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) <= 0; end; class operator TIntX.GreaterThanOrEqual(int1: TIntX; int2: UInt32): Boolean; begin result := TOpHelper.Cmp(int1, int2) >= 0; end; class operator TIntX.GreaterThanOrEqual(int1: UInt32; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) <= 0; end; class operator TIntX.GreaterThanOrEqual(int1: TIntX; int2: Int64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) >= 0; end; class operator TIntX.GreaterThanOrEqual(int1: Int64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) <= 0; end; class operator TIntX.GreaterThanOrEqual(int1: TIntX; int2: UInt64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) >= 0; end; class operator TIntX.GreaterThanOrEqual(int1: UInt64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) <= 0; end; class operator TIntX.LessThan(int1: TIntX; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int1, int2, true) < 0; end; class operator TIntX.LessThan(int1: TIntX; int2: Integer): Boolean; begin result := TOpHelper.Cmp(int1, int2) < 0; end; class operator TIntX.LessThan(int1: Integer; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) > 0; end; class operator TIntX.LessThan(int1: TIntX; int2: UInt32): Boolean; begin result := TOpHelper.Cmp(int1, int2) < 0; end; class operator TIntX.LessThan(int1: UInt32; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) > 0; end; class operator TIntX.LessThan(int1: TIntX; int2: Int64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) < 0; end; class operator TIntX.LessThan(int1: Int64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) > 0; end; class operator TIntX.LessThan(int1: TIntX; int2: UInt64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) < 0; end; class operator TIntX.LessThan(int1: UInt64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) > 0; end; class operator TIntX.LessThanOrEqual(int1: TIntX; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int1, int2, true) <= 0; end; class operator TIntX.LessThanOrEqual(int1: TIntX; int2: Integer): Boolean; begin result := TOpHelper.Cmp(int1, int2) <= 0; end; class operator TIntX.LessThanOrEqual(int1: Integer; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) >= 0; end; class operator TIntX.LessThanOrEqual(int1: TIntX; int2: UInt32): Boolean; begin result := TOpHelper.Cmp(int1, int2) <= 0; end; class operator TIntX.LessThanOrEqual(int1: UInt32; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, int1) >= 0; end; class operator TIntX.LessThanOrEqual(int1: TIntX; int2: Int64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) <= 0; end; class operator TIntX.LessThanOrEqual(int1: Int64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) >= 0; end; class operator TIntX.LessThanOrEqual(int1: TIntX; int2: UInt64): Boolean; begin result := TOpHelper.Cmp(int1, TIntX.Create(int2), false) <= 0; end; class operator TIntX.LessThanOrEqual(int1: UInt64; int2: TIntX): Boolean; begin result := TOpHelper.Cmp(int2, TIntX.Create(int1), false) >= 0; end; class operator TIntX.Add(int1: TIntX; int2: TIntX): TIntX; begin result := TOpHelper.AddSub(int1, int2, false); end; class operator TIntX.Subtract(int1: TIntX; int2: TIntX): TIntX; begin result := TOpHelper.AddSub(int1, int2, true); end; class operator TIntX.Multiply(int1: TIntX; int2: TIntX): TIntX; begin result := TMultiplyManager.GetCurrentMultiplier().Multiply(int1, int2); end; class operator TIntX.IntDivide(int1: TIntX; int2: TIntX): TIntX; var modRes: TIntX; begin result := TDivideManager.GetCurrentDivider().DivMod(int1, int2, modRes, TDivModResultFlags.dmrfDiv); end; class operator TIntX.modulus(int1: TIntX; int2: TIntX): TIntX; var modRes: TIntX; begin TDivideManager.GetCurrentDivider().DivMod(int1, int2, modRes, TDivModResultFlags.dmrfMod); result := modRes; end; class operator TIntX.LeftShift(IntX: TIntX; shift: Integer): TIntX; begin result := TOpHelper.Sh(IntX, shift, true); end; class operator TIntX.RightShift(IntX: TIntX; shift: Integer): TIntX; begin result := TOpHelper.Sh(IntX, shift, false); end; class operator TIntX.Positive(value: TIntX): TIntX; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; result := TIntX.Create(value); end; class operator TIntX.negative(value: TIntX): TIntX; var newValue: TIntX; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; newValue := TIntX.Create(value); if (newValue._length <> 0) then begin newValue._negative := not newValue._negative; end; result := newValue; end; class operator TIntX.Inc(value: TIntX): TIntX; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; result := value + UInt32(1); end; class operator TIntX.Dec(value: TIntX): TIntX; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; result := value - UInt32(1); end; class operator TIntX.BitwiseOr(int1: TIntX; int2: TIntX): TIntX; begin result := TOpHelper.BitwiseOr(int1, int2); end; class operator TIntX.BitwiseAnd(int1: TIntX; int2: TIntX): TIntX; begin result := TOpHelper.BitwiseAnd(int1, int2); end; class operator TIntX.BitwiseXor(int1: TIntX; int2: TIntX): TIntX; begin result := TOpHelper.ExclusiveOr(int1, int2); end; class operator TIntX.LogicalNot(value: TIntX): TIntX; begin result := TOpHelper.OnesComplement(value); end; class operator TIntX.Implicit(value: Byte): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: ShortInt): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: SmallInt): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: Word): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: Integer): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: UInt32): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: Int64): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Implicit(value: UInt64): TIntX; begin result := TIntX.Create(value); end; class operator TIntX.Explicit(value: Double): TIntX; begin result := TIntX.Create(value); end; {$OVERFLOWCHECKS ON} class operator TIntX.Explicit(value: TIntX): Byte; begin result := Byte(Integer(value)); end; {$OVERFLOWCHECKS OFF} {$OVERFLOWCHECKS ON} class operator TIntX.Explicit(value: TIntX): ShortInt; begin result := ShortInt(Integer(value)); end; {$OVERFLOWCHECKS OFF} {$OVERFLOWCHECKS ON} class operator TIntX.Explicit(value: TIntX): SmallInt; begin result := SmallInt(Integer(value)); end; {$OVERFLOWCHECKS OFF} {$OVERFLOWCHECKS ON} class operator TIntX.Explicit(value: TIntX): Word; begin result := Word(Integer(value)); end; {$OVERFLOWCHECKS OFF} class operator TIntX.Explicit(value: TIntX): Integer; var res: Integer; begin res := Integer(UInt32(value)); if value._negative then result := -res else result := res end; class operator TIntX.Explicit(value: TIntX): UInt32; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create('value'); if (value._length = 0) then begin result := 0; Exit; end; result := value._digits[0]; end; class operator TIntX.Explicit(value: TIntX): Int64; var res: Int64; begin res := Int64(UInt64(value)); if value._negative then result := -res else result := res end; class operator TIntX.Explicit(value: TIntX): UInt64; var res: UInt64; begin res := UInt32(value); if (value._length > 1) then begin res := res or UInt64(value._digits[1]) shl TConstants.DigitBitCount; end; result := res; end; class operator TIntX.Explicit(value: TIntX): Double; begin result := value.AsDouble; end; class function TIntX.Multiply(int1: TIntX; int2: TIntX; mode: TMultiplyMode): TIntX; begin result := TMultiplyManager.GetMultiplier(mode).Multiply(int1, int2); end; class function TIntX.Divide(int1: TIntX; int2: TIntX; mode: TDivideMode): TIntX; var modRes: TIntX; begin result := TDivideManager.GetDivider(mode).DivMod(int1, int2, modRes, TDivModResultFlags.dmrfDiv); end; class function TIntX.Modulo(int1: TIntX; int2: TIntX; mode: TDivideMode): TIntX; var modRes: TIntX; begin TDivideManager.GetDivider(mode).DivMod(int1, int2, modRes, TDivModResultFlags.dmrfMod); result := modRes; end; class function TIntX.DivideModulo(int1: TIntX; int2: TIntX; out modRes: TIntX): TIntX; begin result := TDivideManager.GetCurrentDivider().DivMod(int1, int2, modRes, TDivModResultFlags(Ord(TDivModResultFlags.dmrfDiv) or Ord(TDivModResultFlags.dmrfMod))); end; class function TIntX.DivideModulo(int1: TIntX; int2: TIntX; out modRes: TIntX; mode: TDivideMode): TIntX; begin result := TDivideManager.GetDivider(mode).DivMod(int1, int2, modRes, TDivModResultFlags(Ord(TDivModResultFlags.dmrfDiv) or Ord(TDivModResultFlags.dmrfMod))); end; class function TIntX.Random(): TIntX; begin result := TOpHelper.Random(); end; class function TIntX.RandomRange(Min: UInt32; Max: UInt32): TIntX; begin result := TOpHelper.RandomRange(Min, Max); end; class function TIntX.AbsoluteValue(value: TIntX): TIntX; begin // Exception if CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' value'); result := TOpHelper.AbsoluteValue(value); end; class function TIntX.Log10(value: TIntX): Double; begin // Exception if CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' value'); result := TOpHelper.Log10(value); end; class function TIntX.Ln(value: TIntX): Double; begin // Exception if CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' value'); result := TOpHelper.Ln(value); end; class function TIntX.LogN(base: Double; value: TIntX): Double; begin // Exception if CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' value'); result := TOpHelper.LogN(base, value); end; class function TIntX.IntegerLogN(base: TIntX; number: TIntX): TIntX; begin // Exceptions if CompareRecords(base, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' base'); if CompareRecords(number, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' number'); if ((base = 0) or (number = 0)) then raise EArgumentException.Create(uStrings.LogCantComputeZero); if ((base._negative) or (number._negative)) then raise EArgumentException.Create(uStrings.LogNegativeNotAllowed); result := TOpHelper.IntegerLogN(base, number); end; class function TIntX.Square(value: TIntX): TIntX; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; result := TOpHelper.Square(value); end; class function TIntX.IntegerSquareRoot(value: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(value, Default (TIntX)) then begin raise EArgumentNilException.Create('value'); end; if value._negative then raise EArgumentException.Create(NegativeSquareRoot + ' value'); result := TOpHelper.IntegerSquareRoot(value); end; class function TIntX.Factorial(value: TIntX): TIntX; begin // Exception if CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create(uStrings.CantBeNull + ' value'); result := TOpHelper.Factorial(value); end; class function TIntX.GCD(int1: TIntX; int2: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(int1, Default (TIntX)) then raise EArgumentNilException.Create('int1'); if TIntX.CompareRecords(int2, Default (TIntX)) then raise EArgumentNilException.Create('int2'); result := TOpHelper.GCD(int1, int2); end; class function TIntX.LCM(int1: TIntX; int2: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(int1, Default (TIntX)) then raise EArgumentNilException.Create('int1'); if TIntX.CompareRecords(int2, Default (TIntX)) then raise EArgumentNilException.Create('int2'); result := TOpHelper.LCM(int1, int2); end; class function TIntX.InvMod(int1: TIntX; int2: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(int1, Default (TIntX)) then raise EArgumentNilException.Create('int1'); if TIntX.CompareRecords(int2, Default (TIntX)) then raise EArgumentNilException.Create('int2'); if ((int1._negative) or (int2._negative)) then raise EArgumentException.Create(uStrings.InvModNegativeNotAllowed); result := TOpHelper.InvMod(int1, int2); end; class function TIntX.ModPow(value: TIntX; exponent: TIntX; modulus: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create('value'); if TIntX.CompareRecords(exponent, Default (TIntX)) then raise EArgumentNilException.Create('exponent'); if TIntX.CompareRecords(modulus, Default (TIntX)) then raise EArgumentNilException.Create('modulus'); if modulus <= 0 then raise EArgumentException.Create(uStrings.ModPowModulusCantbeZeroorNegative); if (exponent._negative) then raise EArgumentException.Create(uStrings.ModPowExponentCantbeNegative); result := TOpHelper.ModPow(value, exponent, modulus); end; class function TIntX.Bezoutsidentity(int1: TIntX; int2: TIntX; out bezOne: TIntX; out bezTwo: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(int1, Default (TIntX)) then raise EArgumentNilException.Create('int1'); if TIntX.CompareRecords(int2, Default (TIntX)) then raise EArgumentNilException.Create('int2'); result := TOpHelper.Bezoutsidentity(int1, int2, bezOne, bezTwo); end; class function TIntX.IsProbablyPrime(value: TIntX; Accuracy: Integer = 5): Boolean; begin // Exception if TIntX.CompareRecords(value, Default (TIntX)) then raise EArgumentNilException.Create('value'); result := TOpHelper.IsProbablyPrime(value, Accuracy); end; class function TIntX.Max(left: TIntX; right: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(left, Default (TIntX)) then raise EArgumentNilException.Create('left'); if TIntX.CompareRecords(right, Default (TIntX)) then raise EArgumentNilException.Create('right'); result := TOpHelper.Max(left, right); end; class function TIntX.Min(left: TIntX; right: TIntX): TIntX; begin // Exceptions if TIntX.CompareRecords(left, Default (TIntX)) then raise EArgumentNilException.Create('left'); if TIntX.CompareRecords(right, Default (TIntX)) then raise EArgumentNilException.Create('right'); result := TOpHelper.Min(left, right); end; class function TIntX.Pow(value: TIntX; power: UInt32): TIntX; begin result := TOpHelper.Pow(value, power, TIntX.GlobalSettings.multiplyMode); end; class function TIntX.Pow(value: TIntX; power: UInt32; multiplyMode: TMultiplyMode): TIntX; begin result := TOpHelper.Pow(value, power, multiplyMode); end; function TIntX.ToString(): String; begin result := ToString(UInt32(10), true); end; function TIntX.ToString(numberBase: UInt32): String; begin result := ToString(numberBase, true); end; function TIntX.ToString(numberBase: UInt32; UpperCase: Boolean): String; var tempCharArray: TIntXLibCharArray; begin if UpperCase then tempCharArray := TConstants.FBaseUpperChars else begin tempCharArray := TConstants.FBaseLowerChars; end; result := TStringConvertManager.GetStringConverter(Settings.ToStringMode) .ToString(Self, numberBase, tempCharArray); end; function TIntX.ToString(numberBase: UInt32; const alphabet: String): String; begin TStrRepHelper.AssertAlphabet(alphabet, numberBase); result := TStringConvertManager.GetStringConverter(Settings.ToStringMode) .ToString(Self, numberBase, TStrRepHelper.ToCharArray(alphabet)); end; function TIntX.AsDouble: Double; const infinityLength = Integer(1024 div 32); DoublePositiveInfinity: Double = 1.0 / 0.0; DoubleNegativeInfinity: Double = -1.0 / 0.0; var man, h, m, l: UInt64; exp, sign, lLength, z: Integer; // reg: TOpHelper.TBuilder; bits: TIntXLibUInt32Array; begin // Exception if TIntX.CompareRecords(Self, Default (TIntX)) then raise EArgumentNilException.Create('value'); // sign := 1; // reg := TOpHelper.TBuilder.Create(Self, sign); // reg.GetApproxParts(exp, man); // result := TOpHelper.GetDoubleFromParts(sign, exp, man); bits := Self._digits; lLength := Self._length; if Self.IsZero then begin result := 0; Exit; end; if Self.IsNegative then begin sign := -1 end else begin sign := 1; end; if (lLength > infinityLength) then begin if sign = 1 then begin result := DoublePositiveInfinity; Exit; end else begin result := DoubleNegativeInfinity; Exit; end; end; h := bits[lLength - 1]; if lLength > 1 then m := bits[lLength - 2] else m := 0; if lLength > 2 then l := bits[lLength - 3] else l := 0; // measure the exact bit count z := TOpHelper.CbitHighZero(UInt32(h)); exp := ((lLength - 2) * 32) - z; // extract most significant bits man := (h shl (32 + z)) or (m shl z) or (l shr (32 - z)); result := TOpHelper.GetDoubleFromParts(sign, exp, man); end; function TIntX.AsInteger: Integer; var res: Integer; begin // Exception if TIntX.CompareRecords(Self, Default (TIntX)) then raise EArgumentNilException.Create('value'); if (Self._length = 0) then begin result := 0; Exit; end; if ((Self._length > 1) or (Self._digits[0] > UInt32(TConstants.MaxIntValue))) then raise EOverflowException.Create(uStrings.OverFlow_Data); res := Integer(Self._digits[0]); if Self._negative then result := -res else result := res; end; function TIntX.AsUInt32: UInt32; begin // Exception if TIntX.CompareRecords(Self, Default (TIntX)) then raise EArgumentNilException.Create('value'); if (Self._length = 0) then begin result := 0; Exit; end; if ((Self._length > 1) or (Self._negative)) then raise EOverflowException.Create(uStrings.OverFlow_Data); result := Self._digits[0]; end; function TIntX.AsInt64: Int64; var res: UInt64; begin // Exception if TIntX.CompareRecords(Self, Default (TIntX)) then raise EArgumentNilException.Create('value'); if (Self._length = 0) then begin result := 0; Exit; end; if (Self._length > 2) then raise EOverflowException.Create(uStrings.OverFlow_Data); res := Self._digits[0]; if (Self._length > 1) then begin res := res or (UInt64(Self._digits[1]) shl TConstants.DigitBitCount); end; {$WARNINGS OFF} if res > (TConstants.MinInt64Value) then begin raise EOverflowException.Create(uStrings.OverFlow_Data); end; if ((res = TConstants.MinInt64Value) and (not Self._negative)) then begin raise EOverflowException.Create(uStrings.OverFlow_Data); end; {$WARNINGS ON} if Self._negative then result := -Int64(res) else result := Int64(res); end; function TIntX.AsUInt64: UInt64; var res: UInt64; begin // Exception if TIntX.CompareRecords(Self, Default (TIntX)) then raise EArgumentNilException.Create('value'); if (Self._length = 0) then begin result := 0; Exit; end; if (((Self._length) > 2) or (Self._negative)) then raise EOverflowException.Create(uStrings.OverFlow_Data); res := Self._digits[0]; if (Self._length > 1) then begin res := res or (UInt64(Self._digits[1]) shl TConstants.DigitBitCount); end; result := res; end; class function TIntX.Parse(const value: String): TIntX; begin result := TParseManager.GetCurrentParser().Parse(value, UInt32(10), TConstants.FBaseCharToDigits, true); end; class function TIntX.Parse(const value: String; numberBase: UInt32): TIntX; begin result := TParseManager.GetCurrentParser().Parse(value, numberBase, TConstants.FBaseCharToDigits, false); end; class function TIntX.Parse(const value: String; numberBase: UInt32; const alphabet: String): TIntX; var LCharDigits: TDictionary; begin LCharDigits := TStrRepHelper.CharDictionaryFromAlphabet(alphabet, numberBase); try result := TParseManager.GetCurrentParser().Parse(value, numberBase, LCharDigits, false); finally LCharDigits.Free; end; end; class function TIntX.Parse(const value: String; mode: TParseMode): TIntX; begin result := TParseManager.GetParser(mode).Parse(value, UInt32(10), TConstants.FBaseCharToDigits, true); end; class function TIntX.Parse(const value: String; numberBase: UInt32; mode: TParseMode): TIntX; begin result := TParseManager.GetParser(mode).Parse(value, numberBase, TConstants.FBaseCharToDigits, false); end; class function TIntX.Parse(const value: String; numberBase: UInt32; const alphabet: String; mode: TParseMode): TIntX; var LCharDigits: TDictionary; begin LCharDigits := TStrRepHelper.CharDictionaryFromAlphabet(alphabet, numberBase); try result := TParseManager.GetParser(mode).Parse(value, numberBase, LCharDigits, false); finally LCharDigits.Free; end; end; function TIntX.Equals(n: TIntX): Boolean; begin result := Self = n; end; function TIntX.Equals(n: Integer): Boolean; begin result := Self = n; end; function TIntX.Equals(n: UInt32): Boolean; begin result := Self = n; end; function TIntX.Equals(n: Int64): Boolean; begin result := Self = n; end; function TIntX.Equals(n: UInt64): Boolean; begin result := Self = n; end; function TIntX.CompareTo(n: TIntX): Integer; begin result := TOpHelper.Cmp(Self, n, true); end; function TIntX.CompareTo(n: Integer): Integer; begin result := TOpHelper.Cmp(Self, n); end; function TIntX.CompareTo(n: UInt32): Integer; begin result := TOpHelper.Cmp(Self, n); end; function TIntX.CompareTo(n: Int64): Integer; begin result := TOpHelper.Cmp(Self, n, true); end; function TIntX.CompareTo(n: UInt64): Integer; begin result := TOpHelper.Cmp(Self, n, true); end; procedure TIntX.Normalize(); var newDigits: TIntXLibUInt32Array; begin if (UInt32(Length(_digits)) > _length) then begin SetLength(newDigits, _length); Move(_digits[0], newDigits[0], _length * SizeOf(UInt32)); _digits := newDigits; end; if (_length = 0) then begin _negative := false; end; end; procedure TIntX.GetInternalState(out digits: TIntXLibUInt32Array; out negative: Boolean; out zeroinithelper: Boolean); begin SetLength(digits, _length); Move(_digits[0], digits[0], _length * SizeOf(UInt32)); negative := _negative; zeroinithelper := _zeroinithelper; end; procedure TIntX.InitFromZero(); begin _length := 0; SetLength(_digits, 0); _zeroinithelper := true; _negative := false; end; procedure TIntX.InitFromUlong(value: UInt64); var low, high: UInt32; begin // Divide uint64 into 2 uint32 values low := UInt32(value); high := UInt32(value shr TConstants.DigitBitCount); // Prepare internal fields if (high = 0) then begin SetLength(_digits, 1); _digits[0] := low; end else begin SetLength(_digits, 2); _digits[0] := low; _digits[1] := high; end; _length := UInt32(Length(_digits)); end; procedure TIntX.InitFromIntX(value: TIntX); begin _digits := value._digits; _length := value._length; _negative := value._negative; _zeroinithelper := value._zeroinithelper; end; procedure TIntX.InitFromDigits(digits: TIntXLibUInt32Array; negative: Boolean; mlength: UInt32); begin _length := mlength; SetLength(_digits, _length); Move(digits[0], _digits[0], mlength * SizeOf(UInt32)); if (mlength <> 0) then begin _negative := negative; end; end; procedure TIntX.TryNormalize(); begin if (Settings.AutoNormalize) then begin Normalize(); end; end; end.