diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h index b4336529..aeca177b 100644 --- a/mpir.net/mpir.net/HugeFloat.h +++ b/mpir.net/mpir.net/HugeFloat.h @@ -1,1378 +1,1378 @@ -/* -Copyright 2014 Alex Dyachenko - -This file is part of the MPIR Library. - -The MPIR Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published -by the Free Software Foundation; either version 3 of the License, or (at -your option) any later version. - -The MPIR Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the MPIR Library. If not, see http://www.gnu.org/licenses/. -*/ - -#pragma once - -using namespace System; -using namespace System::IO; -using namespace System::Runtime::InteropServices; - -#ifdef SPECIALIZE_EXPRESSIONS -#undef SPECIALIZE_EXPRESSIONS -#undef MP -#undef CUSTOM_MP -#undef MPSTRUCT -#undef MPTYPE -#undef MPTYPE_NAME -#undef MPEXPR_NAME -#undef MPEXPR -#undef CTXT -#undef CTXTI -#undef ASSIGN_TO -#undef Mpt -#undef SET_CONTEXT_PRECISION -#endif -#define SPECIALIZE_EXPRESSIONS -#define Mpt Flt -#define CUSTOM_MP(x) custom_mpf_##x -#define MPSTRUCT __mpf_struct -#define MP(x) mpf_##x -#define MPTYPE HugeFloat -#define MPTYPE_NAME Float -#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression -#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression -#define CTXT(x) context.FloatArgs[x] -#define CTXTI(x) context.IntArgs[x] -#define CTXTR(x) context.RationalArgs[x] -#define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) -#define SET_CONTEXT_PRECISION context.FloatPrecision = mpf_get_prec(destination); -#include "ExpressionMacros.h" - -namespace MPIR -{ - ref class MpirRandom; - ref class MPTYPE; - - #pragma region FloatExpression - - /// - /// Base class for all float expressions resulting from many float operations on MPIR types. - /// Expressions can be arbitrarily nested, and are lazily evaluated - /// when they are either assigned to the Value property of an MPIR object, or are consumed by a function or operator that returns a primitive type. - /// Assignment to the Value property is necessary because .Net does not support overloading the assignment operator. - /// - public ref class MPEXPR_NAME abstract : public IComparable, IComparable, IEquatable - { - internal: - MPEXPR_NAME() { } - virtual void AssignTo(MP(ptr) destination) abstract; - virtual void ASSIGN_TO(EvaluationContext& context) - { - context.Initialized(FloatInitialized); - auto ptr = &context.Temp[context.Index].MPTYPE_NAME; - CTXT(context.Index++) = ptr; - MP(init2)(ptr, context.FloatPrecision); - AssignTo(ptr); - } - - private: - int CompareTo(Object^ a, bool& valid); - - public: - #pragma region Arithmetic - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_ui b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (mpir_ui a, MPEXPR_NAME^ b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_si b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (mpir_si a, MPEXPR_NAME^ b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_ui b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (mpir_ui a, MPEXPR_NAME^ b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_si b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (mpir_si a, MPEXPR_NAME^ b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, mpir_ui b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator * (mpir_ui a, MPEXPR_NAME^ b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, mpir_si b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator * (mpir_si a, MPEXPR_NAME^ b); - - /// Shifts the source operand to the left by , i.e. multiplies by 2^. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Number of bits to shift by, i.e. power of 2 to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator << (MPEXPR_NAME^ a, mp_bitcnt_t bits); - - /// Shifts the source operand to the right by , i.e. divides by 2^. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide - /// Number of bits to shift by, i.e. power of 2 to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - static MPEXPR_NAME^ operator >> (MPEXPR_NAME^ a, mp_bitcnt_t bits); - - /// Negates the source value. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to negate - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, mpir_ui b); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - static MPEXPR_NAME^ operator / (mpir_ui a, MPEXPR_NAME^ b); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, mpir_si b); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - static MPEXPR_NAME^ operator / (mpir_si a, MPEXPR_NAME^ b); - - /// Raises the source value to the specified power. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Power to raise to - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, mpir_ui power); - - #pragma endregion - - #pragma region Math - - /// Computes the absolute value of the source number. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Abs(); - - /// Computes the square root of the source number. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ SquareRoot(); - - /// Rounds the source number down to the next integer. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Floor(); - - /// Rounds the source number up to the next integer. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Ceiling(); - - /// Rounds the source number to the next integer toward zero. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Truncate(); - - #pragma endregion - - #pragma region Comparisons - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// The precision of the calculation is the precision of this instance if it is a computed number, otherwise the precision of if that is a computed number, - /// otherwise the current default float precision. - /// When the argument is a double, it may be an infinity, but results are undefined for a NaN. - /// Value to compare the source with - /// A positive number if the source is greater than , negative if less, and zero if they are equal. - virtual int CompareTo(Object^ a) sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// The precision of the calculation is the precision of this instance if it is a computed number, otherwise the precision of if that is a computed number, - /// otherwise the current default float precision if both are expressions. - /// Value to compare the source with - /// A positive number if the source is greater than , negative if less, and zero if they are equal. - virtual int CompareTo(MPEXPR_NAME^ a) sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Value to compare the source with - /// true if the values of the source and are equal, false otherwise. - virtual bool Equals(MPEXPR_NAME^ a) sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// When the argument is a double, it may be an infinity, but results are undefined for a NaN. - /// Value to compare the source with. This can be a multi-precision number, an expression, or a supported primitive type (long, ulong, or double). - /// true if the values of the source and are equal, false otherwise. - virtual bool Equals(Object^ a) override sealed; - - /// Compares two numbers approximately, taking into account most significant bits of the mantissa. - /// If any argument is an expression, it is evaluated into a temporary variable with the specified before the comparison is performed. - /// In the future values like 1000 and 0111 may be considered the same to 3 bits (on the basis that their difference is that small). - /// - /// Value to compare the source with - /// The number of most significant bits that must match for the two numbers to be considered equal - /// true if the values of the source and are equal to , false otherwise. - bool Equals(MPEXPR_NAME^ a, mp_bitcnt_t precision) { IN_SPECIFIC_CONTEXT(precision, this, a); return MP(eq)(CTXT(0), CTXT(1), precision) != 0; } - - /// Computes the hash code of the source value. - /// If called on an expression, it is evaluated into a temporary variable with the current default float precision before the calculation is performed. - /// Multi-precision classes are mutable with value semantics. The hash code is based on the value, and will change if the value changes. - /// For this reason, the value of an object must not be modified while the object is contained in a hash table. - /// a signed integer hash code for the value. - virtual int GetHashCode() override sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Can be called with an infinity, but results are undefined for a NaN. - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Calculates the sign (+1, 0, or -1) of the source value. - /// If the source is an expression, it is evaluated into a temporary variable with the current default float precision before the sign is computed. - /// - /// +1 if the source is positive, -1 if negative, and 0 if zero. - int Sign(); - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// The result equals | source - a | / source. - /// Source value to compare with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ RelativeDifferenceFrom(MPEXPR_NAME^ a); - - #pragma endregion - }; - - #pragma endregion - - #pragma region concrete expressions - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Add, Flt) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Flt, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Flt, Si) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Flt) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Flt, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Flt) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Flt, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Flt) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Multiply, Flt) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Flt, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Flt, Si) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Divide, Flt) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Flt, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Ui, Flt) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Flt, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Si, Flt) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Flt, Bits) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftRight, Flt, Bits) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Flt, Ui) - - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Flt) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Flt) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, SquareRoot, Flt) - DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, SquareRoot, Ui) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, RelativeDifferenceFrom, Flt) - - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Floor, Flt) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Ceiling, Flt) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Truncate, Flt) - - DEFINE_UNARY_EXPRESSION (MPEXPR_NAME, Random, MpirRandom^) - DEFINE_BINARY_EXPRESSION (MPEXPR_NAME, RandomBits, MpirRandom^, mp_bitcnt_t) - DEFINE_BINARY_EXPRESSION (MPEXPR_NAME, RandomChunky, MpirRandom^, mp_exp_t) - DEFINE_TERNARY_EXPRESSION (MPEXPR_NAME, RandomLimbsChunky, MpirRandom^, mp_size_t, mp_exp_t) - - #pragma endregion - - #pragma region HugeFloat class - - /// - /// Multi-precision Float class. - /// - public ref class MPTYPE : MPEXPR_NAME - { - internal: - //fields - MP(ptr) _value; - mp_bitcnt_t _allocatedPrecision; - - private: - //construction - void AllocateStruct() - { - _value = (MP(ptr))((*__gmp_allocate_func)(sizeof(MPSTRUCT))); - } - void FromString(String^ value, int base, bool exponentInDecimal); - MPTYPE(bool initialize); - String^ ToString(int base, bool lowercase, int maxDigits, bool exponentInDecimal); - - internal: - virtual void DeallocateStruct() - { - MP(set_prec_raw)(_value, _allocatedPrecision); - MP(clear)(_value); - (*__gmp_free_func)(_value, sizeof(MPSTRUCT)); - _value = nullptr; - } - - //assignment - virtual void AssignTo(MP(ptr) destination) override - { - if(destination != _value) - MP(set)(destination, _value); - } - virtual void ASSIGN_TO(EvaluationContext& context) override - { - CTXT(context.Index++) = _value; - } - - public: - #pragma region construction and disposal - - static MPTYPE() - { - DefaultPrecision = sizeof(mpir_ui) * 8 * 2; //2 limbs - } - - /// - /// Gets or sets the default precision of a float variable in bits. - /// The actual precision may be slightly greater if the value is not a whole limb multiple. - /// All subsequently constructed variables will use this precision, but previously constructed variables are unaffected. - /// The initial default value is 2 limbs. - /// - static property mp_bitcnt_t DefaultPrecision - { - mp_bitcnt_t get() { return MP(get_default_prec)(); } - void set(mp_bitcnt_t value) { MP(set_default_prec)(value); } - } - - /// - /// Initializes a new float instance and sets its value to 0. - /// The precision of the new variable's mantissa is set from the static DefaultPrecision property. - /// - MPTYPE(); - - /// - /// Initializes a new float instance, allocating enough memory to hold at least bits, and sets its value to 0. - /// All float operations are performed to the precision of the destination. - /// - /// Minimum number of bits the initially allocated memory should hold for the mantissa - /// the newly constructed instance - static MPTYPE^ Allocate(mp_bitcnt_t precision); - - /// - /// Initializes a new float instance and sets its value from the specified string. - /// No leading base characters are allowed. - /// The exponent is always in decimal. - /// - /// string representing the initial value for the new instance. Whitespace in the string is ignored. - MPTYPE(String^ value) { FromString(value, 0, true); } - - /// - /// Initializes a new float instance and sets its value from the specified string - /// - /// string representing the initial value for the new instance. Whitespace in the string is ignored. - /// base the string is in. - /// The base may vary from 2 to 62. No leading base characters are allowed. The exponent is always in decimal - /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. - /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. - MPTYPE(String^ value, int base) { FromString(value, base, true); } - - /// - /// Initializes a new float instance and sets its value from the specified string - /// - /// string representing the initial value for the new instance. Whitespace in the string is ignored. - /// base the string is in. - /// The base may vary from 2 to 62. No leading base characters are allowed. - /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. - /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. - /// True if the exponent is in decimal, false to use the same base as the mantissa. - MPTYPE(String^ value, int base, bool exponentInDecimal) { FromString(value, base, exponentInDecimal); } - - /// - /// Initializes a new float instance and sets its value to the result of computing the source expression. - /// - /// the expression that will be computed, and the result set as the initial value of the new instance. - MPTYPE(MPEXPR_NAME^ value); - - /// - /// Initializes a new float instance and sets its value to the result of computing the source expression. - /// - /// the expression that will be computed, and the result set as the initial value of the new instance. - MPTYPE(IntegerExpression^ value); - - /// - /// Initializes a new float instance and sets its value to the result of computing the source expression. - /// - /// the expression that will be computed, and the result set as the initial value of the new instance. - MPTYPE(RationalExpression^ value); - - /// - /// Constructs and returns a new float instance with its value set to . - /// - /// value for the initial value for the new float instance - MPTYPE(mpir_si value); - - /// - /// Constructs and returns a new float instance with its value set to . - /// - /// value for the initial value for the new float instance - MPTYPE(mpir_ui value); - - /// - /// Constructs and returns a new float instance with its value set to the parameter. - /// There is no rounding, this conversion is exact. - /// - /// Initial value for the new float instance. This is an exact conversion. - MPTYPE(double value); - - //disposal - - //creating a destructor in C++ implements IDisposable. - - /// - /// Frees all memory allocated by the instance. - /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. - /// - ~MPTYPE() { this->!MPTYPE(); } - - /// - /// Frees all memory allocated by the instance. - /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. - /// - !MPTYPE() { if(_value != 0) DeallocateStruct(); } - - #pragma endregion - - #pragma region conversions - - /// - /// Converts the number to a string. - /// To avoid debugging performance problems, this method outputs at most the number of digits specified in MpirSettings.ToStringDigits. - /// If the number is larger, the least significant digits are shown with a leading ellipsis (i.e., [-]...NNNNN) - /// Setting MpirSettings.ToStringDigits to 0 removes the upper limit. - /// - /// A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits. - virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits, false); } - - /// - /// Converts the number to a string in the specified base. - /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. - /// - /// The base to use for the output. The base can be from 2 to 62; uppercase letters represent digits 10-35 and lowercase letters represent digits 36-61. - /// A string representation of the number in the specified base. - String^ ToString(int base) { return ToString(base, false, 0, false); } - - /// - /// Converts the number to a string in the specified base. - /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. - /// - /// The base to use for the output. - /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. - /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// Indicates if lowercase or uppercase letters should be used for the output. - /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. - /// A string representation of the number in the specified base. - String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0, false); } - - /// - /// Converts the number to a string in the specified base. - /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. - /// - /// The base to use for the output. - /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. - /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// Indicates if lowercase or uppercase letters should be used for the output. - /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. - /// True to always show the exponent in decimal, False to use the same base as the mantissa - /// A string representation of the number in the specified base. - String^ ToString(int base, bool lowercase, bool exponentInDecimal) { return ToString(base, lowercase, 0, exponentInDecimal); } - -#if BITS_PER_MP_LIMB == 64 - /// - /// Returns the absolute value of the number as a ulong, truncating any fractional part. - /// If the number is too big, the result is undefined. Call FitsUlong() to check if the number will fit. - /// The sign of the number is ignored, only the absolute value is used. - /// This method is supported only on 64-bit builds - /// - /// The absolute value as a ulong, with any fractional part truncated. - mpir_ui ToUlong() { return MP(get_ui)(_value); } - - /// - /// Returns the value of the number as a long. - /// If the number is too big, the result is undefined. Call FitsLong() to check if the number will fit. - /// This method is supported only on 64-bit builds - /// - /// The value as a long, with any fractional part truncated. - mpir_si ToLong() { return MP(get_si)(_value); } -#else - /// - /// Returns the absolute value of the number as a uint, truncating any fractional part. - /// If the number is too big, the result is undefined. Call FitsUint() to check if the number will fit. - /// The sign of the number is ignored, only the absolute value is used. - /// This method is supported only on 32-bit builds - /// - /// The absolute value as a uint, with any fractional part truncated. - mpir_ui ToUint() { return MP(get_ui)(_value); } - - /// - /// Returns the value of the number as an int. - /// If the number is too big, the result is undefined. Call FitsInt() to check if the number will fit. - /// This method is supported only on 32-bit builds - /// - /// The value as an int, with any fractional part truncated. - mpir_si ToInt() { return MP(get_si)(_value); } -#endif - - /// - /// Returns the value of the number as a double, truncating if necessary (rounding towards zero). - /// If the exponent from the conversion is too big, the result is system dependent. An infinity is returned where available. - /// A hardware overflow trap may or may not occur. - /// - /// The value as a double, possibly truncated. - double ToDouble() { return MP(get_d)(_value); } - - /// - /// Returns the value of the number as a double, truncating if necessary (rounding towards zero), and returning the exponent separately. - /// The return is the mantissa, its absolute value will be in the range [0.5 - 1). - - /// The exponent is binary, i.e. mantissa * 2^exp is the value of the source number. - /// If the source value is zero, both mantissa and exponent are returned as 0. - /// - /// variable to store the exponent in. - /// The mantissa of the value as a double, possibly truncated. - double ToDouble([Out] mpir_si% exp) - { - double x; - exp = MP(get_2exp_d)(&x, _value); - return x; - } - - #pragma endregion - - #pragma region assignment - - /// - /// When getting, returns this float. - /// When setting, sets the value of the float object to the value resulting from computing the supplied expression. - /// The getter is a no-op and never needs to be invoked directly, but makes compound operators such as +=, *=, etc. possible. - /// Do not set the Value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// - /// MPIR types are implemented as reference types with value semantics. - /// Like Strings, the objects themselves are just lightweight pointers to data allocated elsewhere. - /// Unlike Strings, MPIR types are mutable. - /// Value semantics requires you to be able to code, a = b + c. - /// However, .Net (outside of C++) does not allow overloading the assignment operator, - /// and assigning references would necessitate some unnecessary duplication and extra memory allocations. - /// To solve this problem, MPIR.Net uses the property assignment. - /// The setter of the Value property does what an overloaded assignment operator would do in C++. - /// The syntax is a little different: a.Value = b + c, but it is fluent enough to become a quick habit, - /// and additionally reinforces the concept that an existing object can change its value while reusing internally allocated memory. - /// To this end, all overloaded operators and most functions that operate on MPIR types, - /// instead of eagerly computing a result, produce and return an expression that is basically a formula for the computation. - /// Expressions can then be composed using additional operators to achieve expression trees of arbitrary complexity. - /// All computations are deferred until an expression is assigned to the Value property of an MPIR object, - /// consumed by a method or operator that returns a primitive type, - /// or supplied as an argument to an MPIR type constructor. - /// The getter is a no-op defined to make possible constructs such as a.Value += 5, a.Value *= 10, etc. - /// Direct assignments such as a = b + c, a *= 10 will not compile because there is no implicit conversion from an expression. - /// Even if an implicit conversion were defined, such code would incur an extra allocation plus garbage collection, - /// and would not perform as well as doing the same operations on a.Value. - /// It would also not compile if the source were a "using" variable, as all method-local floats should be. - /// - property MPEXPR_NAME^ Value - { - void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); } - MPEXPR_NAME^ get() { return this; } - } - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// value for the new value for the object - void SetTo(mpir_ui value) { MP(set_ui)(_value, value); } - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// value for the new value for the object - void SetTo(mpir_si value) { MP(set_si)(_value, value); } - - /// - /// Sets the value of the float object. This is an exact conversion, there is no rounting. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(double value) { MP(set_d)(_value, value); } - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object. - /// May be an float or a pair of floats separated by a slash. - /// The string's leading characters may indicate base: - /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise - void SetTo(String^ value) { SetTo(value, 0); } - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - /// base the mantissa in the string is in. Exponent is always in decimcal. - /// The base may vary from 2 to 62. No leading leading base characters are allowed. - /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. - /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. - void SetTo(String^ value, int base) { SetTo(value, base, true); } - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// If the fraction is not in canonical form, Canonicalize() must be called. - /// - /// new value for the object - /// base the string is in. - /// The base may vary from 2 to 62. No leading leading base characters are allowed. - /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. - /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. - /// If true, the exponent is in decimal; otherwise it is in the same base as the mantissa - void SetTo(String^ value, int base, bool exponentInDecimal); - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(IntegerExpression^ value) - { - EvaluationContext context; - value->AssignToInteger(context); - MP(set_z)(_value, CTXTI(0)); - } - - /// - /// Sets the value of the float object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(RationalExpression^ value); - - /// - /// Swaps the values of two floats. - /// This operation is a pointer swap and doesn't affect allocated memory. - /// Do not call this method while either object is contained in a hash table, because this would change their hash codes. - /// - /// Source number to swap this instance's value with - void Swap(MPTYPE^ a) - { - MP(swap)(_value, a->_value); - - mp_bitcnt_t prec = a->_allocatedPrecision; - a->_allocatedPrecision = _allocatedPrecision; - _allocatedPrecision = prec; - } - - #pragma endregion - - #pragma region Size checks - - /// - /// Gets or sets the effective precision of the number without changing the memory allocated. - /// The number of bits cannot exceed the precision with which the variable was initialized or last reallocated. - /// The value of the number is unchanged, and in particular if it previously had a higher precision it will retain that higher precision. - /// New values assigned to the Value property will use the new precision. - /// This is an efficient way to use a float variable at different precisions during a calculation, - /// perhaps to gradually increase precision in an iteration, or just to use various different - /// precisions for different purposes during a calculation. - /// The number can be safely disposed after modifying its precision (this would not be the case in unmanaged MPIR). - /// - property mp_bitcnt_t Precision - { - mp_bitcnt_t get() { return MP(get_prec)(_value); } - void set(mp_bitcnt_t value) - { - if(value > _allocatedPrecision) - throw gcnew ArgumentException("Cannot set precision higher than allocated"); - - MP(set_prec_raw)(_value, value); - } - } - - /// - /// Gets the precision in bits that is currently allocated for internal storage of the mantissa. - /// The precision actually in effect, used in calculations, is initially the same but may be reduced by setting the Precision property. - /// However Precision cannot exceed AllocatedPrecision. - /// To change AllocatedPrecision, call Reallocate(). - /// The value actually allocated may be slightly more than the number of bits requested by Allocate() or Reallocate(). - /// - property mp_bitcnt_t AllocatedPrecision - { - mp_bitcnt_t get() { return _allocatedPrecision; } - } - - /// - /// Set the precision of this instance to be at least prec bits, reallocating its limbs data. - /// The value of this instance will be truncated to the new precision. - /// This function requires a call to realloc, and so should not be used in a tight loop. - /// - /// Minimum number of bits the allocated memory should hold for the mantissa. - void Reallocate(mp_bitcnt_t precision) - { - MP(set_prec_raw)(_value, _allocatedPrecision); - MP(set_prec)(_value, precision); - _allocatedPrecision = precision; - } - -#if BITS_PER_MP_LIMB == 64 - /// - /// Returns true if the value of the source number, if truncated to an integer, is in the long range. - /// This method is supported only on 64-bit builds - /// - /// true if the value will fit in a long - bool FitsLong() { return MP(fits_si_p)(_value) != 0; } - - /// - /// Returns true if the value of the source number, if truncated to an integer, is in the ulong range. - /// This method is supported only on 64-bit builds - /// - /// true if the value will fit in a long - bool FitsUlong() { return MP(fits_ui_p)(_value) != 0; } -#endif - - /// - /// Returns true if the value of the source number, if truncated to an integer, is in the int range. - /// - /// true if the value will fit in an int - bool FitsInt() { return MP(fits_sint_p)(_value) != 0; } - - /// - /// Returns true if the value of the source number, if truncated to an integer, is in the uint range. - /// - /// true if the value will fit in an int - bool FitsUint() { return MP(fits_uint_p)(_value) != 0; } - - /// - /// Returns true if the value of the source number, if truncated to an integer, is in the short range. - /// - /// true if the value will fit in a short - bool FitsShort() { return MP(fits_sshort_p)(_value) != 0; } - - /// - /// Returns true if the value of the source number, if truncated to an integer, is in the ushort range. - /// - /// true if the value will fit in a short - bool FitsUshort() { return MP(fits_ushort_p)(_value) != 0; } - - /// - /// Returns true if the source number is a whole integer. - /// - /// true if the value is an integer - bool IsInteger() { return MP(integer_p)(_value) != 0; } - - #pragma endregion - - #pragma region IO - - /// - /// Outputs the float to the as a string of digits in decimal. - /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not valid for this format. - /// This is because the Read method stops reading when it encounters an invalid character. - /// - /// Text writer to output the number to - /// the number of characters written - size_t Write(TextWriter^ writer) { return Write(writer, 10, 0, false, true); } - - /// - /// Outputs the float to the as a string of digits in base . - /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent in the same base. - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not valid for this format. - /// This is because the Read method stops reading when it encounters an invalid character. - /// - /// Text writer to output the number to - /// The base to use for the output. - /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// the number of characters written - size_t Write(TextWriter^ writer, int base) { return Write(writer, base, 0, false, true); } - - /// - /// Outputs the float to the as a string of digits in base . - /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not valid for this format. - /// This is because the Read method stops reading when it encounters an invalid character. - /// - /// Text writer to output the number to - /// Indicates if lowercase or uppercase letters should be used for the output. - /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. - /// The base to use for the output. - /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. - /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// the number of characters written - size_t Write(TextWriter^ writer, int base, bool lowercase) { return Write(writer, base, 0, lowercase, true); } - - /// - /// Outputs the float to the as a string of digits in base . - /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not valid for this format. - /// This is because the Read method stops reading when it encounters an invalid character. - /// - /// Text writer to output the number to - /// The base to use for the output. - /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. - /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// Indicates if lowercase or uppercase letters should be used for the output. - /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. - /// Whether the exponent should always be written in decimal, or use the same base as the mantissa. - /// Maximum number of digits for the mantissa. - /// No more digits than are accurately representable by the number's precision will be printed. - /// Use zero to select that accurate maximum. - /// the number of characters written - size_t Write(TextWriter^ writer, int base, int maxDigits, bool lowercase, bool exponentInDecimal); - - /// - /// Inputs the number as a possibly white-space preceeded string. - /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. - /// The mantissa and exponent are always in decimal, no leading base characters are allowed. - /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. - /// This method reads the output of a Write(TextWriter) when decimal base is used. - /// - /// Text reader to input the number from - /// the number of characters read - size_t Read(TextReader^ reader) { return Read(reader, 0, true); } - - /// - /// Inputs the number as a possibly white-space preceeded string. - /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. - /// The mantissa is always in the specified base, the exponent is always in decimal. No leading base characters are allowed. - /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. - /// This method reads the output of a Write(TextWriter) when decimal base is used. - /// - /// Text reader to input the number from - /// The base to use for the mantissa. - /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// For bases 36 and less, uppercase and lowercase letters are equivalent. - /// the number of characters read - size_t Read(TextReader^ reader, int base) { return Read(reader, base, true); } - - /// - /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. - /// The mantissa is always in the specified base, the exponent is either in the same base or in decimal. No leading base characters are allowed. - /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. - /// This method reads the output of a Write(TextWriter, ...) method with the same base. - /// - /// Text reader to input the number from - /// The base to use for the input. - /// The base can be from 2 to 62; For bases up to 36 case is ignored. - /// For bases larger than 36, uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// Whether the exponent should always be written in decimal, or use the same base as the mantissa. - /// the number of characters read - size_t Read(TextReader^ reader, int base, bool exponentInDecimal); - - #pragma endregion - - #pragma region Arithmetic - - /// Computes the square root of the source number. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// source number to take the square root of - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ SquareRoot(mpir_ui a) { return gcnew MPEXPR(SquareRootUi)(a); } - - #pragma endregion - }; - - #pragma endregion -}; +/* +Copyright 2014 Alex Dyachenko + +This file is part of the MPIR Library. + +The MPIR Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +The MPIR Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the MPIR Library. If not, see http://www.gnu.org/licenses/. +*/ + +#pragma once + +using namespace System; +using namespace System::IO; +using namespace System::Runtime::InteropServices; + +#ifdef SPECIALIZE_EXPRESSIONS +#undef SPECIALIZE_EXPRESSIONS +#undef MP +#undef CUSTOM_MP +#undef MPSTRUCT +#undef MPTYPE +#undef MPTYPE_NAME +#undef MPEXPR_NAME +#undef MPEXPR +#undef CTXT +#undef CTXTI +#undef ASSIGN_TO +#undef Mpt +#undef SET_CONTEXT_PRECISION +#endif +#define SPECIALIZE_EXPRESSIONS +#define Mpt Flt +#define CUSTOM_MP(x) custom_mpf_##x +#define MPSTRUCT __mpf_struct +#define MP(x) mpf_##x +#define MPTYPE HugeFloat +#define MPTYPE_NAME Float +#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression +#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression +#define CTXT(x) context.FloatArgs[x] +#define CTXTI(x) context.IntArgs[x] +#define CTXTR(x) context.RationalArgs[x] +#define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) +#define SET_CONTEXT_PRECISION context.FloatPrecision = mpf_get_prec(destination); +#include "ExpressionMacros.h" + +namespace MPIR +{ + ref class MpirRandom; + ref class MPTYPE; + + #pragma region FloatExpression + + /// + /// Base class for all float expressions resulting from many float operations on MPIR types. + /// Expressions can be arbitrarily nested, and are lazily evaluated + /// when they are either assigned to the Value property of an MPIR object, or are consumed by a function or operator that returns a primitive type. + /// Assignment to the Value property is necessary because .Net does not support overloading the assignment operator. + /// + public ref class MPEXPR_NAME abstract : public IComparable, IComparable, IEquatable + { + internal: + MPEXPR_NAME() { } + virtual void AssignTo(MP(ptr) destination) abstract; + virtual void ASSIGN_TO(EvaluationContext& context) + { + context.Initialized(FloatInitialized); + auto ptr = &context.Temp[context.Index].MPTYPE_NAME; + CTXT(context.Index++) = ptr; + MP(init2)(ptr, context.FloatPrecision); + AssignTo(ptr); + } + + private: + int CompareTo(Object^ a, bool& valid); + + public: + #pragma region Arithmetic + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_ui b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (mpir_ui a, MPEXPR_NAME^ b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_si b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (mpir_si a, MPEXPR_NAME^ b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_ui b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (mpir_ui a, MPEXPR_NAME^ b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_si b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (mpir_si a, MPEXPR_NAME^ b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, mpir_ui b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator * (mpir_ui a, MPEXPR_NAME^ b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, mpir_si b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator * (mpir_si a, MPEXPR_NAME^ b); + + /// Shifts the source operand to the left by , i.e. multiplies by 2^. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Number of bits to shift by, i.e. power of 2 to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator << (MPEXPR_NAME^ a, mp_bitcnt_t bits); + + /// Shifts the source operand to the right by , i.e. divides by 2^. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide + /// Number of bits to shift by, i.e. power of 2 to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + static MPEXPR_NAME^ operator >> (MPEXPR_NAME^ a, mp_bitcnt_t bits); + + /// Negates the source value. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to negate + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, mpir_ui b); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + static MPEXPR_NAME^ operator / (mpir_ui a, MPEXPR_NAME^ b); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, mpir_si b); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + static MPEXPR_NAME^ operator / (mpir_si a, MPEXPR_NAME^ b); + + /// Raises the source value to the specified power. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Power to raise to + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, mpir_ui power); + + #pragma endregion + + #pragma region Math + + /// Computes the absolute value of the source number. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Abs(); + + /// Computes the square root of the source number. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ SquareRoot(); + + /// Rounds the source number down to the next integer. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Floor(); + + /// Rounds the source number up to the next integer. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Ceiling(); + + /// Rounds the source number to the next integer toward zero. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Truncate(); + + #pragma endregion + + #pragma region Comparisons + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// The precision of the calculation is the precision of this instance if it is a computed number, otherwise the precision of if that is a computed number, + /// otherwise the current default float precision. + /// When the argument is a double, it may be an infinity, but results are undefined for a NaN. + /// Value to compare the source with + /// A positive number if the source is greater than , negative if less, and zero if they are equal. + virtual int CompareTo(Object^ a) sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// The precision of the calculation is the precision of this instance if it is a computed number, otherwise the precision of if that is a computed number, + /// otherwise the current default float precision if both are expressions. + /// Value to compare the source with + /// A positive number if the source is greater than , negative if less, and zero if they are equal. + virtual int CompareTo(MPEXPR_NAME^ a) sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Value to compare the source with + /// true if the values of the source and are equal, false otherwise. + virtual bool Equals(MPEXPR_NAME^ a) sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// When the argument is a double, it may be an infinity, but results are undefined for a NaN. + /// Value to compare the source with. This can be a multi-precision number, an expression, or a supported primitive type (long, ulong, or double). + /// true if the values of the source and are equal, false otherwise. + virtual bool Equals(Object^ a) override sealed; + + /// Compares two numbers approximately, taking into account most significant bits of the mantissa. + /// If any argument is an expression, it is evaluated into a temporary variable with the specified before the comparison is performed. + /// In the future values like 1000 and 0111 may be considered the same to 3 bits (on the basis that their difference is that small). + /// + /// Value to compare the source with + /// The number of most significant bits that must match for the two numbers to be considered equal + /// true if the values of the source and are equal to , false otherwise. + bool Equals(MPEXPR_NAME^ a, mp_bitcnt_t precision) { IN_SPECIFIC_CONTEXT(precision, this, a); return MP(eq)(CTXT(0), CTXT(1), precision) != 0; } + + /// Computes the hash code of the source value. + /// If called on an expression, it is evaluated into a temporary variable with the current default float precision before the calculation is performed. + /// Multi-precision classes are mutable with value semantics. The hash code is based on the value, and will change if the value changes. + /// For this reason, the value of an object must not be modified while the object is contained in a hash table. + /// a signed integer hash code for the value. + virtual int GetHashCode() override sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Can be called with an infinity, but results are undefined for a NaN. + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Calculates the sign (+1, 0, or -1) of the source value. + /// If the source is an expression, it is evaluated into a temporary variable with the current default float precision before the sign is computed. + /// + /// +1 if the source is positive, -1 if negative, and 0 if zero. + int Sign(); + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// The result equals | source - a | / source. + /// Source value to compare with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ RelativeDifferenceFrom(MPEXPR_NAME^ a); + + #pragma endregion + }; + + #pragma endregion + + #pragma region concrete expressions + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Add, Flt) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Flt, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Flt, Si) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Flt) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Flt, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Flt) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Flt, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Flt) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Multiply, Flt) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Flt, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Flt, Si) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Divide, Flt) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Flt, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Ui, Flt) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Flt, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Si, Flt) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Flt, Bits) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftRight, Flt, Bits) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Flt, Ui) + + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Flt) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Flt) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, SquareRoot, Flt) + DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, SquareRoot, Ui) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, RelativeDifferenceFrom, Flt) + + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Floor, Flt) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Ceiling, Flt) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Truncate, Flt) + + DEFINE_UNARY_EXPRESSION (MPEXPR_NAME, Random, MpirRandom^) + DEFINE_BINARY_EXPRESSION (MPEXPR_NAME, RandomBits, MpirRandom^, mp_bitcnt_t) + DEFINE_BINARY_EXPRESSION (MPEXPR_NAME, RandomChunky, MpirRandom^, mp_exp_t) + DEFINE_TERNARY_EXPRESSION (MPEXPR_NAME, RandomLimbsChunky, MpirRandom^, mp_size_t, mp_exp_t) + + #pragma endregion + + #pragma region HugeFloat class + + /// + /// Multi-precision Float class. + /// + public ref class MPTYPE : MPEXPR_NAME + { + internal: + //fields + MP(ptr) _value; + mp_bitcnt_t _allocatedPrecision; + + private: + //construction + void AllocateStruct() + { + _value = (MP(ptr))((*__gmp_allocate_func)(sizeof(MPSTRUCT))); + } + void FromString(String^ value, int base, bool exponentInDecimal); + MPTYPE(bool initialize); + String^ ToString(int base, bool lowercase, int maxDigits, bool exponentInDecimal); + + internal: + virtual void DeallocateStruct() + { + MP(set_prec_raw)(_value, _allocatedPrecision); + MP(clear)(_value); + (*__gmp_free_func)(_value, sizeof(MPSTRUCT)); + _value = nullptr; + } + + //assignment + virtual void AssignTo(MP(ptr) destination) override + { + if(destination != _value) + MP(set)(destination, _value); + } + virtual void ASSIGN_TO(EvaluationContext& context) override + { + CTXT(context.Index++) = _value; + } + + public: + #pragma region construction and disposal + + static MPTYPE() + { + DefaultPrecision = sizeof(mpir_ui) * 8 * 2; //2 limbs + } + + /// + /// Gets or sets the default precision of a float variable in bits. + /// The actual precision may be slightly greater if the value is not a whole limb multiple. + /// All subsequently constructed variables will use this precision, but previously constructed variables are unaffected. + /// The initial default value is 2 limbs. + /// + static property mp_bitcnt_t DefaultPrecision + { + mp_bitcnt_t get() { return MP(get_default_prec)(); } + void set(mp_bitcnt_t value) { MP(set_default_prec)(value); } + } + + /// + /// Initializes a new float instance and sets its value to 0. + /// The precision of the new variable's mantissa is set from the static DefaultPrecision property. + /// + MPTYPE(); + + /// + /// Initializes a new float instance, allocating enough memory to hold at least bits, and sets its value to 0. + /// All float operations are performed to the precision of the destination. + /// + /// Minimum number of bits the initially allocated memory should hold for the mantissa + /// the newly constructed instance + static MPTYPE^ Allocate(mp_bitcnt_t precision); + + /// + /// Initializes a new float instance and sets its value from the specified string. + /// No leading base characters are allowed. + /// The exponent is always in decimal. + /// + /// string representing the initial value for the new instance. Whitespace in the string is ignored. + MPTYPE(String^ value) { FromString(value, 0, true); } + + /// + /// Initializes a new float instance and sets its value from the specified string + /// + /// string representing the initial value for the new instance. Whitespace in the string is ignored. + /// base the string is in. + /// The base may vary from 2 to 62. No leading base characters are allowed. The exponent is always in decimal + /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. + /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. + MPTYPE(String^ value, int base) { FromString(value, base, true); } + + /// + /// Initializes a new float instance and sets its value from the specified string + /// + /// string representing the initial value for the new instance. Whitespace in the string is ignored. + /// base the string is in. + /// The base may vary from 2 to 62. No leading base characters are allowed. + /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. + /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. + /// True if the exponent is in decimal, false to use the same base as the mantissa. + MPTYPE(String^ value, int base, bool exponentInDecimal) { FromString(value, base, exponentInDecimal); } + + /// + /// Initializes a new float instance and sets its value to the result of computing the source expression. + /// + /// the expression that will be computed, and the result set as the initial value of the new instance. + MPTYPE(MPEXPR_NAME^ value); + + /// + /// Initializes a new float instance and sets its value to the result of computing the source expression. + /// + /// the expression that will be computed, and the result set as the initial value of the new instance. + MPTYPE(IntegerExpression^ value); + + /// + /// Initializes a new float instance and sets its value to the result of computing the source expression. + /// + /// the expression that will be computed, and the result set as the initial value of the new instance. + MPTYPE(RationalExpression^ value); + + /// + /// Constructs and returns a new float instance with its value set to . + /// + /// value for the initial value for the new float instance + MPTYPE(mpir_si value); + + /// + /// Constructs and returns a new float instance with its value set to . + /// + /// value for the initial value for the new float instance + MPTYPE(mpir_ui value); + + /// + /// Constructs and returns a new float instance with its value set to the parameter. + /// There is no rounding, this conversion is exact. + /// + /// Initial value for the new float instance. This is an exact conversion. + MPTYPE(double value); + + //disposal + + //creating a destructor in C++ implements IDisposable. + + /// + /// Frees all memory allocated by the instance. + /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. + /// + ~MPTYPE() { this->!MPTYPE(); } + + /// + /// Frees all memory allocated by the instance. + /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. + /// + !MPTYPE() { if(_value != 0) DeallocateStruct(); } + + #pragma endregion + + #pragma region conversions + + /// + /// Converts the number to a string. + /// To avoid debugging performance problems, this method outputs at most the number of digits specified in MpirSettings.ToStringDigits. + /// If the number is larger, the least significant digits are shown with a leading ellipsis (i.e., [-]...NNNNN) + /// Setting MpirSettings.ToStringDigits to 0 removes the upper limit. + /// + /// A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits. + virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits, false); } + + /// + /// Converts the number to a string in the specified base. + /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. + /// + /// The base to use for the output. The base can be from 2 to 62; uppercase letters represent digits 10-35 and lowercase letters represent digits 36-61. + /// A string representation of the number in the specified base. + String^ ToString(int base) { return ToString(base, false, 0, false); } + + /// + /// Converts the number to a string in the specified base. + /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. + /// + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// A string representation of the number in the specified base. + String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0, false); } + + /// + /// Converts the number to a string in the specified base. + /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. + /// + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// True to always show the exponent in decimal, False to use the same base as the mantissa + /// A string representation of the number in the specified base. + String^ ToString(int base, bool lowercase, bool exponentInDecimal) { return ToString(base, lowercase, 0, exponentInDecimal); } + +#if BITS_PER_MP_LIMB == 64 + /// + /// Returns the absolute value of the number as a ulong, truncating any fractional part. + /// If the number is too big, the result is undefined. Call FitsUlong() to check if the number will fit. + /// The sign of the number is ignored, only the absolute value is used. + /// This method is supported only on 64-bit builds + /// + /// The absolute value as a ulong, with any fractional part truncated. + mpir_ui ToUlong() { return MP(get_ui)(_value); } + + /// + /// Returns the value of the number as a long. + /// If the number is too big, the result is undefined. Call FitsLong() to check if the number will fit. + /// This method is supported only on 64-bit builds + /// + /// The value as a long, with any fractional part truncated. + mpir_si ToLong() { return MP(get_si)(_value); } +#else + /// + /// Returns the absolute value of the number as a uint, truncating any fractional part. + /// If the number is too big, the result is undefined. Call FitsUint() to check if the number will fit. + /// The sign of the number is ignored, only the absolute value is used. + /// This method is supported only on 32-bit builds + /// + /// The absolute value as a uint, with any fractional part truncated. + mpir_ui ToUint() { return MP(get_ui)(_value); } + + /// + /// Returns the value of the number as an int. + /// If the number is too big, the result is undefined. Call FitsInt() to check if the number will fit. + /// This method is supported only on 32-bit builds + /// + /// The value as an int, with any fractional part truncated. + mpir_si ToInt() { return MP(get_si)(_value); } +#endif + + /// + /// Returns the value of the number as a double, truncating if necessary (rounding towards zero). + /// If the exponent from the conversion is too big, the result is system dependent. An infinity is returned where available. + /// A hardware overflow trap may or may not occur. + /// + /// The value as a double, possibly truncated. + double ToDouble() { return MP(get_d)(_value); } + + /// + /// Returns the value of the number as a double, truncating if necessary (rounding towards zero), and returning the exponent separately. + /// The return is the mantissa, its absolute value will be in the range [0.5 - 1). + + /// The exponent is binary, i.e. mantissa * 2^exp is the value of the source number. + /// If the source value is zero, both mantissa and exponent are returned as 0. + /// + /// variable to store the exponent in. + /// The mantissa of the value as a double, possibly truncated. + double ToDouble([Out] mpir_si% exp) + { + double x; + exp = MP(get_2exp_d)(&x, _value); + return x; + } + + #pragma endregion + + #pragma region assignment + + /// + /// When getting, returns this float. + /// When setting, sets the value of the float object to the value resulting from computing the supplied expression. + /// The getter is a no-op and never needs to be invoked directly, but makes compound operators such as +=, *=, etc. possible. + /// Do not set the Value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// + /// MPIR types are implemented as reference types with value semantics. + /// Like Strings, the objects themselves are just lightweight pointers to data allocated elsewhere. + /// Unlike Strings, MPIR types are mutable. + /// Value semantics requires you to be able to code, a = b + c. + /// However, .Net (outside of C++) does not allow overloading the assignment operator, + /// and assigning references would necessitate some unnecessary duplication and extra memory allocations. + /// To solve this problem, MPIR.Net uses the property assignment. + /// The setter of the Value property does what an overloaded assignment operator would do in C++. + /// The syntax is a little different: a.Value = b + c, but it is fluent enough to become a quick habit, + /// and additionally reinforces the concept that an existing object can change its value while reusing internally allocated memory. + /// To this end, all overloaded operators and most functions that operate on MPIR types, + /// instead of eagerly computing a result, produce and return an expression that is basically a formula for the computation. + /// Expressions can then be composed using additional operators to achieve expression trees of arbitrary complexity. + /// All computations are deferred until an expression is assigned to the Value property of an MPIR object, + /// consumed by a method or operator that returns a primitive type, + /// or supplied as an argument to an MPIR type constructor. + /// The getter is a no-op defined to make possible constructs such as a.Value += 5, a.Value *= 10, etc. + /// Direct assignments such as a = b + c, a *= 10 will not compile because there is no implicit conversion from an expression. + /// Even if an implicit conversion were defined, such code would incur an extra allocation plus garbage collection, + /// and would not perform as well as doing the same operations on a.Value. + /// It would also not compile if the source were a "using" variable, as all method-local floats should be. + /// + property MPEXPR_NAME^ Value + { + void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); } + MPEXPR_NAME^ get() { return this; } + } + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// value for the new value for the object + void SetTo(mpir_ui value) { MP(set_ui)(_value, value); } + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// value for the new value for the object + void SetTo(mpir_si value) { MP(set_si)(_value, value); } + + /// + /// Sets the value of the float object. This is an exact conversion, there is no rounting. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(double value) { MP(set_d)(_value, value); } + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object. + /// May be an float or a pair of floats separated by a slash. + /// The string's leading characters may indicate base: + /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise + void SetTo(String^ value) { SetTo(value, 0); } + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + /// base the mantissa in the string is in. Exponent is always in decimcal. + /// The base may vary from 2 to 62. No leading leading base characters are allowed. + /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. + /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. + void SetTo(String^ value, int base) { SetTo(value, base, true); } + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// If the fraction is not in canonical form, Canonicalize() must be called. + /// + /// new value for the object + /// base the string is in. + /// The base may vary from 2 to 62. No leading leading base characters are allowed. + /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. + /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. + /// If true, the exponent is in decimal; otherwise it is in the same base as the mantissa + void SetTo(String^ value, int base, bool exponentInDecimal); + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(IntegerExpression^ value) + { + EvaluationContext context; + value->AssignToInteger(context); + MP(set_z)(_value, CTXTI(0)); + } + + /// + /// Sets the value of the float object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(RationalExpression^ value); + + /// + /// Swaps the values of two floats. + /// This operation is a pointer swap and doesn't affect allocated memory. + /// Do not call this method while either object is contained in a hash table, because this would change their hash codes. + /// + /// Source number to swap this instance's value with + void Swap(MPTYPE^ a) + { + MP(swap)(_value, a->_value); + + mp_bitcnt_t prec = a->_allocatedPrecision; + a->_allocatedPrecision = _allocatedPrecision; + _allocatedPrecision = prec; + } + + #pragma endregion + + #pragma region Size checks + + /// + /// Gets or sets the effective precision of the number without changing the memory allocated. + /// The number of bits cannot exceed the precision with which the variable was initialized or last reallocated. + /// The value of the number is unchanged, and in particular if it previously had a higher precision it will retain that higher precision. + /// New values assigned to the Value property will use the new precision. + /// This is an efficient way to use a float variable at different precisions during a calculation, + /// perhaps to gradually increase precision in an iteration, or just to use various different + /// precisions for different purposes during a calculation. + /// The number can be safely disposed after modifying its precision (this would not be the case in unmanaged MPIR). + /// + property mp_bitcnt_t Precision + { + mp_bitcnt_t get() { return MP(get_prec)(_value); } + void set(mp_bitcnt_t value) + { + if(value > _allocatedPrecision) + throw gcnew ArgumentException("Cannot set precision higher than allocated"); + + MP(set_prec_raw)(_value, value); + } + } + + /// + /// Gets the precision in bits that is currently allocated for internal storage of the mantissa. + /// The precision actually in effect, used in calculations, is initially the same but may be reduced by setting the Precision property. + /// However Precision cannot exceed AllocatedPrecision. + /// To change AllocatedPrecision, call Reallocate(). + /// The value actually allocated may be slightly more than the number of bits requested by Allocate() or Reallocate(). + /// + property mp_bitcnt_t AllocatedPrecision + { + mp_bitcnt_t get() { return _allocatedPrecision; } + } + + /// + /// Set the precision of this instance to be at least prec bits, reallocating its limbs data. + /// The value of this instance will be truncated to the new precision. + /// This function requires a call to realloc, and so should not be used in a tight loop. + /// + /// Minimum number of bits the allocated memory should hold for the mantissa. + void Reallocate(mp_bitcnt_t precision) + { + MP(set_prec_raw)(_value, _allocatedPrecision); + MP(set_prec)(_value, precision); + _allocatedPrecision = precision; + } + +#if BITS_PER_MP_LIMB == 64 + /// + /// Returns true if the value of the source number, if truncated to an integer, is in the long range. + /// This method is supported only on 64-bit builds + /// + /// true if the value will fit in a long + bool FitsLong() { return MP(fits_si_p)(_value) != 0; } + + /// + /// Returns true if the value of the source number, if truncated to an integer, is in the ulong range. + /// This method is supported only on 64-bit builds + /// + /// true if the value will fit in a long + bool FitsUlong() { return MP(fits_ui_p)(_value) != 0; } +#endif + + /// + /// Returns true if the value of the source number, if truncated to an integer, is in the int range. + /// + /// true if the value will fit in an int + bool FitsInt() { return MP(fits_sint_p)(_value) != 0; } + + /// + /// Returns true if the value of the source number, if truncated to an integer, is in the uint range. + /// + /// true if the value will fit in an int + bool FitsUint() { return MP(fits_uint_p)(_value) != 0; } + + /// + /// Returns true if the value of the source number, if truncated to an integer, is in the short range. + /// + /// true if the value will fit in a short + bool FitsShort() { return MP(fits_sshort_p)(_value) != 0; } + + /// + /// Returns true if the value of the source number, if truncated to an integer, is in the ushort range. + /// + /// true if the value will fit in a short + bool FitsUshort() { return MP(fits_ushort_p)(_value) != 0; } + + /// + /// Returns true if the source number is a whole integer. + /// + /// true if the value is an integer + bool IsInteger() { return MP(integer_p)(_value) != 0; } + + #pragma endregion + + #pragma region IO + + /// + /// Outputs the float to the as a string of digits in decimal. + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// + /// Text writer to output the number to + /// the number of characters written + size_t Write(TextWriter^ writer) { return Write(writer, 10, 0, false, true); } + + /// + /// Outputs the float to the as a string of digits in base . + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent in the same base. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// + /// Text writer to output the number to + /// The base to use for the output. + /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// the number of characters written + size_t Write(TextWriter^ writer, int base) { return Write(writer, base, 0, false, true); } + + /// + /// Outputs the float to the as a string of digits in base . + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// + /// Text writer to output the number to + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// the number of characters written + size_t Write(TextWriter^ writer, int base, bool lowercase) { return Write(writer, base, 0, lowercase, true); } + + /// + /// Outputs the float to the as a string of digits in base . + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// + /// Text writer to output the number to + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// Whether the exponent should always be written in decimal, or use the same base as the mantissa. + /// Maximum number of digits for the mantissa. + /// No more digits than are accurately representable by the number's precision will be printed. + /// Use zero to select that accurate maximum. + /// the number of characters written + size_t Write(TextWriter^ writer, int base, int maxDigits, bool lowercase, bool exponentInDecimal); + + /// + /// Inputs the number as a possibly white-space preceeded string. + /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. + /// The mantissa and exponent are always in decimal, no leading base characters are allowed. + /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. + /// This method reads the output of a Write(TextWriter) when decimal base is used. + /// + /// Text reader to input the number from + /// the number of characters read + size_t Read(TextReader^ reader) { return Read(reader, 0, true); } + + /// + /// Inputs the number as a possibly white-space preceeded string. + /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. + /// The mantissa is always in the specified base, the exponent is always in decimal. No leading base characters are allowed. + /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. + /// This method reads the output of a Write(TextWriter) when decimal base is used. + /// + /// Text reader to input the number from + /// The base to use for the mantissa. + /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// For bases 36 and less, uppercase and lowercase letters are equivalent. + /// the number of characters read + size_t Read(TextReader^ reader, int base) { return Read(reader, base, true); } + + /// + /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. + /// The mantissa is always in the specified base, the exponent is either in the same base or in decimal. No leading base characters are allowed. + /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. + /// This method reads the output of a Write(TextWriter, ...) method with the same base. + /// + /// Text reader to input the number from + /// The base to use for the input. + /// The base can be from 2 to 62; For bases up to 36 case is ignored. + /// For bases larger than 36, uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Whether the exponent should always be written in decimal, or use the same base as the mantissa. + /// the number of characters read + size_t Read(TextReader^ reader, int base, bool exponentInDecimal); + + #pragma endregion + + #pragma region Arithmetic + + /// Computes the square root of the source number. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// source number to take the square root of + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ SquareRoot(mpir_ui a) { return gcnew MPEXPR(SquareRootUi)(a); } + + #pragma endregion + }; + + #pragma endregion +}; diff --git a/mpir.net/mpir.net/HugeInt.h b/mpir.net/mpir.net/HugeInt.h index a2c5c1dc..f531da81 100644 --- a/mpir.net/mpir.net/HugeInt.h +++ b/mpir.net/mpir.net/HugeInt.h @@ -1,2302 +1,2302 @@ -/* -Copyright 2014 Alex Dyachenko - -This file is part of the MPIR Library. - -The MPIR Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published -by the Free Software Foundation; either version 3 of the License, or (at -your option) any later version. - -The MPIR Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the MPIR Library. If not, see http://www.gnu.org/licenses/. -*/ - -#pragma once - -using namespace System; -using namespace System::IO; -using namespace System::Runtime::InteropServices; - -#ifdef SPECIALIZE_EXPRESSIONS -#undef SPECIALIZE_EXPRESSIONS -#undef MP -#undef CUSTOM_MP -#undef MPSTRUCT -#undef MPTYPE -#undef MPTYPE_NAME -#undef MPEXPR_NAME -#undef MPEXPR -#undef CTXT -#undef ASSIGN_TO -#undef Mpt -#undef SET_CONTEXT_PRECISION -#endif -#define SPECIALIZE_EXPRESSIONS -#define Mpt Int -#define CUSTOM_MP(x) custom_mpz_##x -#define MPSTRUCT __mpz_struct -#define MP(x) mpz_##x -#define MPTYPE HugeInt -#define MPTYPE_NAME Integer -#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression -#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression -#define CTXT(x) context.IntArgs[x] -#define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) -#define SET_CONTEXT_PRECISION -#include "ExpressionMacros.h" - -extern __mpz_struct HugeIntConst1; - -namespace MPIR -{ - ref class MpirRandom; - ref class RationalExpression; - ref class FloatExpression; - ref class MPTYPE; - ref class MPEXPR(Multiply); - ref class MPEXPR(Divide); - ref class MPEXPR(DivideUi); - ref class MPEXPR(Mod); - ref class MPEXPR(DivMod); - ref class MPEXPR(ModUi); - ref class MPEXPR(ShiftRight); - ref class MPEXPR(Root); - ref class MPEXPR(SquareRoot); - ref class MPEXPR(Gcd); - ref class MPEXPR(RemoveFactors); - ref class MPEXPR(Sequence); - - #pragma region IntegerExpression - - /// - /// Base class for all integer expressions resulting from many integer operations on MPIR types. - /// Expressions can be arbitrarily nested, and are lazily evaluated - /// when they are either assigned to the Value property of an MPIR object, or are consumed by a function or operator that returns a primitive type. - /// Assignment to the Value property is necessary because .Net does not support overloading the assignment operator. - /// - public ref class MPEXPR_NAME abstract : public IComparable, IComparable, IEquatable - { - internal: - MPEXPR_NAME() { } - virtual void AssignTo(MP(ptr) destination) abstract; - virtual void ASSIGN_TO(EvaluationContext& context) - { - context.Initialized(IntInitialized); - auto ptr = &context.Temp[context.Index].MPTYPE_NAME; - CTXT(context.Index++) = ptr; - MP(init)(ptr); - AssignTo(ptr); - } - virtual void AssignToRational(EvaluationContext& context) - { - context.Initialized(IntInitialized); - auto ptr = &context.Temp[context.Index].Rational; - context.RationalArgs[context.Index++] = ptr; - MP(init)(&ptr->_mp_num); - AssignTo(&ptr->_mp_num); - ptr->_mp_den = HugeIntConst1; - } - static MPEXPR_NAME() - { - MP(init_set_ui)(&HugeIntConst1, 1); - } - - private: - int CompareTo(Object^ a, bool& valid); - - public: - #pragma region Arithmetic and Bitwise logic - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_ui b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (mpir_ui a, MPEXPR_NAME^ b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_si b); - - /// Adds two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to add to - /// Source value to add - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator + (mpir_si a, MPEXPR_NAME^ b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_ui b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (mpir_ui a, MPEXPR_NAME^ b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_si b); - - /// Subtracts two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to subtract from - /// Source value to subtract - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (mpir_si a, MPEXPR_NAME^ b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Multiply)^ operator * (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Multiply)^ operator * (MPEXPR_NAME^ a, mpir_ui b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Multiply)^ operator * (mpir_ui a, MPEXPR_NAME^ b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Multiply)^ operator * (MPEXPR_NAME^ a, mpir_si b); - - /// Multiplies two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Source value to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Multiply)^ operator * (mpir_si a, MPEXPR_NAME^ b); - - /// Shifts the source operand to the left by , i.e. multiplies by 2^. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Number of bits to shift by, i.e. power of 2 to multiply by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator << (MPEXPR_NAME^ a, mp_bitcnt_t bits); - - /// Shifts the source operand to the right by , i.e. divides by 2^. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// By default, the shifted value (i.e., the quotient of the division) is computed. If instead the shifted bits (i.e., the remainder) is desired, you can call - /// the Remainder method on the resulting expression before you assign it. You can also specify the rounding mode to use for the division by calling a method on the resulting expression. - /// Source value to divide - /// Number of bits to shift by, i.e. power of 2 to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// The expression exposes methods you can call to select whether you need to compute the quotient or remainder of the division, and/or to set the rounding mode. - /// By default, the shifted value (i.e., quotient) is computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. - /// - static MPEXPR(ShiftRight)^ operator >> (MPEXPR_NAME^ a, mp_bitcnt_t bits); - - /// Negates the source value. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to negate - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// You can optionally save the remainder or specify the rounding mode to use for the division by calling methods on the resulting expression, before assigning it. - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// The expression exposes methods you can call optionally if you need to save the remainder of the division, and/or to set the rounding mode. - /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. - /// - static MPEXPR(Divide)^ operator / (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Divides two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// You can optionally save the remainder or specify the rounding mode to use for the division by calling methods on the resulting expression, before assigning it. - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// The expression exposes methods you can call optionally if you need to save the remainder of the division, and/or to set the rounding mode. - /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. - /// - static MPEXPR(DivideUi)^ operator / (MPEXPR_NAME^ a, mpir_ui b); - - /// Calculates the remainder from the division of two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// You can optionally save the quotient in addition to the remainder or specify the rounding mode to use for the division - /// by calling methods on the resulting expression, before assigning it. - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// The expression exposes methods you can call optionally if you need to save the quotient in addition to the remainder, and/or to set the rounding mode. - /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. - /// - static MPEXPR(Mod)^ operator % (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Calculates the remainder from the division of two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// You can optionally save the quotient in addition to the remainder or specify the rounding mode to use for the division - /// by calling methods on the resulting expression, before assigning it. - /// Source value to divide - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// The expression exposes methods you can call optionally if you need to save the quotient in addition to the remainder, and/or to set the rounding mode. - /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. - /// - static MPEXPR(ModUi)^ operator % (MPEXPR_NAME^ a, mpir_ui b); - - /// Raises the source value to the specified power. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to multiply - /// Power to raise to - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, mpir_ui power); - - /// Computes the bitwise AND of two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to AND - /// Source value to AND with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator & (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Computes the bitwise (inclusive) OR of two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to OR - /// Source value to OR with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator | (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Computes the bitwise XOR (exclusive or) of two numbers. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to XOR - /// Source value to XOR with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, MPEXPR_NAME^ b); - - /// Computes the bitwise complement of a number. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to complement - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ operator ~ (MPEXPR_NAME^ a); - - /// If the source is >= 0, returns the population count of op, which is the number of 1 bits in the binary representation. -#if BITS_PER_MP_LIMB == 64 - /// If the source is < 0, the number of 1s is infinite, and the return value is ulong.MaxValue, the largest possible bit count. -#else - /// If the source is < 0, the number of 1s is infinite, and the return value is uint.MaxValue, the largest possible bit count. -#endif - /// Because the result is a primitive type, it is computed immediately. - /// - /// The population count for a non-negative number - mp_bitcnt_t PopCount() { IN_CONTEXT(this); return MP(popcount)(CTXT(0)); } - - /// If this number and the operand are both >= 0 or both < 0, returns the hamming distance between them, which is the number of bit positions with different bit values. -#if BITS_PER_MP_LIMB == 64 - /// If one operand is >= 0 and the other < 0 then the number of bits different is infinite, and the return value is ulong.MaxValue, the largest possible bit count. -#else - /// If one operand is >= 0 and the other < 0 then the number of bits different is infinite, and the return value is uint.MaxValue, the largest possible bit count. -#endif - /// Because the result is a primitive type, it is computed immediately. - /// - /// Source value to compute the hamming distance to - /// The hamming distance between this number and - mp_bitcnt_t HammingDistance(MPEXPR_NAME^ a) { IN_CONTEXT(this, a); return MP(hamdist)(CTXT(0), CTXT(1)); } - - /// Scans the source number, starting from the bit, towards more significant bits, until the first 0 or 1 bit - /// (depending on the is found, and return the index of the found bit. - /// If the bit at the starting position is already what's sought, then is returned. -#if BITS_PER_MP_LIMB == 64 - /// If there's no bit found, then ulong.MaxValue (the largest possible bit count) is returned. -#else - /// If there's no bit found, then uint.MaxValue (the largest possible bit count) is returned. -#endif - /// This will happen with = true past the end of a non-negative number, or with = false past the end of a negative number. - /// A false bit will always be found at the position past the end of a non-negatitve number, and a true bit past the end of a negative number. - /// - /// Value of the bit to scan for, true for 1, false for 0 - /// Starting bit position to search. The least significant bit is zero. -#if BITS_PER_MP_LIMB == 64 - /// The index of the found bit, or ulong.MaxValue if no bit found. -#else - /// The index of the found bit, or uint.MaxValue if no bit found. -#endif - mp_bitcnt_t FindBit(bool value, mp_bitcnt_t start) { IN_CONTEXT(this); return value ? MP(scan1)(CTXT(0), start) : MP(scan0)(CTXT(0), start); } - - /// Computes the absolute value of the source number. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Abs(); - - /// Divides two numbers where it is known in advance that the division is exact. This method is faster than normal division, - /// but produces an undefined result when the division is not exact. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - MPEXPR_NAME^ DivideExactly(MPEXPR_NAME^ a); - - /// Divides two numbers where it is known in advance that the division is exact. This method is faster than normal division, - /// but produces an undefined result when the division is not exact. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to divide by - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. - /// - MPEXPR_NAME^ DivideExactly(mpir_ui a); - - /// Raises the source value to the specified modulo . - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Power to raise the source value to. - /// Negative power values are supported if an inverse mod exists, otherwise divide by zero is raised. - /// Modulo to perform the powering operation with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ PowerMod(MPEXPR_NAME^ power, MPEXPR_NAME^ modulo); - - /// Raises the source value to the specified modulo . - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Power to raise the source value to - /// Modulo to perform the powering operation with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ PowerMod(mpir_ui power, MPEXPR_NAME^ modulo); - - /// Computes the truncated integer part of the root of the specified from the source value. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// You can optionally save the remainder from the root operation, or a flag indicating whether the root was exact, - /// by calling a method on the resulting expression, before assigning it. - /// Power of the root to compute. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR(Root)^ Root(mpir_ui power); - - /// Computes the truncated integer part of the square root of the source value. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// You can optionally save the remainder from the root operation - /// by calling a method on the resulting expression, before assigning it. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR(SquareRoot)^ SquareRoot(); - - /// Calculates the remainder from the division of two numbers, using the rounding mode set in MpirSettings.RoundingMode. - /// Because the result is a primitive type, it is computed immediately. - /// - /// divisor to divide the source by - /// The remainder of the division - mpir_ui Mod(mpir_ui a) { return Mod(a, RoundingModes::Default); } - - /// Calculates the remainder from the division of two numbers, using the specified rounding mode. - /// Because the result is a primitive type, it is computed immediately. - /// - /// divisor to divide the source by - /// rounding mode to use for the division - /// The remainder of the division - mpir_ui Mod(mpir_ui a, RoundingModes roundingMode); - - #pragma endregion - - #pragma region Comparisons - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Both this method and Equals() allow the argument to be a RationalExpression, however we do not define mixed equality operators, - /// because otherwise testing for a null/non-null expression would require an awkward explicit cast on the null. - /// Although this only applies to equality operators, while comparison operators could have possibly worked, we're leaving out all mixed operators for now. - /// Since comparison via CompareTo() or Equals() is possible between ints and rationals, operators would just be another way to do the same thing. - /// Value to compare the source with. This can be an integer or rational multi-precision number or expression, or a supported primitive type (long, ulong, or double). - /// A positive number if the source is greater than , negative if less, and zero if they are equal. - virtual int CompareTo(Object^ a) sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Value to compare the source with - /// A positive number if the source is greater than , negative if less, and zero if they are equal. - virtual int CompareTo(MPEXPR_NAME^ a) sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Value to compare the source with - /// true if the values of the source and are equal, false otherwise. - virtual bool Equals(MPEXPR_NAME^ a) sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Both this method and CompareTo() allow the argument to be a RationalExpression, however we do not define mixed equality operators, - /// because otherwise testing for a null/non-null expression would require an awkward explicit cast on the null. - /// Although this only applies to equality operators, while comparison operators could have possibly worked, we're leaving out all mixed operators for now. - /// Since comparison via CompareTo() or Equals() is possible between ints and rationals, operators would just be another way to do the same thing. - /// Value to compare the source with. This can be an integer or rational multi-precision number or expression, or a supported primitive type (long, ulong, or double). - /// true if the values of the source and are equal, false otherwise. - virtual bool Equals(Object^ a) override sealed; - - /// Computes the hash code of the source value. - /// If called on an expression, it is evaluated into a temporary variable before the comparison is performed. - /// Multi-precision classes are mutable with value semantics. The hash code is based on the value, and will change if the value changes. - /// For this reason, the value of an object must not be modified while the object is contained in a hash table. - /// a signed integer hash code for the value. - virtual int GetHashCode() override sealed; - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator < (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator >= (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator > (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator <= (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator != (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } - - /// Compares two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Source value to compare - /// Source value to compare with - /// A boolean result of the comparison. - static bool operator == (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } - - /// Compares the absolute values of two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Value to compare the source with - /// A positive number if the absolute value of the source is greater than the absolute value of , negative if less, and zero if they are equal. - int CompareAbsTo(MPEXPR_NAME^ a) { IN_CONTEXT(this, a); return MP(cmpabs)(CTXT(0), CTXT(1)); } - - /// Compares the absolute values of two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Value to compare the source with - /// A positive number if the absolute value of the source is greater than , negative if less, and zero if they are equal. - int CompareAbsTo(mpir_ui a) { IN_CONTEXT(this); return MP(cmpabs_ui)(CTXT(0), a); } - - /// Compares the absolute values of two numbers. - /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Value to compare the source with - /// A positive number if the absolute value of the source is greater than the absolute value of , negative if less, and zero if they are equal. - int CompareAbsTo(double a) { IN_CONTEXT(this); return MP(cmpabs_d)(CTXT(0), a); } - - /// Calculates the sign (+1, 0, or -1) of the source value. - /// If the source is an expression, it is evaluated into a temporary variable before the sign is computed. - /// - /// +1 if the source is positive, -1 if negative, and 0 if zero. - int Sign() { IN_CONTEXT(this); return MP(sgn)(CTXT(0)); } - - #pragma endregion - - #pragma region Utility methods - - /// - /// Checks if the source is evenly divisible by . - /// Because this method returns a primitive type, it is computed immediately. - /// - /// Divisor to test with. This can be zero; only zero is considired divisible by zero. - /// True if the source is evenly divisible by - bool IsDivisibleBy(MPEXPR_NAME^ a) { IN_CONTEXT(this, a); return MP(divisible_p)(CTXT(0), CTXT(1)) != 0; } - - /// - /// Checks if the source is evenly divisible by . - /// Because this method returns a primitive type, it is computed immediately. - /// - /// Divisor to test with. This can be zero; only zero is considired divisible by zero. - /// True if the source is evenly divisible by - bool IsDivisibleBy(mpir_ui a) { IN_CONTEXT(this); return MP(divisible_ui_p)(CTXT(0), a) != 0; } - - /// - /// Checks if the source is evenly divisible by 2^. - /// Because this method returns a primitive type, it is computed immediately. - /// - /// Power of 2 to use for the divisor - /// True if the source is evenly divisible by 2^ - bool IsDivisibleByPowerOf2(mp_bitcnt_t power) { IN_CONTEXT(this); return MP(divisible_2exp_p)(CTXT(0), power) != 0; } - - /// - /// Checks if the source is congruent to modulo . - /// Because this method returns a primitive type, it is computed immediately. - /// - /// Divisor to test with. This can be zero; only zero is considired divisible by zero. - /// Modulo with respect to which to test for congruency - /// True if the source is congruent to modulo - bool IsCongruentTo(MPEXPR_NAME^ a, MPEXPR_NAME^ mod) { IN_CONTEXT(this, a, mod); return MP(congruent_p)(CTXT(0), CTXT(1), CTXT(2)) != 0; } - - /// - /// Checks if the source is congruent to modulo . - /// Because this method returns a primitive type, it is computed immediately. - /// - /// Divisor to test with. This can be zero; only zero is considired divisible by zero. - /// Modulo with respect to which to test for congruency - /// True if the source is congruent to modulo - bool IsCongruentTo(mpir_ui a, mpir_ui mod) { IN_CONTEXT(this); return MP(congruent_ui_p)(CTXT(0), a, mod) != 0; } - - /// - /// Checks if the source is congruent to modulo 2^. - /// Because this method returns a primitive type, it is computed immediately. - /// - /// Divisor to test with - /// Power of 2 to use for the modulo - /// True if the source is congruent to modulo 2^ - bool IsCongruentToModPowerOf2(MPEXPR_NAME^ a, mp_bitcnt_t power) { IN_CONTEXT(this, a); return MP(congruent_2exp_p)(CTXT(0), CTXT(1), power) != 0; } - - /// - /// Checks if the source is a perfect power. - /// Because this method returns a primitive type, it is computed immediately. - /// Both 0 and 1 are considered perfect powers. - /// Negative values are accepted, but of course can only be odd powers. - /// - /// True if the source is a perfect power - bool IsPerfectPower() { IN_CONTEXT(this); return MP(perfect_power_p)(CTXT(0)) != 0; } - - /// - /// Checks if the source is a perfect square. - /// Because this method returns a primitive type, it is computed immediately. - /// Both 0 and 1 are considered perfect squares. - /// - /// True if the source is a perfect square - bool IsPerfectSquare() { IN_CONTEXT(this); return MP(perfect_square_p)(CTXT(0)) != 0; } - - /// - /// Returns the size of the absolute value of the number, measured in number of limbs. - /// If op is zero, the returned value will be zero. - /// For a HugeInt object, this method simply retrieves the value from a stored private field. - /// However for an expression it can potentially be very expensive, since it requires evaluation of the expression result. - /// Because this method returns a primitive type, it is computed immediately. - /// - /// The number of limbs used to represent the number - size_t Size() { IN_CONTEXT(this); return MP(size)(CTXT(0)); } - - #pragma endregion - - #pragma region Number-theoretic - - /// - /// Looks for the next candidate prime greater than this number. - /// Note that this function will occasionally return composites. - /// It is designed to give a quick method for generating numbers which do not have small prime factors (less than 1000) - /// and which pass a small number of rounds of Miller-Rabin (just two rounds). - /// The test is designed for speed, assuming that a high quality followup test can then be run to ensure primality. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Random number generator to use for probabilistic primality tests - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, performs the requested operation - MPEXPR_NAME^ NextPrimeCandidate(MpirRandom^ random); - - /// Computes the greatest common divisor of this number and . - /// The result is always positive even if one or both inputs are negative (or zero if both inputs are zero). - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to compute the GCD with - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR(Gcd)^ Gcd(MPEXPR_NAME^ a); - - /// - /// Computes the greatest common divisor of this number and . - /// The result is always positive even if the source number is negative. - /// Because the result is a primitive type, it is computed immediately. - /// - /// Source value to compute the GCD with. If zero, zero is returned. - /// The greatest common divisor of the absolute value of this number and . - mpir_ui Gcd(mpir_ui a) { IN_CONTEXT(this); return MP(gcd_ui)(nullptr, CTXT(0), a); } - - /// Computes the least common multiple of this number and . - /// The result is always positive, irrespective of the signs of the source numbers. - /// The result will be zero if either source number is zero. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to compute the LCM with. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Lcm(MPEXPR_NAME^ a); - - /// Computes the least common multiple of this number and . - /// The result is always positive, irrespective of the signs of the source numbers. - /// The result will be zero if either source number is zero. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Source value to compute the LCM with. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Lcm(mpir_ui a); - - /// Computes the inverse of this number modulo . - /// If the inverse exists, the result will satisfy 0 <= result < . - /// If an inverse doesn't exist an ArgumentException is thrown. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Modulo with respect to which to invert the number. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Invert(MPEXPR_NAME^ modulo); - - /// Remove all occurrences of the from the source number. - /// You can optionally save the number of such occurrences that were removed. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Factor to remove from the source number. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR(RemoveFactors)^ RemoveFactors(MPEXPR_NAME^ factor); - - #pragma endregion - }; - - #pragma endregion - - #pragma region MpirSettings - - /// - /// Static class for MPIR settings such as rounding defaults - /// - public ref class MpirSettings abstract sealed - { - private: - static int _toStringDigits; - - internal: - static MPTYPE^ _toStringModulo; - - public: - -#undef GMP_VERSION - - /// - /// Represents the total number of bits in a single MPIR limb, including data bits and nail bits - /// - literal int BITS_PER_LIMB = BITS_PER_UI; - - /// - /// Represents the number of nail bits in a single MPIR limb. Nail bits are used internally by MPIR - /// - literal int NAIL_BITS_PER_LIMB = GMP_NAIL_BITS; - - /// - /// Represents the number of data bits in a single MPIR limb - /// - literal int USABLE_BITS_PER_LIMB = GMP_NUMB_BITS; - - /// - /// Represents the version of GMP with which the underlying MPIR library is compatible - /// - static initonly const Version^ GMP_VERSION = gcnew Version(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL); - - /// - /// Represents the version of the underlying MPIR library - /// - static initonly const Version^ MPIR_VERSION = gcnew Version(_MSC_MPIR_VERSION); - - /// - /// Gets or sets the default rounding mode used for MPIR division operations that don't explicitly specify a rounding mode. - /// Defaults to Truncate. - /// - static property RoundingModes RoundingMode; - - /// - /// Gets or sets the maximum number of digits the object.ToString() method override will output. - /// If a number is longer than this number of digits, it will be output as "[-]...NNNNN" with the least significant digits shown. - /// Defaults to 256. - /// Specifying 0 will cause all digits to be output. This should be used with care, as for example, the debugger calls ToString() - /// on watched objects, and may have performance issues with large objects. - /// - static property int ToStringDigits - { - int get() { return _toStringDigits; } - void set(int value); - } - - static MpirSettings() - { - RoundingMode = RoundingModes::Truncate; - ToStringDigits = 256; - } - }; - - #pragma endregion - - #pragma region mid-level abstract expression specializations - - /// - /// Expression that results from a multiplication operator. Used internally to optimize computations that can use addmul/submul MPIR calls. - /// - public ref class MPEXPR(Multiply) abstract : MPEXPR_NAME - { - internal: - MPEXPR(Multiply)() { } - virtual void AddTo(MP(ptr) destination) abstract; - virtual void SubtractFrom(MP(ptr) destination) abstract; - }; - - /// - /// Expression that results from a division or modulo operator. Allows to set the rounding mode for the division. - /// - public ref class MPEXPR(DivMod) abstract : MPEXPR_NAME - { - internal: - MPEXPR(DivMod)() { } - RoundingModes rounding; - - public: - /// - /// Optionally sets the rounding mode for the division. If not set, the static MpirSettings.RoundingMode will be used. - /// - /// the mode to use. If this is Default, the static MpirSettings.Rounding mode is used. - /// An updated expression, with its internal state updated to use the specified rounding mode. - MPEXPR_NAME^ Rounding(RoundingModes mode) - { - rounding = mode; - return this; - } - }; - - /// - /// Expression that results from a division operator. Allows to save the remainder to a separate result object, and/or set the rounding mode for the division. - /// - public ref class MPEXPR(Divide) abstract : MPEXPR(DivMod) - { - internal: - MPEXPR(Divide)() { } - MPTYPE^ _remainder; - void CUSTOM_MP(div)(MP(ptr) q, MP(srcptr) n, MP(srcptr) d); - - public: - /// - /// Optionally save the remainder of the division to a separate result. This cannot be the same object the resulting division quotient is being assigned to. - /// - /// destination for the remainder. This cannot be the same object the resulting division quotient is being assigned to. - /// An updated expression, with its internal state updated to compute the remainder. - MPEXPR(DivMod)^ SavingRemainderTo(MPTYPE^ destination) - { - _remainder = destination; - return this; - } - }; - - /// - /// Expression that results from a division operator. Allows to save the remainder, and/or set the rounding mode for the division. - /// - public ref class MPEXPR(DivideUi) abstract : MPEXPR(Divide) - { - private: - Action^ _limbRemainder; - - internal: - MPEXPR(DivideUi)() { } - void CUSTOM_MP(div_ui)(MP(ptr) q, MP(srcptr) n, mpir_ui d); - - public: - /// - /// Optionally saves the remainder of the division to a separate result. - /// - /// The delegate that will be called with the remainder of the division. - /// The delegate is called when the division is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. - /// An updated expression, with its internal state updated to compute the remainder. - MPEXPR(Divide)^ SettingRemainderTo(Action^ callback) - { - _limbRemainder = callback; - return this; - } - }; - - /// - /// Expression that results from a modulo operator. Allows to save the division result to a separate object, and/or set the rounding mode for the division. - /// - public ref class MPEXPR(Mod) abstract : MPEXPR(DivMod) - { - internal: - MPEXPR(Mod)() { } - MPTYPE^ _quotient; - void CUSTOM_MP(mod)(MP(ptr) r, MP(srcptr) n, MP(srcptr) d); - - public: - /// - /// Optionally save the quotient of the division to a separate result. This cannot be the same object the resulting division modulo is being assigned to. - /// - /// destination for the quotient. This cannot be the same object the resulting division modulo is being assigned to. - /// An updated expression, with its internal state updated to compute the quotient. - MPEXPR(DivMod)^ SavingQuotientTo(MPTYPE^ destination) - { - _quotient = destination; - return this; - } - }; - - /// - /// Expression that results from a modulo operator. Allows to save the division result to a separate object, and/or set the rounding mode for the division. - /// - public ref class MPEXPR(ModUi) abstract : MPEXPR(Mod) - { - private: - Action^ _limbRemainder; - - internal: - MPEXPR(ModUi)() { } - void CUSTOM_MP(mod_ui)(MP(ptr) r, MP(srcptr) n, mpir_ui d); - - public: - /// - /// Optionally saves the remainder of the division to a separate result. - /// - /// The delegate that will be called with the remainder of the division. - /// The delegate is called when the division is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. - /// An updated expression, with its internal state updated to compute the remainder. - MPEXPR(Mod)^ SettingRemainderTo(Action^ callback) - { - _limbRemainder = callback; - return this; - } - }; - - /// - /// Expression that results from a right shift operator. Allows to save the remainder to a separate result object, and/or set the rounding mode for the division. - /// - public ref class MPEXPR(ShiftRight) abstract : MPEXPR(DivMod) - { - private: - bool _remainder; - - internal: - MPEXPR(ShiftRight)() { } - void CUSTOM_MP(div_2exp)(MP(ptr) q, MP(srcptr) n, mp_bitcnt_t bits); - - public: - /// - /// Computes the remainder of the division, rather than the quotient, which is the default. - /// - /// An updated expression, with its internal state updated to compute the remainder, rather than the quotient. - MPEXPR(DivMod)^ Remainder() - { - _remainder = true; - return this; - } - }; - - /// - /// Expression that results from a square root function. Allows to save the remainder to a separate result object. - /// - public ref class MPEXPR(SquareRoot) abstract : MPEXPR_NAME - { - internal: - MPEXPR(SquareRoot)() { } - MPTYPE^ _remainder; - void CUSTOM_MP(sqrt)(MP(ptr) dest, MP(srcptr) oper); - - public: - /// - /// Optionally saves the remainder of the root operation to a separate result. - /// - /// destination for the remainder. This cannot be the same object the result of the root operation is being assigned to. - /// An updated expression, with its internal state updated to save the remainder. - MPEXPR_NAME^ SavingRemainderTo(MPTYPE^ destination) - { - _remainder = destination; - return this; - } - }; - - /// - /// Expression that results from a root function. Allows to save a flag indicating whether the root was exact, or to save the remainder to a separate result object. - /// - public ref class MPEXPR(Root) abstract : MPEXPR(SquareRoot) - { - private: - Action^ _exact; - - internal: - MPEXPR(Root)() { } - void CUSTOM_MP(root)(MP(ptr) dest, MP(srcptr) oper, mpir_ui power); - - public: - /// - /// Optionally gets a flag indicating whether the root operation was exact. - /// - /// Delegate that will be called with the exact flag. - /// The delegate is called when the root operation is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. - /// An updated expression, with its internal state updated to compute the exact flag. - MPEXPR_NAME^ SettingExactTo(Action^ callback) - { - _exact = callback; - return this; - } - }; - - /// - /// Expression that results from a Gcd method. Allows to additionally compute Diophantine equation multiplier(s). - /// - public ref class MPEXPR(Gcd) abstract : MPEXPR_NAME - { - internal: - MPEXPR(Gcd)() { } - MPTYPE^ _s; - MPTYPE^ _t; - void CUSTOM_MP(gcd)(MP(ptr) dest, MP(srcptr) a, MP(srcptr) b); - - public: - /// - /// Optionally computes and saves the coefficients and such that a + b = g = gcd(a, b). - /// If only one of the coefficients is needed, use null for the other. - /// The values and are chosen such that normally, || < |b|/(2g) and || < |a|/(2g), - /// and these relations define and uniquely. - /// There are a few exceptional cases: - /// If |a| = |b|, then = 0 and = sgn(b). - /// Otherwise, = sgn(a) if b = 0 or |b| = 2g, and = sgn(b) if a = 0 or |a| = 2g. - /// In all cases, = 0 if and only if g = |b|, i.e., if b divides a or a = b = 0. - /// destination for the first coefficient. Can be null if not needed. - /// destination for the second coefficient. Can be null if not needed. - /// An updated expression, with its internal state updated to save the coefficients. - MPEXPR_NAME^ SavingDiophantineMultipliersTo(MPTYPE^ s, MPTYPE^ t) - { - _s = s; - _t = t; - return this; - } - }; - - /// - /// Expression that results from a RemoveFactors method. Allows to additionally save the number of factors that were removed. - /// - public ref class MPEXPR(RemoveFactors) abstract : MPEXPR_NAME - { - internal: - MPEXPR(RemoveFactors)() { } - Action^ _count; - - public: - /// - /// Optionally gets the number of factors removed. - /// - /// Delegate that will be called with the number of factors that were removed. - /// The delegate is called when the root operation is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. - /// An updated expression, with its internal state updated to save the number of factors. - MPEXPR_NAME^ SavingCountRemovedTo(Action^ callback) - { - _count = callback; - return this; - } - }; - - /// - /// Expression that results from a method calculating a single number from a sequence, such as a fibonacci or lucas number. Allows to save the previous number in addition to the requested one, so that the sequence can be continued. - /// - public ref class MPEXPR(Sequence) abstract : MPEXPR_NAME - { - internal: - MPEXPR(Sequence)() { } - MPTYPE^ _previous; - - public: - /// - /// Optionally save the previous number in the sequence to a separate result. This cannot be the same object to which the expression is assigned. - /// - /// destination for the previous number. This cannot be the same object to which the expression is assigned. - /// An updated expression, with its internal state updated to additionally compute the previous number. - MPEXPR_NAME^ SavingPreviousTo(MPTYPE^ destination) - { - _previous = destination; - return this; - } - }; - - #pragma endregion - - #pragma region concrete expressions - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Add, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Int, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Int, Si) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Int, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Int, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Int) - -#undef ADDITIONAL_MEMBERS -#define ADDITIONAL_MEMBERS \ - void virtual AddTo(MP(ptr) destination) override; \ - void virtual SubtractFrom(MP(ptr) destination) override; - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Multiply), Multiply, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(Multiply), Multiply, Int, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(Multiply), Multiply, Int, Si) - -#undef ADDITIONAL_MEMBERS -#define ADDITIONAL_MEMBERS - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Int, Bits) - - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Int) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Int) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Divide), Divide, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(DivideUi), Divide, Int, Ui) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(ShiftRight), ShiftRight, Int, Bits) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Mod), Mod, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(ModUi), Mod, Int, Ui) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, DivideExactly, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, DivideExactly, Int, Ui) - - DEFINE_TERNARY_EXPRESSION_WITH_THREE (MPEXPR_NAME, PowerMod, Int) - DEFINE_TERNARY_EXPRESSION_WITH_BUILT_IN_MIDDLE (MPEXPR_NAME, PowerMod, Int, Ui, Int) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Int, Ui) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(Root), Root, Int, Ui) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR(SquareRoot), SquareRoot, Int) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, And, Int) - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Or, Int) - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Xor, Int) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Complement, Int) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Invert, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, NextPrimeCandidate, Int, Rnd) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Gcd), Gcd, Int) - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(RemoveFactors), RemoveFactors, Int) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Lcm, Int) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Lcm, Int, Ui) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Power, Ui, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Factorial, Ui, Ui) - DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Primorial, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Binomial, Ui, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Binomial, Int, Ui) - DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR(Sequence), Fibonacci, Ui) - DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR(Sequence), Lucas, Ui) - - DEFINE_BINARY_EXPRESSION(MPEXPR_NAME, RandomBits, MpirRandom^, mp_bitcnt_t) - DEFINE_BINARY_EXPRESSION(MPEXPR_NAME, RandomBitsChunky, MpirRandom^, mp_bitcnt_t) - DEFINE_BINARY_EXPRESSION(MPEXPR_NAME, Random, MpirRandom^, MPEXPR_NAME^) - - #pragma endregion - - #pragma region HugeInt class - - /// - /// Multi-precision Integer class. - /// - public ref class MPTYPE : MPEXPR_NAME - { - internal: - //fields - MP(ptr) _value; - - private: - //construction - void AllocateStruct() - { - _value = (MP(ptr))((*__gmp_allocate_func)(sizeof(MPSTRUCT))); - } - void FromString(String^ value, int base); - MPTYPE(bool initialize); - - internal: - String^ ToString(int base, bool lowercase, int maxDigits); - virtual void DeallocateStruct() - { - MP(clear)(_value); - (*__gmp_free_func)(_value, sizeof(MPSTRUCT)); - _value = nullptr; - } - - //assignment - virtual void AssignTo(MP(ptr) destination) override - { - if(destination != _value) - MP(set)(destination, _value); - } - virtual void ASSIGN_TO(EvaluationContext& context) override - { - CTXT(context.Index++) = _value; - } - - public: - #pragma region construction and disposal - - /// - /// Initializes a new integer instance and sets its value to 0 - /// - MPTYPE(); - - /// - /// Initializes a new integer instance, allocating enough memory to hold at least bits, and sets its value to 0. - /// This is only the initial space, integer will grow automatically in the normal way, if necessary, for subsequent values stored. - /// This makes it possible to avoid repeated reallocations if a maximum size is known in advance. - /// - /// Minimum number of bits the initially allocated memory should hold - /// the newly constructed instance - static MPTYPE^ Allocate(mp_bitcnt_t bits); - - /// - /// Initializes a new integer instance and sets its value from the specified string, using leading characters to recognize the base: - /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise. - /// - /// string representing the initial value for the new instance. Whitespace in the string is ignored. - MPTYPE(String^ value) { FromString(value, 0); } - - /// - /// Initializes a new integer instance and sets its value from the specified string - /// - /// string representing the initial value for the new instance. Whitespace in the string is ignored. - /// base the string is in. - /// The base may vary from 2 to 62, or if base is 0, then the leading characters are used: 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise. - /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. - /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. - MPTYPE(String^ value, int base) { FromString(value, base); } - - /// - /// Initializes a new integer instance and sets its value to the result of computing the source expression. - /// - /// the expression that will be computed, and the result set as the initial value of the new instance. - MPTYPE(MPEXPR_NAME^ value); - - /// - /// Constructs and returns a new integer instance with its value set to the parameter. - /// - /// Initial value for the new integer instance - MPTYPE(mpir_si value); - - /// - /// Constructs and returns a new integer instance with its value set to the parameter. - /// - /// Initial value for the new integer instance - MPTYPE(mpir_ui value); - - /// - /// Constructs and returns a new integer instance with its value set to the parameter. - /// - /// Initial value for the new integer instance. Any fractional portion is truncated. - MPTYPE(double value); - - /// - /// Change the space allocated for integer to bits. The value in integer is preserved if it fits, or is set to 0 if not. - /// This function can be used to increase the space for a variable in order to avoid repeated automatic reallocations, or to decrease it to give memory back to the heap. - /// - /// Minimum number of bits the allocated memory should hold - void Reallocate(mp_bitcnt_t bits) { MP(realloc2)(_value, bits); } - - //disposal - - //creating a destructor in C++ implements IDisposable. - - /// - /// Frees all memory allocated by the instance. - /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. - /// - ~MPTYPE() { this->!MPTYPE(); } - - /// - /// Frees all memory allocated by the instance. - /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. - /// - !MPTYPE() { if(_value != 0) DeallocateStruct(); } - - #pragma endregion - - #pragma region Properties - - /// - /// Gets the number of limbs currently allocated. This value will never be less than Size(). - /// When a new value is assigned to the object, more space is automatically allocated if necessary. - /// Reallocate() can also be used manually. - /// - property int AllocatedSize - { - int get() { return _value->_mp_alloc; } - } - - #pragma endregion - - #pragma region conversions - - /// - /// Converts the number to a string. - /// To avoid debugging performance problems, this method outputs at most the number of digits specified in MpirSettings.ToStringDigits. - /// If the number is larger, the least significant digits are shown with a leading ellipsis (i.e., [-]...NNNNN) - /// Setting MpirSettings.ToStringDigits to 0 removes the upper limit. - /// - /// A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits. - virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits); } - - /// - /// Converts the number to a string in the specified base. - /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. - /// - /// The base to use for the output. The base can be from 2 to 62; uppercase letters represent digits 10-35 and lowercase letters represent digits 36-61. - /// A string representation of the number in the specified base. - String^ ToString(int base) { return ToString(base, false, 0); } - - /// - /// Converts the number to a string in the specified base. - /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. - /// - /// The base to use for the output. - /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. - /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// Indicates if lowercase or uppercase letters should be used for the output. - /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. - /// A string representation of the number in the specified base. - String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0); } - -#if BITS_PER_MP_LIMB == 64 - /// - /// Returns the absolute value of the number as a ulong. - /// If the number is too big, then just the least significant bits that do fit are returned. - /// The sign of the number is ignored, only the absolute value is used. - /// This method is supported only on 64-bit builds - /// - /// The absolute value as a ulong, possibly truncated to the least significant bits only. - mpir_ui ToUlong() { return MP(get_ui)(_value); } - - /// - /// Returns the value of the number as a long. - /// If the number is too big, then just the least significant bits that do fit are returned, with the same sign as the number. - /// When truncation occurs, the result is propobly not very useful. Call FitsLong() to check if the number will fit. - /// This method is supported only on 64-bit builds - /// - /// The value as a long, possibly truncated to the least significant bits only. - mpir_si ToLong() { return MP(get_si)(_value); } -#else - /// - /// Returns the absolute value of the number as a uint. - /// If the number is too big, then just the least significant bits that do fit are returned. - /// The sign of the number is ignored, only the absolute value is used. - /// This method is supported only on 32-bit builds - /// - /// The absolute value as a uint, possibly truncated to the least significant bits only. - mpir_ui ToUint() { return MP(get_ui)(_value); } - - /// - /// Returns the value of the number as an int. - /// If the number is too big, then just the least significant bits that do fit are returned, with the same sign as the number. - /// When truncation occurs, the result is propobly not very useful. Call FitsInt() to check if the number will fit. - /// This method is supported only on 32-bit builds - /// - /// The value as an int, possibly truncated to the least significant bits only. - mpir_si ToInt() { return MP(get_si)(_value); } -#endif - - /// - /// Returns the value of the number as a double, truncating if necessary (rounding towards zero). - /// If the exponent from the conversion is too big, the result is system dependent. An infinity is returned where available. - /// A hardware overflow trap may or may not occur. - /// - /// The value as a double, possibly truncated. - double ToDouble() { return MP(get_d)(_value); } - - /// - /// Returns the value of the number as a double, truncating if necessary (rounding towards zero), and returning the exponent separately. - /// The return is the mantissa, its absolute value will be in the range [0.5 - 1). - /// If the source value is zero, both mantissa and exponent are returned as 0. - /// - /// variable to store the exponent in. - /// The mantissa of the value as a double, possibly truncated. - double ToDouble([Out] mpir_si% exp) - { - double result; - exp = MP(get_2exp_d)(&result, _value); - return result; - } - - #pragma endregion - - #pragma region assignment - - /// - /// When getting, returns this integer. - /// When setting, sets the value of the integer object to the value resulting from computing the supplied expression. - /// The getter is a no-op and never needs to be invoked directly, but makes compound operators such as +=, *=, etc. possible. - /// Do not set the Value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// - /// MPIR types are implemented as reference types with value semantics. - /// Like Strings, the objects themselves are just lightweight pointers to data allocated elsewhere. - /// Unlike Strings, MPIR types are mutable. - /// Value semantics requires you to be able to code, a = b + c. - /// However, .Net (outside of C++) does not allow overloading the assignment operator, - /// and assigning references would necessitate some unnecessary duplication and extra memory allocations. - /// To solve this problem, MPIR.Net uses the property assignment. - /// The setter of the Value property does what an overloaded assignment operator would do in C++. - /// The syntax is a little different: a.Value = b + c, but it is fluent enough to become a quick habit, - /// and additionally reinforces the concept that an existing object can change its value while reusing internally allocated memory. - /// To this end, all overloaded operators and most functions that operate on MPIR types, - /// instead of eagerly computing a result, produce and return an expression that is basically a formula for the computation. - /// Expressions can then be composed using additional operators to achieve expression trees of arbitrary complexity. - /// All computations are deferred until an expression is assigned to the Value property of an MPIR object, - /// consumed by a method or operator that returns a primitive type, - /// or supplied as an argument to an MPIR type constructor. - /// The getter is a no-op defined to make possible constructs such as a.Value += 5, a.Value *= 10, etc. - /// Direct assignments such as a = b + c, a *= 10 will not compile because there is no implicit conversion from an expression. - /// Even if an implicit conversion were defined, such code would incur an extra allocation plus garbage collection, - /// and would not perform as well as doing the same operations on a.Value. - /// It would also not compile if the source were a "using" variable, as all method-local integers should be. - /// - property MPEXPR_NAME^ Value - { - void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); } - MPEXPR_NAME^ get() { return this; } - } - - /// - /// Sets the value of the integer object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(mpir_ui value) { MP(set_ui)(_value, value); } - - /// - /// Sets the value of the integer object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(mpir_si value) { MP(set_si)(_value, value); } - - /// - /// Sets the value of the integer object. Any fractional portion is truncated. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(double value) { MP(set_d)(_value, value); } - - /// - /// Sets the value of the integer object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object. The string's leading characters may indicate base: - /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise - void SetTo(String^ value) { SetTo(value, 0); } - - /// - /// Sets the value of the integer object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - /// base the string is in. - /// The base may vary from 2 to 62, or if base is 0, then the leading characters are used: 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise. - /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. - /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. - void SetTo(String^ value, int base); - - /// - /// Sets the value of the integer object. Any fractional portion is truncated. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// new value for the object - void SetTo(RationalExpression^ value); - - /// - /// Sets the value of the integer object. Any fractional portion is truncated. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// If the argument is an expression, it is evaluated with the current default float precision. - /// new value for the object - void SetTo(FloatExpression^ value); - - /// - /// Swaps the values of two integers. - /// This operation is a pointer swap and doesn't affect allocated memory. - /// Do not call this method while either object is contained in a hash table, because this would change their hash codes. - /// - /// Source number to swap this instance's value with - void Swap(MPTYPE^ a) - { - MP(swap)(_value, a->_value); - } - - #pragma endregion - - #pragma region bit operations - - /// - /// Sets a single bit at the specified position. - /// - /// Value of the bit to set, true for 1, false for 0 - /// Position of the bit to set. - /// The least significant bit is zero. - /// If position is beyond the current size of the number, the number is extended automatically. - void SetBit(mp_bitcnt_t position, bool value) { value ? MP(setbit)(_value, position) : MP(clrbit)(_value, position); } - - /// - /// Gets a single bit at the specified position. - /// - /// Position of the bit to get. - /// The least significant bit is zero. - /// If position is beyond the current size of the number, returns true for negative number, false for non-negative; the number itself is not extended. - /// true if the specified bit is 1, false if zero. - /// If position is beyond the current size of the number, returns true for negative number, false for non-negative; the number itself is not extended. - bool GetBit(mp_bitcnt_t position) { return MP(tstbit)(_value, position) != 0; } - - /// - /// Complements (inverts) a single bit at the specified position. - /// - /// Position of the bit to flip. - /// The least significant bit is zero. - /// If position is beyond the current size of the number, the number is extended automatically. - void ComplementBit(mp_bitcnt_t position) { MP(combit)(_value, position); } - - #pragma endregion - - #pragma region size checks - -#if BITS_PER_MP_LIMB == 64 - /// - /// Returns true if the value of the integer is in the ulong range. - /// This method is supported only on 64-bit builds - /// - /// true if the value will fit in a ulong - bool FitsUlong() { return MP(fits_ui_p)(_value) != 0; } - - /// - /// Returns true if the value of the integer is in the long range. - /// This method is supported only on 64-bit builds - /// - /// true if the value will fit in a long - bool FitsLong() { return MP(fits_si_p)(_value) != 0; } -#endif - - /// - /// Returns true if the value of the integer is in the uint range. - /// - /// true if the value will fit in a uint - bool FitsUint() { return MP(fits_uint_p)(_value) != 0; } - - /// - /// Returns true if the value of the integer is in the int range. - /// - /// true if the value will fit in a int - bool FitsInt() { return MP(fits_sint_p)(_value) != 0; } - - /// - /// Returns true if the value of the integer is in the ushort range. - /// - /// true if the value will fit in a ushort - bool FitsUshort() { return MP(fits_ushort_p)(_value) != 0; } - - /// - /// Returns true if the value of the integer is in the short range. - /// - /// true if the value will fit in a short - bool FitsShort() { return MP(fits_sshort_p)(_value) != 0; } - - /// - /// Returns the number of digits the number would take if written in the specified base. - /// The sign of the number is ignored, just the absolute value is used. - /// The result will be either exact or 1 too big. - /// If is a power of 2, the result will always be exact. - /// If the number is 0, the result is always 1. - /// This function can be used to estimate the space required when converting to a string. - /// The right amount of allocation is normally two more than the value returned, - /// one extra for a minus sign and one for the null-terminator. - /// It will be noted that base=2 can be used to locate the most significant 1 bit in op, - /// counting from 1 (unlike all bitwise functions, which start from 0). - /// - /// Numeric base for the would-be string conversion, in the range from 2 to 62. - /// The number of digits the number would take written in the specified base, possibly 1 too big, not counting a leading minus. - mp_size_t ApproximateSizeInBase(int base) { return MP(sizeinbase)(_value, base); } - - #pragma endregion - - #pragma region IO - - /// - /// Outputs the integer to the in raw binary format. - /// The number is written in a portable format, with 4 bytes of size information, and that many bytes of limbs. - /// Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). - /// The output can be read with Read(Stream). - /// The output cannot be read by MP(inp_raw) from GMP 1, because of changes necessary - /// for compatibility between 32-bit and 64-bit machines. - /// - /// Stream to output the number to - /// the number of bytes written, or 0 if an error occurs. - size_t Write(Stream^ stream); - - /// - /// Reads the integer value from the in raw binary format, as it would have been written by Write(Stream). - /// The number is read in a portable format, with 4 bytes of size information, and that many bytes of limbs. - /// Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). - /// This routine can read the output from MP(out_raw) also from GMP 1, in spite of changes - /// necessary for compatibility between 32-bit and 64-bit machines. - /// - /// Stream to input the number from - /// the number of bytes read, or 0 if an error occurs. - size_t Read(Stream^ stream); - - /// - /// Outputs the integer to the as a string of digits in decimal. - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not a valid decimal digit. - /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. - /// - /// Text writer to output the number to - /// the number of characters written - size_t Write(TextWriter^ writer) { return Write(writer, 0, false); } - - /// - /// Outputs the integer to the as a string of digits in base . - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not a valid digit in base . - /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. - /// For hexadecimal, binary, or octal, no leading base indication is written. - /// Therefore, for bases other than 10, use the Read(reader, base) overload rather than Read(reader) to read the number back. - /// - /// Text writer to output the number to - /// The base to use for the output. - /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// the number of characters written - size_t Write(TextWriter^ writer, int base) { return Write(writer, base, false); } - - /// - /// Outputs the integer to the as a string of digits in base . - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not a valid digit in base . - /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. - /// For hexadecimal, binary, or octal, no leading base indication is written. - /// Therefore, for bases other than 10, use the Read(reader, base) overload rather than Read(reader) to read the number back. - /// - /// Text writer to output the number to - /// The base to use for the output. - /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. - /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// Indicates if lowercase or uppercase letters should be used for the output. - /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. - /// the number of characters written - size_t Write(TextWriter^ writer, int base, bool lowercase); - - /// - /// Inputs the number as a possibly white-space preceeded string. - /// The base of the number is determined from the leading characters: 0x or 0X for hexadecimal, 0b or 0B for binary, 0 for octal, decimal otherwise. - /// Reading terminates at end-of-stream, or up to but not including a character that is not a valid digit. - /// This method reads the output of a Write(TextWriter) when decimal base is used. - /// For hexadecimal, binary, or octal, because Write(TextWriter) doesn't write leading base indication characters, - /// using this overload of Read will fail to recognize the correct base. - /// Text reader to input the number from - /// the number of characters read - size_t Read(TextReader^ reader) { return Read(reader, 0); } - - /// - /// Inputs the number as a possibly white-space preceeded string in base from the . - /// Reading terminates at end-of-stream, or up to but not including a character that is not a valid digit. - /// This method reads the output of a Write(TextWriter) method. - /// - /// Text reader to input the number from - /// The base to use for the input. - /// The base can be from 2 to 62; For bases up to 36 case is ignored. - /// For bases larger than 36, uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// If 0, the base of the number is determined from the leading characters: 0x or 0X for hexadecimal, 0b or 0B for binary, 0 for octal, decimal otherwise. - /// Note that the leading base characters are not written by the Write method. - /// the number of characters read - size_t Read(TextReader^ reader, int base); - - /// - /// Imports the number from arbitrary words of binary data. - /// No sign information is taken from the data, the imported number will be positive or zero. - /// - /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. - /// Array of binary "limbs" to import from. - /// Elements don't necessarily need to be of the size; the data is interpreted as a flat byte array. - /// Number of "limbs" to import - /// Number of bytes per "limb." - /// Specifies the order of the "limbs." - /// Specifies the byte order within each "limb." - /// The number of most-significant bits to ignore in each "limb." - generic where T : value class void Import(array^ data, size_t limbCount, int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) - { - if(limbCount == 0) - { - MP(set_ui)(_value, 0); - return; - } - - PIN(data); - MP(import)(_value, limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, pinned_data); - } - - /// - /// Exports the absolute value of the number to arbitrary words of binary data. - /// The sign of op is ignored. - /// - /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. - /// Array of binary "limbs" to export to. - /// Elements don't necessarily need to be of the size; the data is interpreted as a flat byte array. - /// The total size of the array in bytes must be sufficient for the export. - /// Number of bytes per "limb." - /// Specifies the order of the "limbs." - /// Specifies the byte order within each "limb." - /// The number of most-significant bits to reserve, and set to zero, in each "limb." - /// The number of limbs exported. - /// If the number is non-zero, then the most significant word produced will be non-zero. - /// If the number is zero, then the count returned will be zero and nothing written to the data. - generic where T : value class size_t Export(array^ data, int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) - { - PIN(data); - size_t limbCount; - MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); - return limbCount; - } - - /// - /// Exports the absolute value of the number to arbitrary words of binary data. An array of type T is allocated for the export. - /// The sign of op is ignored. - /// - /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. - /// Number of bytes per "limb." - /// Specifies the order of the "limbs." - /// Specifies the byte order within each "limb." - /// The number of most-significant bits to reserve, and set to zero, in each "limb." - /// An array of type T containing the exported limb data. - /// If the number is non-zero, then the most significant word produced will be non-zero. - /// If the number is zero, then a zero-length array is returned. - generic where T : value class array^ Export(int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) - { - if(this->Sign() == 0) - return gcnew array(0); - - auto bitsPerLimb = 8 * bytesPerLimb - nails; - auto limbCount = (MP(sizeinbase)(_value, 2) - 1) / bitsPerLimb + 1; - auto arrayCount = (limbCount * bytesPerLimb - 1) / sizeof(T) + 1; - auto data = gcnew array((int)arrayCount); - - PIN(data); - MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); - return data; - } - - /// - /// Reads limb data from the number into an array. - /// - /// The destination array into which limb data will be copied - /// The 0-based index of the first limb to copy - /// The number of limbs to copy - /// The starting index within the array that will receive the first copied limb. - void ReadLimbs(array^ destination, int start, int length, int destinationIndex); - - /// - /// Modifies a portion or all of the limb data within the number by copying from an array. - /// The number is reallocated if necessary to accommodate the limbs. - /// The previous limb data is preserved, so that partial writes are supported. - /// If a partial write begins beyond the currently allocated limb array, any gap is zeroed out. - /// - /// The source array from which limb data will be copied. The limb data need not be normalized - /// The 0-based index within the destination number's limb data that will receive the first copied limb - /// The number of limbs to copy - /// The starting index within the array from which the first limb is to be copied. - /// Specifies the new sign of the number: true if negative, false if non-negative - void ModifyLimbs(array^ source, int start, int length, int sourceIndex, bool negative); - - /// - /// Writes limb data into the number from an array. - /// The number is reallocated if necessary to accommodate the limbs. - /// The previous limb data is not used; this method is suitable for full replacement of limb data only. - /// - /// The source array from which limb data will be copied - /// The new size of the number. The absolute value is the number of limbs to copy, and will be the new number of limbs, and the sign is the new sign of the number. - /// Copying always starts at the beginning of the number's (re-)allocated limb data. The new limb data must be valid, but need not be normalized - /// The starting index within the array from which the first limb is to be copied. - /// Specifies the new sign of the number: true if negative, false if non-negative - void WriteLimbs(array^ source, int sourceIndex, mp_size_t newSize, bool negative); - - internal: - size_t ReadNoWhite(TextReader^ reader, int base, size_t nread); - - public: - - /// - /// Returns the specified limb of the number. - /// The least significant limb is zero. - /// The sign of the number is ignored. - /// - /// The index of the limb to return. - /// The least significant limb is zero. - /// If the index is outside the range 0 to Size()-1, zero is returned. - /// The specified limb, or zero if is outside of the valid range. - size_t GetLimb(mp_size_t index) { return MP(getlimbn)(_value, index); } - - #pragma endregion - - #pragma region number-theoretic - - /// - /// Determines whether the number is a probable prime with the chance of error being at most 1 in 2^. - /// This function does some trial divisions to speed up the average case, then some probabilistic - /// primality tests to achieve the desired level of error. - /// This function interface is preliminary and may change in the future. - /// - /// Random number generator to use for probabilistic primality tests - /// Defines the maximum allowed probability of a false positive. - /// The odds of a composite number being reported as a probable prime are at most 1 in 2^probability - /// Used to inform the function that trial division up to div has already been performed, - /// and so the number is known to have NO divisors <= pretested. - /// Use 0 to inform the function that no trial division has been done. - /// true if the number is probably prime, or false if it is definitely composite. - bool IsProbablePrime(MpirRandom^ random, int probability, mpir_ui pretested); - - /// - /// Determines whether the number is likely a prime, i.e. you can consider it a prime for practical purposes. - /// This function does some trial divisions to speed up the average case, then some probabilistic primality tests. - /// The term "likely" refers to the fact that the number will not have small factors. - /// This function interface is preliminary and may change in the future. - /// - /// Random number generator to use for probabilistic primality tests - /// Used to inform the function that trial division up to div has already been performed, - /// and so the number is known to have NO divisors <= pretested. - /// Use 0 to inform the function that no trial division has been done. - /// true if the number is likely prime, or false if it is definitely composite. - bool IsLikelyPrime(MpirRandom^ random, mpir_ui pretested); - - /// - /// Calculates the Jacobi symbol (/). - /// This is defined only for odd. - /// - /// First source value for the Jacobi symbol - /// Second source value for the Jacobi symbol - /// The Jacobi symbol (-1, 0, or 1). Return is undefined unless is odd. - static int Jacobi(MPTYPE^ a, MPTYPE^ b) { return MP(jacobi)(a->_value, b->_value); } - - /// - /// Calculates the Legendre symbol (/). - /// This is defined only when is an odd prime. - /// - /// First source value for the Legendre symbol - /// Second source value for the Legendre symbol - /// The Legendre symbol (-1, 0, or 1). Return is undefined unless is an odd prime. - static int Legendre(MPTYPE^ a, MPTYPE^ b) { return MP(legendre)(a->_value, b->_value); } - - /// - /// Calculates the Jacobi symbol (/) with the Kronecker extension - /// (/2) = (2/) when a odd, or (/2) = 0 when a even. - /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads - /// can be used for mixed precision Jacobi symbols too. - /// - /// First source value for the Kronecker symbol - /// Second source value for the Kronecker symbol - /// The Kronecker symbol (-1, 0, or 1). - static int Kronecker(MPTYPE^ a, MPTYPE^ b) { return MP(kronecker)(a->_value, b->_value); } - - /// - /// Calculates the Jacobi symbol (/) with the Kronecker extension - /// (/2) = (2/) when a odd, or (/2) = 0 when a even. - /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads - /// can be used for mixed precision Jacobi symbols too. - /// - /// First source value for the Kronecker symbol - /// Second source value for the Kronecker symbol - /// The Kronecker symbol (-1, 0, or 1). - static int Kronecker(MPTYPE^ a, mpir_ui b) { return MP(kronecker_ui)(a->_value, b); } - - /// - /// Calculates the Jacobi symbol (/) with the Kronecker extension - /// (/2) = (2/) when a odd, or (/2) = 0 when a even. - /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads - /// can be used for mixed precision Jacobi symbols too. - /// - /// First source value for the Kronecker symbol - /// Second source value for the Kronecker symbol - /// The Kronecker symbol (-1, 0, or 1). - static int Kronecker(MPTYPE^ a, mpir_si b) { return MP(kronecker_si)(a->_value, b); } - - /// - /// Calculates the Jacobi symbol (/) with the Kronecker extension - /// (/2) = (2/) when a odd, or (/2) = 0 when a even. - /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads - /// can be used for mixed precision Jacobi symbols too. - /// - /// First source value for the Kronecker symbol - /// Second source value for the Kronecker symbol - /// The Kronecker symbol (-1, 0, or 1). - static int Kronecker(mpir_ui a, MPTYPE^ b) { return MP(ui_kronecker)(a, b->_value); } - - /// - /// Calculates the Jacobi symbol (/) with the Kronecker extension - /// (/2) = (2/) when a odd, or (/2) = 0 when a even. - /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads - /// can be used for mixed precision Jacobi symbols too. - /// - /// First source value for the Kronecker symbol - /// Second source value for the Kronecker symbol - /// The Kronecker symbol (-1, 0, or 1). - static int Kronecker(mpir_si a, MPTYPE^ b) { return MP(si_kronecker)(a, b->_value); } - - /// - /// Returns an expression for calculating raised to the specified . - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// Base for the initial value for the new integer instance - /// Power to raise the to when calculating the initial value for the new instance - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ Power(mpir_ui value, mpir_ui power) { return gcnew MPEXPR(PowerUiUi)(value, power); } - - /// - /// Returns an expression for calculating the factorial of . - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// The source number to take the factorial of - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ Factorial(mpir_ui a) { return gcnew MPEXPR(FactorialUiUi)(a, 1); } - - /// - /// Returns an expression for calculating the multifactorial of of the specified order. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// The source number to take the multifactorial of - /// The order of the multifactorial, i.e. 2 for !!, 3 for !!!, etc. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ Factorial(mpir_ui a, mpir_ui order) { return gcnew MPEXPR(FactorialUiUi)(a, order); } - - /// - /// Returns an expression for calculating the primorial of , i.e. the product of all positive prime numbers <= a. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// The source number to take the primorial of - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ Primorial(mpir_ui a) { return gcnew MPEXPR(PrimorialUi)(a); } - - /// - /// Returns an expression for calculating the binomial coefficient (, ), a.k.a. number of k-element combinations out of an n-element set. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// The first source value of the binomial coefficient, a.k.a. set size - /// The second source value of the binomial coefficient, a.k.a. subset size - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ Binomial(mpir_ui n, mpir_ui k) { return gcnew MPEXPR(BinomialUiUi)(n, k); } - - /// - /// Returns an expression for calculating the binomial coefficient (, ), a.k.a. number of k-element combinations out of an n-element set. - /// Negative values of are supported, using the identity (-n, k) = (-1)^k * (n + k - 1, k). - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// - /// The first source value of the binomial coefficient, a.k.a. set size - /// Negative values of are supported, using the identity (-n, k) = (-1)^k * (n + k - 1, k). - /// - /// The second source value of the binomial coefficient, a.k.a. subset size - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR_NAME^ Binomial(MPEXPR_NAME^ n, mpir_ui k) { return gcnew MPEXPR(BinomialIntUi)(n, k); } - - /// - /// Returns an expression for calculating the th Fibonacci number. - /// You can also optionally save the (-1)th number by calling a method on the resulting expression. - /// This method is designed for calculating isolated Fibonacci numbers. When a sequence of - /// values is wanted it’s best to start with a pair of numbers (Fn and Fn-1) by calling SettingPreviousTo(), - /// and then iterate the defining Fn+1 = Fn + Fn-1. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// Fibonacci and Lucas numbers are closely related, and it's never necessary to calculate both Fn and Ln. - /// - /// The index of the Fibonacci number to calculate - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Sequence)^ Fibonacci(mpir_ui n) { return gcnew MPEXPR(FibonacciUi)(n); } - - /// - /// Returns an expression for calculating the th Lucas number. - /// You can also optionally save the (-1)th number by calling a method on the resulting expression. - /// This method is designed for calculating isolated Lucas numbers. When a sequence of - /// values is wanted it’s best to start with a pair of numbers (Ln and Ln-1) by calling SettingPreviousTo(), - /// and then iterate the defining Ln+1 = Ln + Ln-1. - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// Fibonacci and Lucas numbers are closely related, and it's never necessary to calculate both Fn and Ln. - /// - /// The index of the Lucas number to calculate - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - static MPEXPR(Sequence)^ Lucas(mpir_ui n) { return gcnew MPEXPR(LucasUi)(n); } - - #pragma endregion - }; - - #pragma endregion - - #pragma region HugeIntComponent - - /// This internal class is used to provide access to the numerator and denominator of a Rational number. - /// It is a thin override of HugeInt with the only changes being that it does not perform any allocation/cleanup, - /// it simply reuses an mpz_ptr from a Rational struct that is allocated and freed by HugeRational. - /// It inherits the IDisposable implementation from HugeInt, but overrides the DeallocateStruct worker with a no-op. - /// - private ref class HugeIntComponent sealed : MPTYPE - { - internal: - virtual void DeallocateStruct() override { } - HugeIntComponent(MP(ptr) value) { _value = value; } - }; - - #pragma endregion +/* +Copyright 2014 Alex Dyachenko + +This file is part of the MPIR Library. + +The MPIR Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +The MPIR Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the MPIR Library. If not, see http://www.gnu.org/licenses/. +*/ + +#pragma once + +using namespace System; +using namespace System::IO; +using namespace System::Runtime::InteropServices; + +#ifdef SPECIALIZE_EXPRESSIONS +#undef SPECIALIZE_EXPRESSIONS +#undef MP +#undef CUSTOM_MP +#undef MPSTRUCT +#undef MPTYPE +#undef MPTYPE_NAME +#undef MPEXPR_NAME +#undef MPEXPR +#undef CTXT +#undef ASSIGN_TO +#undef Mpt +#undef SET_CONTEXT_PRECISION +#endif +#define SPECIALIZE_EXPRESSIONS +#define Mpt Int +#define CUSTOM_MP(x) custom_mpz_##x +#define MPSTRUCT __mpz_struct +#define MP(x) mpz_##x +#define MPTYPE HugeInt +#define MPTYPE_NAME Integer +#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression +#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression +#define CTXT(x) context.IntArgs[x] +#define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) +#define SET_CONTEXT_PRECISION +#include "ExpressionMacros.h" + +extern __mpz_struct HugeIntConst1; + +namespace MPIR +{ + ref class MpirRandom; + ref class RationalExpression; + ref class FloatExpression; + ref class MPTYPE; + ref class MPEXPR(Multiply); + ref class MPEXPR(Divide); + ref class MPEXPR(DivideUi); + ref class MPEXPR(Mod); + ref class MPEXPR(DivMod); + ref class MPEXPR(ModUi); + ref class MPEXPR(ShiftRight); + ref class MPEXPR(Root); + ref class MPEXPR(SquareRoot); + ref class MPEXPR(Gcd); + ref class MPEXPR(RemoveFactors); + ref class MPEXPR(Sequence); + + #pragma region IntegerExpression + + /// + /// Base class for all integer expressions resulting from many integer operations on MPIR types. + /// Expressions can be arbitrarily nested, and are lazily evaluated + /// when they are either assigned to the Value property of an MPIR object, or are consumed by a function or operator that returns a primitive type. + /// Assignment to the Value property is necessary because .Net does not support overloading the assignment operator. + /// + public ref class MPEXPR_NAME abstract : public IComparable, IComparable, IEquatable + { + internal: + MPEXPR_NAME() { } + virtual void AssignTo(MP(ptr) destination) abstract; + virtual void ASSIGN_TO(EvaluationContext& context) + { + context.Initialized(IntInitialized); + auto ptr = &context.Temp[context.Index].MPTYPE_NAME; + CTXT(context.Index++) = ptr; + MP(init)(ptr); + AssignTo(ptr); + } + virtual void AssignToRational(EvaluationContext& context) + { + context.Initialized(IntInitialized); + auto ptr = &context.Temp[context.Index].Rational; + context.RationalArgs[context.Index++] = ptr; + MP(init)(&ptr->_mp_num); + AssignTo(&ptr->_mp_num); + ptr->_mp_den = HugeIntConst1; + } + static MPEXPR_NAME() + { + MP(init_set_ui)(&HugeIntConst1, 1); + } + + private: + int CompareTo(Object^ a, bool& valid); + + public: + #pragma region Arithmetic and Bitwise logic + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_ui b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (mpir_ui a, MPEXPR_NAME^ b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (MPEXPR_NAME^ a, mpir_si b); + + /// Adds two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to add to + /// Source value to add + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator + (mpir_si a, MPEXPR_NAME^ b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_ui b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (mpir_ui a, MPEXPR_NAME^ b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_si b); + + /// Subtracts two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to subtract from + /// Source value to subtract + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (mpir_si a, MPEXPR_NAME^ b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Multiply)^ operator * (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Multiply)^ operator * (MPEXPR_NAME^ a, mpir_ui b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Multiply)^ operator * (mpir_ui a, MPEXPR_NAME^ b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Multiply)^ operator * (MPEXPR_NAME^ a, mpir_si b); + + /// Multiplies two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Source value to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Multiply)^ operator * (mpir_si a, MPEXPR_NAME^ b); + + /// Shifts the source operand to the left by , i.e. multiplies by 2^. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Number of bits to shift by, i.e. power of 2 to multiply by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator << (MPEXPR_NAME^ a, mp_bitcnt_t bits); + + /// Shifts the source operand to the right by , i.e. divides by 2^. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// By default, the shifted value (i.e., the quotient of the division) is computed. If instead the shifted bits (i.e., the remainder) is desired, you can call + /// the Remainder method on the resulting expression before you assign it. You can also specify the rounding mode to use for the division by calling a method on the resulting expression. + /// Source value to divide + /// Number of bits to shift by, i.e. power of 2 to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// The expression exposes methods you can call to select whether you need to compute the quotient or remainder of the division, and/or to set the rounding mode. + /// By default, the shifted value (i.e., quotient) is computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. + /// + static MPEXPR(ShiftRight)^ operator >> (MPEXPR_NAME^ a, mp_bitcnt_t bits); + + /// Negates the source value. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to negate + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// You can optionally save the remainder or specify the rounding mode to use for the division by calling methods on the resulting expression, before assigning it. + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// The expression exposes methods you can call optionally if you need to save the remainder of the division, and/or to set the rounding mode. + /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. + /// + static MPEXPR(Divide)^ operator / (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Divides two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// You can optionally save the remainder or specify the rounding mode to use for the division by calling methods on the resulting expression, before assigning it. + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// The expression exposes methods you can call optionally if you need to save the remainder of the division, and/or to set the rounding mode. + /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. + /// + static MPEXPR(DivideUi)^ operator / (MPEXPR_NAME^ a, mpir_ui b); + + /// Calculates the remainder from the division of two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// You can optionally save the quotient in addition to the remainder or specify the rounding mode to use for the division + /// by calling methods on the resulting expression, before assigning it. + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// The expression exposes methods you can call optionally if you need to save the quotient in addition to the remainder, and/or to set the rounding mode. + /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. + /// + static MPEXPR(Mod)^ operator % (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Calculates the remainder from the division of two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// You can optionally save the quotient in addition to the remainder or specify the rounding mode to use for the division + /// by calling methods on the resulting expression, before assigning it. + /// Source value to divide + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// The expression exposes methods you can call optionally if you need to save the quotient in addition to the remainder, and/or to set the rounding mode. + /// By default, the remainder is not computed and the rounding mode defaults to the static MpirSettings.DefaultRoundingMode. + /// + static MPEXPR(ModUi)^ operator % (MPEXPR_NAME^ a, mpir_ui b); + + /// Raises the source value to the specified power. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to multiply + /// Power to raise to + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, mpir_ui power); + + /// Computes the bitwise AND of two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to AND + /// Source value to AND with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator & (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Computes the bitwise (inclusive) OR of two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to OR + /// Source value to OR with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator | (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Computes the bitwise XOR (exclusive or) of two numbers. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to XOR + /// Source value to XOR with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, MPEXPR_NAME^ b); + + /// Computes the bitwise complement of a number. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to complement + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ operator ~ (MPEXPR_NAME^ a); + + /// If the source is >= 0, returns the population count of op, which is the number of 1 bits in the binary representation. +#if BITS_PER_MP_LIMB == 64 + /// If the source is < 0, the number of 1s is infinite, and the return value is ulong.MaxValue, the largest possible bit count. +#else + /// If the source is < 0, the number of 1s is infinite, and the return value is uint.MaxValue, the largest possible bit count. +#endif + /// Because the result is a primitive type, it is computed immediately. + /// + /// The population count for a non-negative number + mp_bitcnt_t PopCount() { IN_CONTEXT(this); return MP(popcount)(CTXT(0)); } + + /// If this number and the operand are both >= 0 or both < 0, returns the hamming distance between them, which is the number of bit positions with different bit values. +#if BITS_PER_MP_LIMB == 64 + /// If one operand is >= 0 and the other < 0 then the number of bits different is infinite, and the return value is ulong.MaxValue, the largest possible bit count. +#else + /// If one operand is >= 0 and the other < 0 then the number of bits different is infinite, and the return value is uint.MaxValue, the largest possible bit count. +#endif + /// Because the result is a primitive type, it is computed immediately. + /// + /// Source value to compute the hamming distance to + /// The hamming distance between this number and + mp_bitcnt_t HammingDistance(MPEXPR_NAME^ a) { IN_CONTEXT(this, a); return MP(hamdist)(CTXT(0), CTXT(1)); } + + /// Scans the source number, starting from the bit, towards more significant bits, until the first 0 or 1 bit + /// (depending on the is found, and return the index of the found bit. + /// If the bit at the starting position is already what's sought, then is returned. +#if BITS_PER_MP_LIMB == 64 + /// If there's no bit found, then ulong.MaxValue (the largest possible bit count) is returned. +#else + /// If there's no bit found, then uint.MaxValue (the largest possible bit count) is returned. +#endif + /// This will happen with = true past the end of a non-negative number, or with = false past the end of a negative number. + /// A false bit will always be found at the position past the end of a non-negatitve number, and a true bit past the end of a negative number. + /// + /// Value of the bit to scan for, true for 1, false for 0 + /// Starting bit position to search. The least significant bit is zero. +#if BITS_PER_MP_LIMB == 64 + /// The index of the found bit, or ulong.MaxValue if no bit found. +#else + /// The index of the found bit, or uint.MaxValue if no bit found. +#endif + mp_bitcnt_t FindBit(bool value, mp_bitcnt_t start) { IN_CONTEXT(this); return value ? MP(scan1)(CTXT(0), start) : MP(scan0)(CTXT(0), start); } + + /// Computes the absolute value of the source number. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Abs(); + + /// Divides two numbers where it is known in advance that the division is exact. This method is faster than normal division, + /// but produces an undefined result when the division is not exact. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + MPEXPR_NAME^ DivideExactly(MPEXPR_NAME^ a); + + /// Divides two numbers where it is known in advance that the division is exact. This method is faster than normal division, + /// but produces an undefined result when the division is not exact. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to divide by + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation. + /// + MPEXPR_NAME^ DivideExactly(mpir_ui a); + + /// Raises the source value to the specified modulo . + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Power to raise the source value to. + /// Negative power values are supported if an inverse mod exists, otherwise divide by zero is raised. + /// Modulo to perform the powering operation with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ PowerMod(MPEXPR_NAME^ power, MPEXPR_NAME^ modulo); + + /// Raises the source value to the specified modulo . + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Power to raise the source value to + /// Modulo to perform the powering operation with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ PowerMod(mpir_ui power, MPEXPR_NAME^ modulo); + + /// Computes the truncated integer part of the root of the specified from the source value. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// You can optionally save the remainder from the root operation, or a flag indicating whether the root was exact, + /// by calling a method on the resulting expression, before assigning it. + /// Power of the root to compute. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR(Root)^ Root(mpir_ui power); + + /// Computes the truncated integer part of the square root of the source value. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// You can optionally save the remainder from the root operation + /// by calling a method on the resulting expression, before assigning it. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR(SquareRoot)^ SquareRoot(); + + /// Calculates the remainder from the division of two numbers, using the rounding mode set in MpirSettings.RoundingMode. + /// Because the result is a primitive type, it is computed immediately. + /// + /// divisor to divide the source by + /// The remainder of the division + mpir_ui Mod(mpir_ui a) { return Mod(a, RoundingModes::Default); } + + /// Calculates the remainder from the division of two numbers, using the specified rounding mode. + /// Because the result is a primitive type, it is computed immediately. + /// + /// divisor to divide the source by + /// rounding mode to use for the division + /// The remainder of the division + mpir_ui Mod(mpir_ui a, RoundingModes roundingMode); + + #pragma endregion + + #pragma region Comparisons + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Both this method and Equals() allow the argument to be a RationalExpression, however we do not define mixed equality operators, + /// because otherwise testing for a null/non-null expression would require an awkward explicit cast on the null. + /// Although this only applies to equality operators, while comparison operators could have possibly worked, we're leaving out all mixed operators for now. + /// Since comparison via CompareTo() or Equals() is possible between ints and rationals, operators would just be another way to do the same thing. + /// Value to compare the source with. This can be an integer or rational multi-precision number or expression, or a supported primitive type (long, ulong, or double). + /// A positive number if the source is greater than , negative if less, and zero if they are equal. + virtual int CompareTo(Object^ a) sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Value to compare the source with + /// A positive number if the source is greater than , negative if less, and zero if they are equal. + virtual int CompareTo(MPEXPR_NAME^ a) sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Value to compare the source with + /// true if the values of the source and are equal, false otherwise. + virtual bool Equals(MPEXPR_NAME^ a) sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Both this method and CompareTo() allow the argument to be a RationalExpression, however we do not define mixed equality operators, + /// because otherwise testing for a null/non-null expression would require an awkward explicit cast on the null. + /// Although this only applies to equality operators, while comparison operators could have possibly worked, we're leaving out all mixed operators for now. + /// Since comparison via CompareTo() or Equals() is possible between ints and rationals, operators would just be another way to do the same thing. + /// Value to compare the source with. This can be an integer or rational multi-precision number or expression, or a supported primitive type (long, ulong, or double). + /// true if the values of the source and are equal, false otherwise. + virtual bool Equals(Object^ a) override sealed; + + /// Computes the hash code of the source value. + /// If called on an expression, it is evaluated into a temporary variable before the comparison is performed. + /// Multi-precision classes are mutable with value semantics. The hash code is based on the value, and will change if the value changes. + /// For this reason, the value of an object must not be modified while the object is contained in a hash table. + /// a signed integer hash code for the value. + virtual int GetHashCode() override sealed; + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, mpir_ui b) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, mpir_ui b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (mpir_ui b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (mpir_ui b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, mpir_si b) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, mpir_si b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (mpir_si b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (mpir_si b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (MPEXPR_NAME^ a, double b) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (MPEXPR_NAME^ a, double b) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator < (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) > 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator >= (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) <= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator > (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) < 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator <= (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) >= 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator != (double b, MPEXPR_NAME^ a) { return IS_NULL(a) || a->CompareTo(b) != 0; } + + /// Compares two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Source value to compare + /// Source value to compare with + /// A boolean result of the comparison. + static bool operator == (double b, MPEXPR_NAME^ a) { return !IS_NULL(a) && a->CompareTo(b) == 0; } + + /// Compares the absolute values of two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Value to compare the source with + /// A positive number if the absolute value of the source is greater than the absolute value of , negative if less, and zero if they are equal. + int CompareAbsTo(MPEXPR_NAME^ a) { IN_CONTEXT(this, a); return MP(cmpabs)(CTXT(0), CTXT(1)); } + + /// Compares the absolute values of two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Value to compare the source with + /// A positive number if the absolute value of the source is greater than , negative if less, and zero if they are equal. + int CompareAbsTo(mpir_ui a) { IN_CONTEXT(this); return MP(cmpabs_ui)(CTXT(0), a); } + + /// Compares the absolute values of two numbers. + /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Value to compare the source with + /// A positive number if the absolute value of the source is greater than the absolute value of , negative if less, and zero if they are equal. + int CompareAbsTo(double a) { IN_CONTEXT(this); return MP(cmpabs_d)(CTXT(0), a); } + + /// Calculates the sign (+1, 0, or -1) of the source value. + /// If the source is an expression, it is evaluated into a temporary variable before the sign is computed. + /// + /// +1 if the source is positive, -1 if negative, and 0 if zero. + int Sign() { IN_CONTEXT(this); return MP(sgn)(CTXT(0)); } + + #pragma endregion + + #pragma region Utility methods + + /// + /// Checks if the source is evenly divisible by . + /// Because this method returns a primitive type, it is computed immediately. + /// + /// Divisor to test with. This can be zero; only zero is considired divisible by zero. + /// True if the source is evenly divisible by + bool IsDivisibleBy(MPEXPR_NAME^ a) { IN_CONTEXT(this, a); return MP(divisible_p)(CTXT(0), CTXT(1)) != 0; } + + /// + /// Checks if the source is evenly divisible by . + /// Because this method returns a primitive type, it is computed immediately. + /// + /// Divisor to test with. This can be zero; only zero is considired divisible by zero. + /// True if the source is evenly divisible by + bool IsDivisibleBy(mpir_ui a) { IN_CONTEXT(this); return MP(divisible_ui_p)(CTXT(0), a) != 0; } + + /// + /// Checks if the source is evenly divisible by 2^. + /// Because this method returns a primitive type, it is computed immediately. + /// + /// Power of 2 to use for the divisor + /// True if the source is evenly divisible by 2^ + bool IsDivisibleByPowerOf2(mp_bitcnt_t power) { IN_CONTEXT(this); return MP(divisible_2exp_p)(CTXT(0), power) != 0; } + + /// + /// Checks if the source is congruent to modulo . + /// Because this method returns a primitive type, it is computed immediately. + /// + /// Divisor to test with. This can be zero; only zero is considired divisible by zero. + /// Modulo with respect to which to test for congruency + /// True if the source is congruent to modulo + bool IsCongruentTo(MPEXPR_NAME^ a, MPEXPR_NAME^ mod) { IN_CONTEXT(this, a, mod); return MP(congruent_p)(CTXT(0), CTXT(1), CTXT(2)) != 0; } + + /// + /// Checks if the source is congruent to modulo . + /// Because this method returns a primitive type, it is computed immediately. + /// + /// Divisor to test with. This can be zero; only zero is considired divisible by zero. + /// Modulo with respect to which to test for congruency + /// True if the source is congruent to modulo + bool IsCongruentTo(mpir_ui a, mpir_ui mod) { IN_CONTEXT(this); return MP(congruent_ui_p)(CTXT(0), a, mod) != 0; } + + /// + /// Checks if the source is congruent to modulo 2^. + /// Because this method returns a primitive type, it is computed immediately. + /// + /// Divisor to test with + /// Power of 2 to use for the modulo + /// True if the source is congruent to modulo 2^ + bool IsCongruentToModPowerOf2(MPEXPR_NAME^ a, mp_bitcnt_t power) { IN_CONTEXT(this, a); return MP(congruent_2exp_p)(CTXT(0), CTXT(1), power) != 0; } + + /// + /// Checks if the source is a perfect power. + /// Because this method returns a primitive type, it is computed immediately. + /// Both 0 and 1 are considered perfect powers. + /// Negative values are accepted, but of course can only be odd powers. + /// + /// True if the source is a perfect power + bool IsPerfectPower() { IN_CONTEXT(this); return MP(perfect_power_p)(CTXT(0)) != 0; } + + /// + /// Checks if the source is a perfect square. + /// Because this method returns a primitive type, it is computed immediately. + /// Both 0 and 1 are considered perfect squares. + /// + /// True if the source is a perfect square + bool IsPerfectSquare() { IN_CONTEXT(this); return MP(perfect_square_p)(CTXT(0)) != 0; } + + /// + /// Returns the size of the absolute value of the number, measured in number of limbs. + /// If op is zero, the returned value will be zero. + /// For a HugeInt object, this method simply retrieves the value from a stored private field. + /// However for an expression it can potentially be very expensive, since it requires evaluation of the expression result. + /// Because this method returns a primitive type, it is computed immediately. + /// + /// The number of limbs used to represent the number + size_t Size() { IN_CONTEXT(this); return MP(size)(CTXT(0)); } + + #pragma endregion + + #pragma region Number-theoretic + + /// + /// Looks for the next candidate prime greater than this number. + /// Note that this function will occasionally return composites. + /// It is designed to give a quick method for generating numbers which do not have small prime factors (less than 1000) + /// and which pass a small number of rounds of Miller-Rabin (just two rounds). + /// The test is designed for speed, assuming that a high quality followup test can then be run to ensure primality. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Random number generator to use for probabilistic primality tests + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, performs the requested operation + MPEXPR_NAME^ NextPrimeCandidate(MpirRandom^ random); + + /// Computes the greatest common divisor of this number and . + /// The result is always positive even if one or both inputs are negative (or zero if both inputs are zero). + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to compute the GCD with + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR(Gcd)^ Gcd(MPEXPR_NAME^ a); + + /// + /// Computes the greatest common divisor of this number and . + /// The result is always positive even if the source number is negative. + /// Because the result is a primitive type, it is computed immediately. + /// + /// Source value to compute the GCD with. If zero, zero is returned. + /// The greatest common divisor of the absolute value of this number and . + mpir_ui Gcd(mpir_ui a) { IN_CONTEXT(this); return MP(gcd_ui)(nullptr, CTXT(0), a); } + + /// Computes the least common multiple of this number and . + /// The result is always positive, irrespective of the signs of the source numbers. + /// The result will be zero if either source number is zero. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to compute the LCM with. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Lcm(MPEXPR_NAME^ a); + + /// Computes the least common multiple of this number and . + /// The result is always positive, irrespective of the signs of the source numbers. + /// The result will be zero if either source number is zero. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Source value to compute the LCM with. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Lcm(mpir_ui a); + + /// Computes the inverse of this number modulo . + /// If the inverse exists, the result will satisfy 0 <= result < . + /// If an inverse doesn't exist an ArgumentException is thrown. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Modulo with respect to which to invert the number. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Invert(MPEXPR_NAME^ modulo); + + /// Remove all occurrences of the from the source number. + /// You can optionally save the number of such occurrences that were removed. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Factor to remove from the source number. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR(RemoveFactors)^ RemoveFactors(MPEXPR_NAME^ factor); + + #pragma endregion + }; + + #pragma endregion + + #pragma region MpirSettings + + /// + /// Static class for MPIR settings such as rounding defaults + /// + public ref class MpirSettings abstract sealed + { + private: + static int _toStringDigits; + + internal: + static MPTYPE^ _toStringModulo; + + public: + +#undef GMP_VERSION + + /// + /// Represents the total number of bits in a single MPIR limb, including data bits and nail bits + /// + literal int BITS_PER_LIMB = BITS_PER_UI; + + /// + /// Represents the number of nail bits in a single MPIR limb. Nail bits are used internally by MPIR + /// + literal int NAIL_BITS_PER_LIMB = GMP_NAIL_BITS; + + /// + /// Represents the number of data bits in a single MPIR limb + /// + literal int USABLE_BITS_PER_LIMB = GMP_NUMB_BITS; + + /// + /// Represents the version of GMP with which the underlying MPIR library is compatible + /// + static initonly const Version^ GMP_VERSION = gcnew Version(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL); + + /// + /// Represents the version of the underlying MPIR library + /// + static initonly const Version^ MPIR_VERSION = gcnew Version(_MSC_MPIR_VERSION); + + /// + /// Gets or sets the default rounding mode used for MPIR division operations that don't explicitly specify a rounding mode. + /// Defaults to Truncate. + /// + static property RoundingModes RoundingMode; + + /// + /// Gets or sets the maximum number of digits the object.ToString() method override will output. + /// If a number is longer than this number of digits, it will be output as "[-]...NNNNN" with the least significant digits shown. + /// Defaults to 256. + /// Specifying 0 will cause all digits to be output. This should be used with care, as for example, the debugger calls ToString() + /// on watched objects, and may have performance issues with large objects. + /// + static property int ToStringDigits + { + int get() { return _toStringDigits; } + void set(int value); + } + + static MpirSettings() + { + RoundingMode = RoundingModes::Truncate; + ToStringDigits = 256; + } + }; + + #pragma endregion + + #pragma region mid-level abstract expression specializations + + /// + /// Expression that results from a multiplication operator. Used internally to optimize computations that can use addmul/submul MPIR calls. + /// + public ref class MPEXPR(Multiply) abstract : MPEXPR_NAME + { + internal: + MPEXPR(Multiply)() { } + virtual void AddTo(MP(ptr) destination) abstract; + virtual void SubtractFrom(MP(ptr) destination) abstract; + }; + + /// + /// Expression that results from a division or modulo operator. Allows to set the rounding mode for the division. + /// + public ref class MPEXPR(DivMod) abstract : MPEXPR_NAME + { + internal: + MPEXPR(DivMod)() { } + RoundingModes rounding; + + public: + /// + /// Optionally sets the rounding mode for the division. If not set, the static MpirSettings.RoundingMode will be used. + /// + /// the mode to use. If this is Default, the static MpirSettings.Rounding mode is used. + /// An updated expression, with its internal state updated to use the specified rounding mode. + MPEXPR_NAME^ Rounding(RoundingModes mode) + { + rounding = mode; + return this; + } + }; + + /// + /// Expression that results from a division operator. Allows to save the remainder to a separate result object, and/or set the rounding mode for the division. + /// + public ref class MPEXPR(Divide) abstract : MPEXPR(DivMod) + { + internal: + MPEXPR(Divide)() { } + MPTYPE^ _remainder; + void CUSTOM_MP(div)(MP(ptr) q, MP(srcptr) n, MP(srcptr) d); + + public: + /// + /// Optionally save the remainder of the division to a separate result. This cannot be the same object the resulting division quotient is being assigned to. + /// + /// destination for the remainder. This cannot be the same object the resulting division quotient is being assigned to. + /// An updated expression, with its internal state updated to compute the remainder. + MPEXPR(DivMod)^ SavingRemainderTo(MPTYPE^ destination) + { + _remainder = destination; + return this; + } + }; + + /// + /// Expression that results from a division operator. Allows to save the remainder, and/or set the rounding mode for the division. + /// + public ref class MPEXPR(DivideUi) abstract : MPEXPR(Divide) + { + private: + Action^ _limbRemainder; + + internal: + MPEXPR(DivideUi)() { } + void CUSTOM_MP(div_ui)(MP(ptr) q, MP(srcptr) n, mpir_ui d); + + public: + /// + /// Optionally saves the remainder of the division to a separate result. + /// + /// The delegate that will be called with the remainder of the division. + /// The delegate is called when the division is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. + /// An updated expression, with its internal state updated to compute the remainder. + MPEXPR(Divide)^ SettingRemainderTo(Action^ callback) + { + _limbRemainder = callback; + return this; + } + }; + + /// + /// Expression that results from a modulo operator. Allows to save the division result to a separate object, and/or set the rounding mode for the division. + /// + public ref class MPEXPR(Mod) abstract : MPEXPR(DivMod) + { + internal: + MPEXPR(Mod)() { } + MPTYPE^ _quotient; + void CUSTOM_MP(mod)(MP(ptr) r, MP(srcptr) n, MP(srcptr) d); + + public: + /// + /// Optionally save the quotient of the division to a separate result. This cannot be the same object the resulting division modulo is being assigned to. + /// + /// destination for the quotient. This cannot be the same object the resulting division modulo is being assigned to. + /// An updated expression, with its internal state updated to compute the quotient. + MPEXPR(DivMod)^ SavingQuotientTo(MPTYPE^ destination) + { + _quotient = destination; + return this; + } + }; + + /// + /// Expression that results from a modulo operator. Allows to save the division result to a separate object, and/or set the rounding mode for the division. + /// + public ref class MPEXPR(ModUi) abstract : MPEXPR(Mod) + { + private: + Action^ _limbRemainder; + + internal: + MPEXPR(ModUi)() { } + void CUSTOM_MP(mod_ui)(MP(ptr) r, MP(srcptr) n, mpir_ui d); + + public: + /// + /// Optionally saves the remainder of the division to a separate result. + /// + /// The delegate that will be called with the remainder of the division. + /// The delegate is called when the division is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. + /// An updated expression, with its internal state updated to compute the remainder. + MPEXPR(Mod)^ SettingRemainderTo(Action^ callback) + { + _limbRemainder = callback; + return this; + } + }; + + /// + /// Expression that results from a right shift operator. Allows to save the remainder to a separate result object, and/or set the rounding mode for the division. + /// + public ref class MPEXPR(ShiftRight) abstract : MPEXPR(DivMod) + { + private: + bool _remainder; + + internal: + MPEXPR(ShiftRight)() { } + void CUSTOM_MP(div_2exp)(MP(ptr) q, MP(srcptr) n, mp_bitcnt_t bits); + + public: + /// + /// Computes the remainder of the division, rather than the quotient, which is the default. + /// + /// An updated expression, with its internal state updated to compute the remainder, rather than the quotient. + MPEXPR(DivMod)^ Remainder() + { + _remainder = true; + return this; + } + }; + + /// + /// Expression that results from a square root function. Allows to save the remainder to a separate result object. + /// + public ref class MPEXPR(SquareRoot) abstract : MPEXPR_NAME + { + internal: + MPEXPR(SquareRoot)() { } + MPTYPE^ _remainder; + void CUSTOM_MP(sqrt)(MP(ptr) dest, MP(srcptr) oper); + + public: + /// + /// Optionally saves the remainder of the root operation to a separate result. + /// + /// destination for the remainder. This cannot be the same object the result of the root operation is being assigned to. + /// An updated expression, with its internal state updated to save the remainder. + MPEXPR_NAME^ SavingRemainderTo(MPTYPE^ destination) + { + _remainder = destination; + return this; + } + }; + + /// + /// Expression that results from a root function. Allows to save a flag indicating whether the root was exact, or to save the remainder to a separate result object. + /// + public ref class MPEXPR(Root) abstract : MPEXPR(SquareRoot) + { + private: + Action^ _exact; + + internal: + MPEXPR(Root)() { } + void CUSTOM_MP(root)(MP(ptr) dest, MP(srcptr) oper, mpir_ui power); + + public: + /// + /// Optionally gets a flag indicating whether the root operation was exact. + /// + /// Delegate that will be called with the exact flag. + /// The delegate is called when the root operation is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. + /// An updated expression, with its internal state updated to compute the exact flag. + MPEXPR_NAME^ SettingExactTo(Action^ callback) + { + _exact = callback; + return this; + } + }; + + /// + /// Expression that results from a Gcd method. Allows to additionally compute Diophantine equation multiplier(s). + /// + public ref class MPEXPR(Gcd) abstract : MPEXPR_NAME + { + internal: + MPEXPR(Gcd)() { } + MPTYPE^ _s; + MPTYPE^ _t; + void CUSTOM_MP(gcd)(MP(ptr) dest, MP(srcptr) a, MP(srcptr) b); + + public: + /// + /// Optionally computes and saves the coefficients and such that a + b = g = gcd(a, b). + /// If only one of the coefficients is needed, use null for the other. + /// The values and are chosen such that normally, || < |b|/(2g) and || < |a|/(2g), + /// and these relations define and uniquely. + /// There are a few exceptional cases: + /// If |a| = |b|, then = 0 and = sgn(b). + /// Otherwise, = sgn(a) if b = 0 or |b| = 2g, and = sgn(b) if a = 0 or |a| = 2g. + /// In all cases, = 0 if and only if g = |b|, i.e., if b divides a or a = b = 0. + /// destination for the first coefficient. Can be null if not needed. + /// destination for the second coefficient. Can be null if not needed. + /// An updated expression, with its internal state updated to save the coefficients. + MPEXPR_NAME^ SavingDiophantineMultipliersTo(MPTYPE^ s, MPTYPE^ t) + { + _s = s; + _t = t; + return this; + } + }; + + /// + /// Expression that results from a RemoveFactors method. Allows to additionally save the number of factors that were removed. + /// + public ref class MPEXPR(RemoveFactors) abstract : MPEXPR_NAME + { + internal: + MPEXPR(RemoveFactors)() { } + Action^ _count; + + public: + /// + /// Optionally gets the number of factors removed. + /// + /// Delegate that will be called with the number of factors that were removed. + /// The delegate is called when the root operation is evaluated, i.e. is assigned to the Value property or consumed by a method that returns a primitive type. + /// An updated expression, with its internal state updated to save the number of factors. + MPEXPR_NAME^ SavingCountRemovedTo(Action^ callback) + { + _count = callback; + return this; + } + }; + + /// + /// Expression that results from a method calculating a single number from a sequence, such as a fibonacci or lucas number. Allows to save the previous number in addition to the requested one, so that the sequence can be continued. + /// + public ref class MPEXPR(Sequence) abstract : MPEXPR_NAME + { + internal: + MPEXPR(Sequence)() { } + MPTYPE^ _previous; + + public: + /// + /// Optionally save the previous number in the sequence to a separate result. This cannot be the same object to which the expression is assigned. + /// + /// destination for the previous number. This cannot be the same object to which the expression is assigned. + /// An updated expression, with its internal state updated to additionally compute the previous number. + MPEXPR_NAME^ SavingPreviousTo(MPTYPE^ destination) + { + _previous = destination; + return this; + } + }; + + #pragma endregion + + #pragma region concrete expressions + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Add, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Int, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Int, Si) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Int, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Int, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Int) + +#undef ADDITIONAL_MEMBERS +#define ADDITIONAL_MEMBERS \ + void virtual AddTo(MP(ptr) destination) override; \ + void virtual SubtractFrom(MP(ptr) destination) override; + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Multiply), Multiply, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(Multiply), Multiply, Int, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(Multiply), Multiply, Int, Si) + +#undef ADDITIONAL_MEMBERS +#define ADDITIONAL_MEMBERS + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Int, Bits) + + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Int) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Int) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Divide), Divide, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(DivideUi), Divide, Int, Ui) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(ShiftRight), ShiftRight, Int, Bits) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Mod), Mod, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(ModUi), Mod, Int, Ui) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, DivideExactly, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, DivideExactly, Int, Ui) + + DEFINE_TERNARY_EXPRESSION_WITH_THREE (MPEXPR_NAME, PowerMod, Int) + DEFINE_TERNARY_EXPRESSION_WITH_BUILT_IN_MIDDLE (MPEXPR_NAME, PowerMod, Int, Ui, Int) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Int, Ui) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR(Root), Root, Int, Ui) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR(SquareRoot), SquareRoot, Int) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, And, Int) + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Or, Int) + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Xor, Int) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Complement, Int) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Invert, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, NextPrimeCandidate, Int, Rnd) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(Gcd), Gcd, Int) + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR(RemoveFactors), RemoveFactors, Int) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Lcm, Int) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Lcm, Int, Ui) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Power, Ui, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Factorial, Ui, Ui) + DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Primorial, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR_NAME, Binomial, Ui, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Binomial, Int, Ui) + DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR(Sequence), Fibonacci, Ui) + DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY (MPEXPR(Sequence), Lucas, Ui) + + DEFINE_BINARY_EXPRESSION(MPEXPR_NAME, RandomBits, MpirRandom^, mp_bitcnt_t) + DEFINE_BINARY_EXPRESSION(MPEXPR_NAME, RandomBitsChunky, MpirRandom^, mp_bitcnt_t) + DEFINE_BINARY_EXPRESSION(MPEXPR_NAME, Random, MpirRandom^, MPEXPR_NAME^) + + #pragma endregion + + #pragma region HugeInt class + + /// + /// Multi-precision Integer class. + /// + public ref class MPTYPE : MPEXPR_NAME + { + internal: + //fields + MP(ptr) _value; + + private: + //construction + void AllocateStruct() + { + _value = (MP(ptr))((*__gmp_allocate_func)(sizeof(MPSTRUCT))); + } + void FromString(String^ value, int base); + MPTYPE(bool initialize); + + internal: + String^ ToString(int base, bool lowercase, int maxDigits); + virtual void DeallocateStruct() + { + MP(clear)(_value); + (*__gmp_free_func)(_value, sizeof(MPSTRUCT)); + _value = nullptr; + } + + //assignment + virtual void AssignTo(MP(ptr) destination) override + { + if(destination != _value) + MP(set)(destination, _value); + } + virtual void ASSIGN_TO(EvaluationContext& context) override + { + CTXT(context.Index++) = _value; + } + + public: + #pragma region construction and disposal + + /// + /// Initializes a new integer instance and sets its value to 0 + /// + MPTYPE(); + + /// + /// Initializes a new integer instance, allocating enough memory to hold at least bits, and sets its value to 0. + /// This is only the initial space, integer will grow automatically in the normal way, if necessary, for subsequent values stored. + /// This makes it possible to avoid repeated reallocations if a maximum size is known in advance. + /// + /// Minimum number of bits the initially allocated memory should hold + /// the newly constructed instance + static MPTYPE^ Allocate(mp_bitcnt_t bits); + + /// + /// Initializes a new integer instance and sets its value from the specified string, using leading characters to recognize the base: + /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise. + /// + /// string representing the initial value for the new instance. Whitespace in the string is ignored. + MPTYPE(String^ value) { FromString(value, 0); } + + /// + /// Initializes a new integer instance and sets its value from the specified string + /// + /// string representing the initial value for the new instance. Whitespace in the string is ignored. + /// base the string is in. + /// The base may vary from 2 to 62, or if base is 0, then the leading characters are used: 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise. + /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. + /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. + MPTYPE(String^ value, int base) { FromString(value, base); } + + /// + /// Initializes a new integer instance and sets its value to the result of computing the source expression. + /// + /// the expression that will be computed, and the result set as the initial value of the new instance. + MPTYPE(MPEXPR_NAME^ value); + + /// + /// Constructs and returns a new integer instance with its value set to the parameter. + /// + /// Initial value for the new integer instance + MPTYPE(mpir_si value); + + /// + /// Constructs and returns a new integer instance with its value set to the parameter. + /// + /// Initial value for the new integer instance + MPTYPE(mpir_ui value); + + /// + /// Constructs and returns a new integer instance with its value set to the parameter. + /// + /// Initial value for the new integer instance. Any fractional portion is truncated. + MPTYPE(double value); + + /// + /// Change the space allocated for integer to bits. The value in integer is preserved if it fits, or is set to 0 if not. + /// This function can be used to increase the space for a variable in order to avoid repeated automatic reallocations, or to decrease it to give memory back to the heap. + /// + /// Minimum number of bits the allocated memory should hold + void Reallocate(mp_bitcnt_t bits) { MP(realloc2)(_value, bits); } + + //disposal + + //creating a destructor in C++ implements IDisposable. + + /// + /// Frees all memory allocated by the instance. + /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. + /// + ~MPTYPE() { this->!MPTYPE(); } + + /// + /// Frees all memory allocated by the instance. + /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory. + /// + !MPTYPE() { if(_value != 0) DeallocateStruct(); } + + #pragma endregion + + #pragma region Properties + + /// + /// Gets the number of limbs currently allocated. This value will never be less than Size(). + /// When a new value is assigned to the object, more space is automatically allocated if necessary. + /// Reallocate() can also be used manually. + /// + property int AllocatedSize + { + int get() { return _value->_mp_alloc; } + } + + #pragma endregion + + #pragma region conversions + + /// + /// Converts the number to a string. + /// To avoid debugging performance problems, this method outputs at most the number of digits specified in MpirSettings.ToStringDigits. + /// If the number is larger, the least significant digits are shown with a leading ellipsis (i.e., [-]...NNNNN) + /// Setting MpirSettings.ToStringDigits to 0 removes the upper limit. + /// + /// A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits. + virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits); } + + /// + /// Converts the number to a string in the specified base. + /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. + /// + /// The base to use for the output. The base can be from 2 to 62; uppercase letters represent digits 10-35 and lowercase letters represent digits 36-61. + /// A string representation of the number in the specified base. + String^ ToString(int base) { return ToString(base, false, 0); } + + /// + /// Converts the number to a string in the specified base. + /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. + /// + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// A string representation of the number in the specified base. + String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0); } + +#if BITS_PER_MP_LIMB == 64 + /// + /// Returns the absolute value of the number as a ulong. + /// If the number is too big, then just the least significant bits that do fit are returned. + /// The sign of the number is ignored, only the absolute value is used. + /// This method is supported only on 64-bit builds + /// + /// The absolute value as a ulong, possibly truncated to the least significant bits only. + mpir_ui ToUlong() { return MP(get_ui)(_value); } + + /// + /// Returns the value of the number as a long. + /// If the number is too big, then just the least significant bits that do fit are returned, with the same sign as the number. + /// When truncation occurs, the result is propobly not very useful. Call FitsLong() to check if the number will fit. + /// This method is supported only on 64-bit builds + /// + /// The value as a long, possibly truncated to the least significant bits only. + mpir_si ToLong() { return MP(get_si)(_value); } +#else + /// + /// Returns the absolute value of the number as a uint. + /// If the number is too big, then just the least significant bits that do fit are returned. + /// The sign of the number is ignored, only the absolute value is used. + /// This method is supported only on 32-bit builds + /// + /// The absolute value as a uint, possibly truncated to the least significant bits only. + mpir_ui ToUint() { return MP(get_ui)(_value); } + + /// + /// Returns the value of the number as an int. + /// If the number is too big, then just the least significant bits that do fit are returned, with the same sign as the number. + /// When truncation occurs, the result is propobly not very useful. Call FitsInt() to check if the number will fit. + /// This method is supported only on 32-bit builds + /// + /// The value as an int, possibly truncated to the least significant bits only. + mpir_si ToInt() { return MP(get_si)(_value); } +#endif + + /// + /// Returns the value of the number as a double, truncating if necessary (rounding towards zero). + /// If the exponent from the conversion is too big, the result is system dependent. An infinity is returned where available. + /// A hardware overflow trap may or may not occur. + /// + /// The value as a double, possibly truncated. + double ToDouble() { return MP(get_d)(_value); } + + /// + /// Returns the value of the number as a double, truncating if necessary (rounding towards zero), and returning the exponent separately. + /// The return is the mantissa, its absolute value will be in the range [0.5 - 1). + /// If the source value is zero, both mantissa and exponent are returned as 0. + /// + /// variable to store the exponent in. + /// The mantissa of the value as a double, possibly truncated. + double ToDouble([Out] mpir_si% exp) + { + double result; + exp = MP(get_2exp_d)(&result, _value); + return result; + } + + #pragma endregion + + #pragma region assignment + + /// + /// When getting, returns this integer. + /// When setting, sets the value of the integer object to the value resulting from computing the supplied expression. + /// The getter is a no-op and never needs to be invoked directly, but makes compound operators such as +=, *=, etc. possible. + /// Do not set the Value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// + /// MPIR types are implemented as reference types with value semantics. + /// Like Strings, the objects themselves are just lightweight pointers to data allocated elsewhere. + /// Unlike Strings, MPIR types are mutable. + /// Value semantics requires you to be able to code, a = b + c. + /// However, .Net (outside of C++) does not allow overloading the assignment operator, + /// and assigning references would necessitate some unnecessary duplication and extra memory allocations. + /// To solve this problem, MPIR.Net uses the property assignment. + /// The setter of the Value property does what an overloaded assignment operator would do in C++. + /// The syntax is a little different: a.Value = b + c, but it is fluent enough to become a quick habit, + /// and additionally reinforces the concept that an existing object can change its value while reusing internally allocated memory. + /// To this end, all overloaded operators and most functions that operate on MPIR types, + /// instead of eagerly computing a result, produce and return an expression that is basically a formula for the computation. + /// Expressions can then be composed using additional operators to achieve expression trees of arbitrary complexity. + /// All computations are deferred until an expression is assigned to the Value property of an MPIR object, + /// consumed by a method or operator that returns a primitive type, + /// or supplied as an argument to an MPIR type constructor. + /// The getter is a no-op defined to make possible constructs such as a.Value += 5, a.Value *= 10, etc. + /// Direct assignments such as a = b + c, a *= 10 will not compile because there is no implicit conversion from an expression. + /// Even if an implicit conversion were defined, such code would incur an extra allocation plus garbage collection, + /// and would not perform as well as doing the same operations on a.Value. + /// It would also not compile if the source were a "using" variable, as all method-local integers should be. + /// + property MPEXPR_NAME^ Value + { + void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); } + MPEXPR_NAME^ get() { return this; } + } + + /// + /// Sets the value of the integer object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(mpir_ui value) { MP(set_ui)(_value, value); } + + /// + /// Sets the value of the integer object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(mpir_si value) { MP(set_si)(_value, value); } + + /// + /// Sets the value of the integer object. Any fractional portion is truncated. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(double value) { MP(set_d)(_value, value); } + + /// + /// Sets the value of the integer object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object. The string's leading characters may indicate base: + /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise + void SetTo(String^ value) { SetTo(value, 0); } + + /// + /// Sets the value of the integer object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + /// base the string is in. + /// The base may vary from 2 to 62, or if base is 0, then the leading characters are used: 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise. + /// For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. + /// For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61. + void SetTo(String^ value, int base); + + /// + /// Sets the value of the integer object. Any fractional portion is truncated. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// new value for the object + void SetTo(RationalExpression^ value); + + /// + /// Sets the value of the integer object. Any fractional portion is truncated. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// If the argument is an expression, it is evaluated with the current default float precision. + /// new value for the object + void SetTo(FloatExpression^ value); + + /// + /// Swaps the values of two integers. + /// This operation is a pointer swap and doesn't affect allocated memory. + /// Do not call this method while either object is contained in a hash table, because this would change their hash codes. + /// + /// Source number to swap this instance's value with + void Swap(MPTYPE^ a) + { + MP(swap)(_value, a->_value); + } + + #pragma endregion + + #pragma region bit operations + + /// + /// Sets a single bit at the specified position. + /// + /// Value of the bit to set, true for 1, false for 0 + /// Position of the bit to set. + /// The least significant bit is zero. + /// If position is beyond the current size of the number, the number is extended automatically. + void SetBit(mp_bitcnt_t position, bool value) { value ? MP(setbit)(_value, position) : MP(clrbit)(_value, position); } + + /// + /// Gets a single bit at the specified position. + /// + /// Position of the bit to get. + /// The least significant bit is zero. + /// If position is beyond the current size of the number, returns true for negative number, false for non-negative; the number itself is not extended. + /// true if the specified bit is 1, false if zero. + /// If position is beyond the current size of the number, returns true for negative number, false for non-negative; the number itself is not extended. + bool GetBit(mp_bitcnt_t position) { return MP(tstbit)(_value, position) != 0; } + + /// + /// Complements (inverts) a single bit at the specified position. + /// + /// Position of the bit to flip. + /// The least significant bit is zero. + /// If position is beyond the current size of the number, the number is extended automatically. + void ComplementBit(mp_bitcnt_t position) { MP(combit)(_value, position); } + + #pragma endregion + + #pragma region size checks + +#if BITS_PER_MP_LIMB == 64 + /// + /// Returns true if the value of the integer is in the ulong range. + /// This method is supported only on 64-bit builds + /// + /// true if the value will fit in a ulong + bool FitsUlong() { return MP(fits_ui_p)(_value) != 0; } + + /// + /// Returns true if the value of the integer is in the long range. + /// This method is supported only on 64-bit builds + /// + /// true if the value will fit in a long + bool FitsLong() { return MP(fits_si_p)(_value) != 0; } +#endif + + /// + /// Returns true if the value of the integer is in the uint range. + /// + /// true if the value will fit in a uint + bool FitsUint() { return MP(fits_uint_p)(_value) != 0; } + + /// + /// Returns true if the value of the integer is in the int range. + /// + /// true if the value will fit in a int + bool FitsInt() { return MP(fits_sint_p)(_value) != 0; } + + /// + /// Returns true if the value of the integer is in the ushort range. + /// + /// true if the value will fit in a ushort + bool FitsUshort() { return MP(fits_ushort_p)(_value) != 0; } + + /// + /// Returns true if the value of the integer is in the short range. + /// + /// true if the value will fit in a short + bool FitsShort() { return MP(fits_sshort_p)(_value) != 0; } + + /// + /// Returns the number of digits the number would take if written in the specified base. + /// The sign of the number is ignored, just the absolute value is used. + /// The result will be either exact or 1 too big. + /// If is a power of 2, the result will always be exact. + /// If the number is 0, the result is always 1. + /// This function can be used to estimate the space required when converting to a string. + /// The right amount of allocation is normally two more than the value returned, + /// one extra for a minus sign and one for the null-terminator. + /// It will be noted that base=2 can be used to locate the most significant 1 bit in op, + /// counting from 1 (unlike all bitwise functions, which start from 0). + /// + /// Numeric base for the would-be string conversion, in the range from 2 to 62. + /// The number of digits the number would take written in the specified base, possibly 1 too big, not counting a leading minus. + mp_size_t ApproximateSizeInBase(int base) { return MP(sizeinbase)(_value, base); } + + #pragma endregion + + #pragma region IO + + /// + /// Outputs the integer to the in raw binary format. + /// The number is written in a portable format, with 4 bytes of size information, and that many bytes of limbs. + /// Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). + /// The output can be read with Read(Stream). + /// The output cannot be read by MP(inp_raw) from GMP 1, because of changes necessary + /// for compatibility between 32-bit and 64-bit machines. + /// + /// Stream to output the number to + /// the number of bytes written, or 0 if an error occurs. + size_t Write(Stream^ stream); + + /// + /// Reads the integer value from the in raw binary format, as it would have been written by Write(Stream). + /// The number is read in a portable format, with 4 bytes of size information, and that many bytes of limbs. + /// Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). + /// This routine can read the output from MP(out_raw) also from GMP 1, in spite of changes + /// necessary for compatibility between 32-bit and 64-bit machines. + /// + /// Stream to input the number from + /// the number of bytes read, or 0 if an error occurs. + size_t Read(Stream^ stream); + + /// + /// Outputs the integer to the as a string of digits in decimal. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not a valid decimal digit. + /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. + /// + /// Text writer to output the number to + /// the number of characters written + size_t Write(TextWriter^ writer) { return Write(writer, 0, false); } + + /// + /// Outputs the integer to the as a string of digits in base . + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not a valid digit in base . + /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. + /// For hexadecimal, binary, or octal, no leading base indication is written. + /// Therefore, for bases other than 10, use the Read(reader, base) overload rather than Read(reader) to read the number back. + /// + /// Text writer to output the number to + /// The base to use for the output. + /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// the number of characters written + size_t Write(TextWriter^ writer, int base) { return Write(writer, base, false); } + + /// + /// Outputs the integer to the as a string of digits in base . + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not a valid digit in base . + /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. + /// For hexadecimal, binary, or octal, no leading base indication is written. + /// Therefore, for bases other than 10, use the Read(reader, base) overload rather than Read(reader) to read the number back. + /// + /// Text writer to output the number to + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// the number of characters written + size_t Write(TextWriter^ writer, int base, bool lowercase); + + /// + /// Inputs the number as a possibly white-space preceeded string. + /// The base of the number is determined from the leading characters: 0x or 0X for hexadecimal, 0b or 0B for binary, 0 for octal, decimal otherwise. + /// Reading terminates at end-of-stream, or up to but not including a character that is not a valid digit. + /// This method reads the output of a Write(TextWriter) when decimal base is used. + /// For hexadecimal, binary, or octal, because Write(TextWriter) doesn't write leading base indication characters, + /// using this overload of Read will fail to recognize the correct base. + /// Text reader to input the number from + /// the number of characters read + size_t Read(TextReader^ reader) { return Read(reader, 0); } + + /// + /// Inputs the number as a possibly white-space preceeded string in base from the . + /// Reading terminates at end-of-stream, or up to but not including a character that is not a valid digit. + /// This method reads the output of a Write(TextWriter) method. + /// + /// Text reader to input the number from + /// The base to use for the input. + /// The base can be from 2 to 62; For bases up to 36 case is ignored. + /// For bases larger than 36, uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// If 0, the base of the number is determined from the leading characters: 0x or 0X for hexadecimal, 0b or 0B for binary, 0 for octal, decimal otherwise. + /// Note that the leading base characters are not written by the Write method. + /// the number of characters read + size_t Read(TextReader^ reader, int base); + + /// + /// Imports the number from arbitrary words of binary data. + /// No sign information is taken from the data, the imported number will be positive or zero. + /// + /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. + /// Array of binary "limbs" to import from. + /// Elements don't necessarily need to be of the size; the data is interpreted as a flat byte array. + /// Number of "limbs" to import + /// Number of bytes per "limb." + /// Specifies the order of the "limbs." + /// Specifies the byte order within each "limb." + /// The number of most-significant bits to ignore in each "limb." + generic where T : value class void Import(array^ data, size_t limbCount, int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) + { + if(limbCount == 0) + { + MP(set_ui)(_value, 0); + return; + } + + PIN(data); + MP(import)(_value, limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, pinned_data); + } + + /// + /// Exports the absolute value of the number to arbitrary words of binary data. + /// The sign of op is ignored. + /// + /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. + /// Array of binary "limbs" to export to. + /// Elements don't necessarily need to be of the size; the data is interpreted as a flat byte array. + /// The total size of the array in bytes must be sufficient for the export. + /// Number of bytes per "limb." + /// Specifies the order of the "limbs." + /// Specifies the byte order within each "limb." + /// The number of most-significant bits to reserve, and set to zero, in each "limb." + /// The number of limbs exported. + /// If the number is non-zero, then the most significant word produced will be non-zero. + /// If the number is zero, then the count returned will be zero and nothing written to the data. + generic where T : value class size_t Export(array^ data, int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) + { + PIN(data); + size_t limbCount; + MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); + return limbCount; + } + + /// + /// Exports the absolute value of the number to arbitrary words of binary data. An array of type T is allocated for the export. + /// The sign of op is ignored. + /// + /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. + /// Number of bytes per "limb." + /// Specifies the order of the "limbs." + /// Specifies the byte order within each "limb." + /// The number of most-significant bits to reserve, and set to zero, in each "limb." + /// An array of type T containing the exported limb data. + /// If the number is non-zero, then the most significant word produced will be non-zero. + /// If the number is zero, then a zero-length array is returned. + generic where T : value class array^ Export(int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) + { + if(this->Sign() == 0) + return gcnew array(0); + + auto bitsPerLimb = 8 * bytesPerLimb - nails; + auto limbCount = (MP(sizeinbase)(_value, 2) - 1) / bitsPerLimb + 1; + auto arrayCount = (limbCount * bytesPerLimb - 1) / sizeof(T) + 1; + auto data = gcnew array((int)arrayCount); + + PIN(data); + MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); + return data; + } + + /// + /// Reads limb data from the number into an array. + /// + /// The destination array into which limb data will be copied + /// The 0-based index of the first limb to copy + /// The number of limbs to copy + /// The starting index within the array that will receive the first copied limb. + void ReadLimbs(array^ destination, int start, int length, int destinationIndex); + + /// + /// Modifies a portion or all of the limb data within the number by copying from an array. + /// The number is reallocated if necessary to accommodate the limbs. + /// The previous limb data is preserved, so that partial writes are supported. + /// If a partial write begins beyond the currently allocated limb array, any gap is zeroed out. + /// + /// The source array from which limb data will be copied. The limb data need not be normalized + /// The 0-based index within the destination number's limb data that will receive the first copied limb + /// The number of limbs to copy + /// The starting index within the array from which the first limb is to be copied. + /// Specifies the new sign of the number: true if negative, false if non-negative + void ModifyLimbs(array^ source, int start, int length, int sourceIndex, bool negative); + + /// + /// Writes limb data into the number from an array. + /// The number is reallocated if necessary to accommodate the limbs. + /// The previous limb data is not used; this method is suitable for full replacement of limb data only. + /// + /// The source array from which limb data will be copied + /// The new size of the number. The absolute value is the number of limbs to copy, and will be the new number of limbs, and the sign is the new sign of the number. + /// Copying always starts at the beginning of the number's (re-)allocated limb data. The new limb data must be valid, but need not be normalized + /// The starting index within the array from which the first limb is to be copied. + /// Specifies the new sign of the number: true if negative, false if non-negative + void WriteLimbs(array^ source, int sourceIndex, mp_size_t newSize, bool negative); + + internal: + size_t ReadNoWhite(TextReader^ reader, int base, size_t nread); + + public: + + /// + /// Returns the specified limb of the number. + /// The least significant limb is zero. + /// The sign of the number is ignored. + /// + /// The index of the limb to return. + /// The least significant limb is zero. + /// If the index is outside the range 0 to Size()-1, zero is returned. + /// The specified limb, or zero if is outside of the valid range. + size_t GetLimb(mp_size_t index) { return MP(getlimbn)(_value, index); } + + #pragma endregion + + #pragma region number-theoretic + + /// + /// Determines whether the number is a probable prime with the chance of error being at most 1 in 2^. + /// This function does some trial divisions to speed up the average case, then some probabilistic + /// primality tests to achieve the desired level of error. + /// This function interface is preliminary and may change in the future. + /// + /// Random number generator to use for probabilistic primality tests + /// Defines the maximum allowed probability of a false positive. + /// The odds of a composite number being reported as a probable prime are at most 1 in 2^probability + /// Used to inform the function that trial division up to div has already been performed, + /// and so the number is known to have NO divisors <= pretested. + /// Use 0 to inform the function that no trial division has been done. + /// true if the number is probably prime, or false if it is definitely composite. + bool IsProbablePrime(MpirRandom^ random, int probability, mpir_ui pretested); + + /// + /// Determines whether the number is likely a prime, i.e. you can consider it a prime for practical purposes. + /// This function does some trial divisions to speed up the average case, then some probabilistic primality tests. + /// The term "likely" refers to the fact that the number will not have small factors. + /// This function interface is preliminary and may change in the future. + /// + /// Random number generator to use for probabilistic primality tests + /// Used to inform the function that trial division up to div has already been performed, + /// and so the number is known to have NO divisors <= pretested. + /// Use 0 to inform the function that no trial division has been done. + /// true if the number is likely prime, or false if it is definitely composite. + bool IsLikelyPrime(MpirRandom^ random, mpir_ui pretested); + + /// + /// Calculates the Jacobi symbol (/). + /// This is defined only for odd. + /// + /// First source value for the Jacobi symbol + /// Second source value for the Jacobi symbol + /// The Jacobi symbol (-1, 0, or 1). Return is undefined unless is odd. + static int Jacobi(MPTYPE^ a, MPTYPE^ b) { return MP(jacobi)(a->_value, b->_value); } + + /// + /// Calculates the Legendre symbol (/). + /// This is defined only when is an odd prime. + /// + /// First source value for the Legendre symbol + /// Second source value for the Legendre symbol + /// The Legendre symbol (-1, 0, or 1). Return is undefined unless is an odd prime. + static int Legendre(MPTYPE^ a, MPTYPE^ b) { return MP(legendre)(a->_value, b->_value); } + + /// + /// Calculates the Jacobi symbol (/) with the Kronecker extension + /// (/2) = (2/) when a odd, or (/2) = 0 when a even. + /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads + /// can be used for mixed precision Jacobi symbols too. + /// + /// First source value for the Kronecker symbol + /// Second source value for the Kronecker symbol + /// The Kronecker symbol (-1, 0, or 1). + static int Kronecker(MPTYPE^ a, MPTYPE^ b) { return MP(kronecker)(a->_value, b->_value); } + + /// + /// Calculates the Jacobi symbol (/) with the Kronecker extension + /// (/2) = (2/) when a odd, or (/2) = 0 when a even. + /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads + /// can be used for mixed precision Jacobi symbols too. + /// + /// First source value for the Kronecker symbol + /// Second source value for the Kronecker symbol + /// The Kronecker symbol (-1, 0, or 1). + static int Kronecker(MPTYPE^ a, mpir_ui b) { return MP(kronecker_ui)(a->_value, b); } + + /// + /// Calculates the Jacobi symbol (/) with the Kronecker extension + /// (/2) = (2/) when a odd, or (/2) = 0 when a even. + /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads + /// can be used for mixed precision Jacobi symbols too. + /// + /// First source value for the Kronecker symbol + /// Second source value for the Kronecker symbol + /// The Kronecker symbol (-1, 0, or 1). + static int Kronecker(MPTYPE^ a, mpir_si b) { return MP(kronecker_si)(a->_value, b); } + + /// + /// Calculates the Jacobi symbol (/) with the Kronecker extension + /// (/2) = (2/) when a odd, or (/2) = 0 when a even. + /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads + /// can be used for mixed precision Jacobi symbols too. + /// + /// First source value for the Kronecker symbol + /// Second source value for the Kronecker symbol + /// The Kronecker symbol (-1, 0, or 1). + static int Kronecker(mpir_ui a, MPTYPE^ b) { return MP(ui_kronecker)(a, b->_value); } + + /// + /// Calculates the Jacobi symbol (/) with the Kronecker extension + /// (/2) = (2/) when a odd, or (/2) = 0 when a even. + /// When is odd the Jacobi symbol and Kronecker symbol are identical, so the various Kronecker overloads + /// can be used for mixed precision Jacobi symbols too. + /// + /// First source value for the Kronecker symbol + /// Second source value for the Kronecker symbol + /// The Kronecker symbol (-1, 0, or 1). + static int Kronecker(mpir_si a, MPTYPE^ b) { return MP(si_kronecker)(a, b->_value); } + + /// + /// Returns an expression for calculating raised to the specified . + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// Base for the initial value for the new integer instance + /// Power to raise the to when calculating the initial value for the new instance + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ Power(mpir_ui value, mpir_ui power) { return gcnew MPEXPR(PowerUiUi)(value, power); } + + /// + /// Returns an expression for calculating the factorial of . + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// The source number to take the factorial of + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ Factorial(mpir_ui a) { return gcnew MPEXPR(FactorialUiUi)(a, 1); } + + /// + /// Returns an expression for calculating the multifactorial of of the specified order. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// The source number to take the multifactorial of + /// The order of the multifactorial, i.e. 2 for !!, 3 for !!!, etc. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ Factorial(mpir_ui a, mpir_ui order) { return gcnew MPEXPR(FactorialUiUi)(a, order); } + + /// + /// Returns an expression for calculating the primorial of , i.e. the product of all positive prime numbers <= a. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// The source number to take the primorial of + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ Primorial(mpir_ui a) { return gcnew MPEXPR(PrimorialUi)(a); } + + /// + /// Returns an expression for calculating the binomial coefficient (, ), a.k.a. number of k-element combinations out of an n-element set. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// The first source value of the binomial coefficient, a.k.a. set size + /// The second source value of the binomial coefficient, a.k.a. subset size + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ Binomial(mpir_ui n, mpir_ui k) { return gcnew MPEXPR(BinomialUiUi)(n, k); } + + /// + /// Returns an expression for calculating the binomial coefficient (, ), a.k.a. number of k-element combinations out of an n-element set. + /// Negative values of are supported, using the identity (-n, k) = (-1)^k * (n + k - 1, k). + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// The first source value of the binomial coefficient, a.k.a. set size + /// Negative values of are supported, using the identity (-n, k) = (-1)^k * (n + k - 1, k). + /// + /// The second source value of the binomial coefficient, a.k.a. subset size + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR_NAME^ Binomial(MPEXPR_NAME^ n, mpir_ui k) { return gcnew MPEXPR(BinomialIntUi)(n, k); } + + /// + /// Returns an expression for calculating the th Fibonacci number. + /// You can also optionally save the (-1)th number by calling a method on the resulting expression. + /// This method is designed for calculating isolated Fibonacci numbers. When a sequence of + /// values is wanted it’s best to start with a pair of numbers (Fn and Fn-1) by calling SettingPreviousTo(), + /// and then iterate the defining Fn+1 = Fn + Fn-1. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// Fibonacci and Lucas numbers are closely related, and it's never necessary to calculate both Fn and Ln. + /// + /// The index of the Fibonacci number to calculate + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Sequence)^ Fibonacci(mpir_ui n) { return gcnew MPEXPR(FibonacciUi)(n); } + + /// + /// Returns an expression for calculating the th Lucas number. + /// You can also optionally save the (-1)th number by calling a method on the resulting expression. + /// This method is designed for calculating isolated Lucas numbers. When a sequence of + /// values is wanted it’s best to start with a pair of numbers (Ln and Ln-1) by calling SettingPreviousTo(), + /// and then iterate the defining Ln+1 = Ln + Ln-1. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// Fibonacci and Lucas numbers are closely related, and it's never necessary to calculate both Fn and Ln. + /// + /// The index of the Lucas number to calculate + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + static MPEXPR(Sequence)^ Lucas(mpir_ui n) { return gcnew MPEXPR(LucasUi)(n); } + + #pragma endregion + }; + + #pragma endregion + + #pragma region HugeIntComponent + + /// This internal class is used to provide access to the numerator and denominator of a Rational number. + /// It is a thin override of HugeInt with the only changes being that it does not perform any allocation/cleanup, + /// it simply reuses an mpz_ptr from a Rational struct that is allocated and freed by HugeRational. + /// It inherits the IDisposable implementation from HugeInt, but overrides the DeallocateStruct worker with a no-op. + /// + private ref class HugeIntComponent sealed : MPTYPE + { + internal: + virtual void DeallocateStruct() override { } + HugeIntComponent(MP(ptr) value) { _value = value; } + }; + + #pragma endregion }; \ No newline at end of file