diff --git a/mpir.net/mpir.net-tests/HugeRationalTests/Arithmetic.cs b/mpir.net/mpir.net-tests/HugeRationalTests/Arithmetic.cs index 24dac616..c65050e8 100644 --- a/mpir.net/mpir.net-tests/HugeRationalTests/Arithmetic.cs +++ b/mpir.net/mpir.net-tests/HugeRationalTests/Arithmetic.cs @@ -374,6 +374,39 @@ namespace MPIR.Tests.HugeRationalTests #endregion + #region Invert + + [TestMethod] + public void RationalInvert() + { + using(var a = new HugeRational("-24092854092874502983745029345723098457209/115756986668303657898962467957")) + { + a.Value = a.Invert(); + Assert.AreEqual("-115756986668303657898962467957/24092854092874502983745029345723098457209", a.ToString()); + a.Value = a.Invert(); + Assert.AreEqual("-24092854092874502983745029345723098457209/115756986668303657898962467957", a.ToString()); + } + } + + #endregion + + #region Power + + [TestMethod] + public void RationalPower() + { + using(var n = new HugeInt("-24092854092874502983745029345723098457209")) + using(var d = new HugeInt("115756986668303657898962467957")) + using(var a = new HugeRational(n, d)) + { + a.Value = a ^ 5; + Assert.AreEqual(n ^ 5, a.Numerator); + Assert.AreEqual(d ^ 5, a.Denominator); + } + } + + #endregion + #region Divide #region Int @@ -434,6 +467,39 @@ namespace MPIR.Tests.HugeRationalTests } } + [TestMethod] + public void RationalDivideSignedLimb() + { + using(var a = new HugeRational("115756986668303657898962467957/39458029384750298767200622330399462537522498")) + { + long b = -5931690917503076532; + a.Value = a / b; + Assert.AreEqual("-115756986668303657898962467957/234052834524092854092874502983745029345723092857791404165816936", a.ToString()); + } + } + + [TestMethod] + public void RationalDivideLimbBy() + { + using(var a = new HugeRational("115756986668303657898962467957/39458029384750298767200622330399462537522498")) + { + ulong b = 5931690917503076532; + a.Value = b / a; + Assert.AreEqual("234052834524092854092874502983745029345723092857791404165816936/115756986668303657898962467957", a.ToString()); + } + } + + [TestMethod] + public void RationalDivideSignedLimbBy() + { + using(var a = new HugeRational("115756986668303657898962467957/39458029384750298767200622330399462537522498")) + { + long b = -5931690917503076532; + a.Value = b / a; + Assert.AreEqual("-234052834524092854092874502983745029345723092857791404165816936/115756986668303657898962467957", a.ToString()); + } + } + #endregion #endregion diff --git a/mpir.net/mpir.net-tests/HugeRationalTests/Comparisons.cs b/mpir.net/mpir.net-tests/HugeRationalTests/Comparisons.cs index 46639da3..5d64164e 100644 --- a/mpir.net/mpir.net-tests/HugeRationalTests/Comparisons.cs +++ b/mpir.net/mpir.net-tests/HugeRationalTests/Comparisons.cs @@ -92,6 +92,21 @@ namespace MPIR.Tests.HugeRationalTests } } + [TestMethod] + public void RationalCompareToLimb2() + { + using(var a = new HugeRational("-222509947/127")) + { + ulong b = 222509820; + ulong d = 127; + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(b, d))); + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(b + 1, d))); + Assert.AreEqual(0, System.Math.Sign((-(a + 1)).CompareTo(b, d))); + Assert.AreEqual(0, System.Math.Sign((-a).CompareTo(b + d, d))); + Assert.AreEqual(1, System.Math.Sign((-a).CompareTo(b, d))); + } + } + [TestMethod] public void RationalCompareToSignedLimb() { @@ -106,6 +121,22 @@ namespace MPIR.Tests.HugeRationalTests } } + [TestMethod] + public void RationalCompareToSignedLimb2() + { + using(var a = new HugeRational("-222509947/127")) + { + long b = -222509820; + long d = 127; + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(b, (ulong)d))); + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(b + 1, (ulong)d))); + Assert.AreEqual(0, System.Math.Sign((a + 1).CompareTo(b, (ulong)d))); + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(b - d + 1, (ulong)d))); + Assert.AreEqual(0, System.Math.Sign(a.CompareTo(b - d, (ulong)d))); + Assert.AreEqual(1, System.Math.Sign(a.CompareTo(b - d - 1, (ulong)d))); + } + } + [TestMethod] public void RationalCompareToSignedDouble() { @@ -453,6 +484,32 @@ namespace MPIR.Tests.HugeRationalTests } } + [TestMethod] + public void RationalEqualsLimb2() + { + using(var a = new HugeRational("222509832377/127")) + { + ulong b = 222509832504; + ulong d = 127; + Assert.IsFalse(a.Equals(b + 1, d)); + Assert.IsTrue(a.Equals(b - d, d)); + Assert.IsTrue((a + 1).Equals(b, d)); + } + } + + [TestMethod] + public void RationalEqualsSignedLimb2() + { + using(var a = new HugeRational("-222509832377/127")) + { + long b = -222509832504; + ulong d = 127; + Assert.IsFalse(a.Equals(b + 1, d)); + Assert.IsTrue(a.Equals(b + (long)d, d)); + Assert.IsTrue((a - 1).Equals(b, d)); + } + } + [TestMethod] public void RationalEqualsDouble() { diff --git a/mpir.net/mpir.net-tests/HugeRationalTests/ConstructionAndDisposal.cs b/mpir.net/mpir.net-tests/HugeRationalTests/ConstructionAndDisposal.cs index 7ac111df..da55ceb7 100644 --- a/mpir.net/mpir.net-tests/HugeRationalTests/ConstructionAndDisposal.cs +++ b/mpir.net/mpir.net-tests/HugeRationalTests/ConstructionAndDisposal.cs @@ -178,6 +178,17 @@ namespace MPIR.Tests.HugeRationalTests } } + [TestMethod] + public void RationalStringConstructorNumeratorOnly() + { + var n = "5432109876543212345789023245987"; + using(var a = new HugeRational(n)) + { + Assert.AreEqual(2, a.NumeratorNumberOfLimbsUsed()); + Assert.AreEqual(n + "/1", a.ToString()); + } + } + [TestMethod] [ExpectedException(typeof(ArgumentException))] public void RationalStringConstructorInvalid() @@ -198,8 +209,10 @@ namespace MPIR.Tests.HugeRationalTests using (var i = new HugeInt("362736035870515331128527330659")) { var d = i.ToString(16); - using (var a = new HugeRational("143210ABCDEF32123457ACDB324598799/" + d, 16)) + var n = "143210ABCDEF32123457ACDB324598799"; + using (var a = new HugeRational(n + "/" + d, 16)) { + Assert.AreEqual(n, a.Numerator.ToString(16)); Assert.AreEqual(3, a.NumeratorNumberOfLimbsUsed()); Assert.AreEqual(i, a.Denominator); } diff --git a/mpir.net/mpir.net-tests/HugeRationalTests/Conversions.cs b/mpir.net/mpir.net-tests/HugeRationalTests/Conversions.cs index e0b1f2d9..02aadec3 100644 --- a/mpir.net/mpir.net-tests/HugeRationalTests/Conversions.cs +++ b/mpir.net/mpir.net-tests/HugeRationalTests/Conversions.cs @@ -60,6 +60,9 @@ namespace MPIR.Tests.HugeRationalTests ulong d = 12764787846358441471; a.SetTo(b, d); Assert.AreEqual(b.ToString() + "/" + d.ToString(), a.ToString()); + + a.SetTo(b); + Assert.AreEqual(b.ToString() + "/1", a.ToString()); } } @@ -72,6 +75,9 @@ namespace MPIR.Tests.HugeRationalTests ulong d = 12764787846358441471; a.SetTo(b, d); Assert.AreEqual(b.ToString() + "/" + d.ToString(), a.ToString()); + + a.SetTo(b); + Assert.AreEqual(b.ToString() + "/1", a.ToString()); } } @@ -114,6 +120,10 @@ namespace MPIR.Tests.HugeRationalTests n = "-98ABCDEF876529834765234123984761/17607EF654EB9A13FFA163C75"; a.SetTo(n, 16); Assert.AreEqual(n, a.ToString(16)); + + n = "-98ABCDEF876529834765234123984761"; + a.SetTo(n, 16); + Assert.AreEqual(n + "/1", a.ToString(16)); } } diff --git a/mpir.net/mpir.net/HugeRational.h b/mpir.net/mpir.net/HugeRational.h index caa75d2c..01c51e61 100644 --- a/mpir.net/mpir.net/HugeRational.h +++ b/mpir.net/mpir.net/HugeRational.h @@ -1,1414 +1,1295 @@ -/* -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 -#endif -#define SPECIALIZE_EXPRESSIONS -#define Mpt Rat -#define CUSTOM_MP(x) custom_mpq_##x -#define MPSTRUCT __mpq_struct -#define MP(x) mpq_##x -#define MPTYPE HugeRational -#define MPTYPE_NAME Rational -#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression -#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression -#define CTXT(x) context.RationalArgs[x] -#define CTXTI(x) context.IntArgs[x] -#define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) -#include "ExpressionMacros.h" - -namespace MPIR -{ - ref class MpirRandom; - ref class MPTYPE; - 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 RationalExpression - - /// - /// Base class for all rational expressions resulting from many rational 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(RationalInitialized); - auto ptr = &context.Temp[context.Index].MPTYPE_NAME; - CTXT(context.Index++) = ptr; - MP(init)(ptr); - 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); - - /// 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, IntegerExpression^ 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 + (IntegerExpression^ 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); - - /// 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, IntegerExpression^ 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 - (IntegerExpression^ 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); - - /// 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, IntegerExpression^ 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 * (IntegerExpression^ 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); - - /// 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, IntegerExpression^ 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 / (IntegerExpression^ 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); - - /// 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(); - - /// Inverts the number (1/source). - /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. - /// If the new denominator is zero, a division by zero is thrown. - /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation - MPEXPR_NAME^ Invert(); - - #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. - /// - /// 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. - /// - /// 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 the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Numerator of the number to compare the source with - /// Denominator of the number to compare the source with - /// A positive number if the source is greater than / , negative if less, and zero if they are equal. - int CompareTo(mpir_si numerator, mpir_ui denominator); - - /// Compares two numbers. - /// If the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Numerator of the number to compare the source with - /// Denominator of the number to compare the source with - /// A positive number if the source is greater than / , negative if less, and zero if they are equal. - int CompareTo(mpir_ui numerator, mpir_ui denominator); - - /// 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. - /// - /// 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. - /// If the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Numerator of the number to compare the source with - /// Denominator of the number to compare the source with - /// true if the values of the source and / are equal, false otherwise. - bool Equals(mpir_si numerator, mpir_ui denominator); - - /// Compares two numbers. - /// If the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. - /// - /// Numerator of the number to compare the source with - /// Denominator of the number to compare the source with - /// true if the values of the source and / are equal, false otherwise. - bool Equals(mpir_ui numerator, mpir_ui denominator); - - /// 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 rational 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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->Equals(b); } - - /// 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 endregion - - #pragma region concrete expressions - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Add, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Rat, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Rat, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Rat, IExpr) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Rat, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Rat, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Rat, IExpr) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, IExpr, Rat) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Multiply, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Rat, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Rat, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Rat, IExpr) - - DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Divide, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Rat, Ui) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Ui, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Rat, Si) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Si, Rat) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Rat, IExpr) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, IExpr, Rat) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Rat, Bits) - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftRight, Rat, Bits) - - DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Rat, Ui) - - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Rat) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Rat) - DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Invert, Rat) - - #pragma endregion - - #pragma region HugeRational class - - /// - /// Multi-precision Rational 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); - String^ ToString(int base, bool lowercase, int maxDigits); - - internal: - 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 rational instance and sets its value to 0/1 - /// - MPTYPE(); - - /// - /// Initializes a new rational instance, allocating enough memory to hold at least + bits, and sets its value to 0/1. - /// This is only the initial space, rational 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 for the numerator - /// Minimum number of bits the initially allocated memory should hold for the denominator - /// the newly constructed instance - static MPTYPE^ Allocate(mp_bitcnt_t numeratorBits, mp_bitcnt_t denominatorBits); - - /// - /// Initializes a new rational 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 rational 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 rational 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 rational 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); - - /// - /// Constructs and returns a new rational instance with its value set to / . - /// If the fraction is not in canonical form, Canonicalize() must be called. - /// - /// Numerator for the initial value for the new rational instance - /// Denominator for the initial value for the new rational instance - MPTYPE(IntegerExpression^ numerator, IntegerExpression^ denominator); - - /// - /// Constructs and returns a new rational instance with its value set to / . - /// If the fraction is not in canonical form, Canonicalize() must be called. - /// - /// Numerator for the initial value for the new rational instance - /// Denominator for the initial value for the new rational instance - MPTYPE(mpir_si numerator, mpir_ui denominator); - - /// - /// Constructs and returns a new rational instance with its value set to / . - /// If the fraction is not in canonical form, Canonicalize() must be called. - /// - /// Numerator for the initial value for the new rational instance - /// Denominator for the initial value for the new rational instance - MPTYPE(mpir_ui numerator, mpir_ui denominator); - - /// - /// Constructs and returns a new rational instance with its value set to the parameter. - /// There is no rounding, this conversion is exact. - /// - /// Initial value for the new rational instance. This is an exact conversion. - MPTYPE(double value); - - /// - /// Removes any factors that are common to the numerator and denominator, and makes the denominator positive. - /// Because this operation is expensive for large numbers, it must be called manually only when needed. - /// Constructors do not automatically canonicalize the new instance. - /// Changing the numerator or denominator directly may, obviously, violate canonical form. - /// Normal rational operations assume canonical form of all operands and guarantee it for the result. - /// - void Canonicalize() { MP(canonicalize)(_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); } - - /// - /// 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); } - -///// -///// 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. -///// -///// 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. -///// -///// The value as a ulong, possibly truncated to the least significant bits only. -//mpir_si ToLong() { return MP(get_si)(_value); } - - /// - /// 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) -//{ -// mpir_si x; -// auto result = MP(get_d_2exp)(&x, _value); -// exp = x; -// return result; -//} - - /// - /// Gets the numerator of this rational. - /// The numerator can be used as a regular integer for any read or write operations. It does not need to be disposed of. - /// If setting the Value of the numerator is not known to maintain canonical form for the rational, Canonicalize() must be called. - /// Do not set the Value of the numerator while the rational object is contained in a hash table, because that changes its hash code. - /// - property HugeInt^ Numerator - { - HugeInt^ get() { return gcnew HugeIntComponent(&_value->_mp_num); } - }; - - /// - /// Gets the denominator of this rational. - /// The denominator can be used as a regular integer for any read or write operations. It does not need to be disposed of. - /// If setting the Value of the denominator is not known to maintain canonical form for the rational, Canonicalize() must be called. - /// Do not set the Value of the denominator while the rational object is contained in a hash table, because that changes its hash code. - /// - property HugeInt^ Denominator - { - HugeInt^ get() { return gcnew HugeIntComponent(&_value->_mp_den); } - }; - - #pragma endregion - - #pragma region assignment - - /// - /// When getting, returns this rational. - /// When setting, sets the value of the rational 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 rationals should be. - /// - property MPEXPR_NAME^ Value - { - void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); } - MPEXPR_NAME^ get() { return this; } - } - - /// - /// Sets the value of the rational 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. - /// - /// numerator for the new value for the object - /// denominator for the new value for the object - void SetTo(mpir_ui numerator, mpir_ui denominator) { MP(set_ui)(_value, numerator, denominator); } - - /// - /// Sets the value of the rational object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// rational value for the new value for the object - void SetTo(mpir_ui value) { SetTo(value, 1); } - - /// - /// Sets the value of the rational 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. - /// - /// numerator for the new value for the object - /// denominator for the new value for the object - void SetTo(mpir_si numerator, mpir_ui denominator) { MP(set_si)(_value, numerator, denominator); } - - /// - /// Sets the value of the rational object. - /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. - /// - /// rational value for the new value for the object - void SetTo(mpir_si value) { SetTo(value, 1); } - - /// - /// Sets the value of the rational 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 rational 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. - /// May be an rational or a pair of rationals 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 rational 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, 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 raitonal 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) - { - value->AssignTo(&_value->_mp_num); - mpz_set_ui(&_value->_mp_den, 1); - } - - /// - /// Sets the value of the raitonal 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. - /// - /// Numerator for the new value for the object - /// Denominator for the new value for the object - void SetTo(IntegerExpression^ numerator, IntegerExpression^ denominator) - { - //use context in case source expressions reference the previous numerator or denominator of the rational - EvaluationContext context; - numerator->AssignToInteger(context); - denominator->AssignToInteger(context); - mpz_set(&_value->_mp_num, CTXTI(0)); - mpz_set(&_value->_mp_den, CTXTI(1)); - } - - /// - /// Swaps the values of two rationals. - /// 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(ptr) temp = a->_value; - a->_value = _value; - _value = temp; - } - - #pragma endregion - - #pragma region Size checks - - /// - /// 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 at most 2 characters too big. - /// If is a power of 2, the result will always be exact. - /// If the number is 0, the result is always 3. - /// 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. - /// A slash between numerator and denominator is accounted for. - /// 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 or 2 too big, not counting a leading minus. - mp_size_t ApproximateSizeInBase(int base) { return mpz_sizeinbase(&_value->_mp_num, base) + mpz_sizeinbase(&_value->_mp_den, base) + 1; } - - #pragma endregion - - #pragma region IO - - /// - /// Outputs the rational to the in raw binary format. - /// The number's numerator and denominator are written in sequence, each 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 rational value from the in raw binary format, as it would have been written by Write(Stream). - /// The number's numerator and denominator are read in sequence, each 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 rational 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 rational 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 rational 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(arrayCount); - -// PIN(data); -// MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); -// return data; -// } - -//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 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 +#endif +#define SPECIALIZE_EXPRESSIONS +#define Mpt Rat +#define CUSTOM_MP(x) custom_mpq_##x +#define MPSTRUCT __mpq_struct +#define MP(x) mpq_##x +#define MPTYPE HugeRational +#define MPTYPE_NAME Rational +#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression +#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression +#define CTXT(x) context.RationalArgs[x] +#define CTXTI(x) context.IntArgs[x] +#define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) +#include "ExpressionMacros.h" + +namespace MPIR +{ + ref class MpirRandom; + ref class MPTYPE; + 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 RationalExpression + + /// + /// Base class for all rational expressions resulting from many rational 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(RationalInitialized); + auto ptr = &context.Temp[context.Index].MPTYPE_NAME; + CTXT(context.Index++) = ptr; + MP(init)(ptr); + 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); + + /// 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, IntegerExpression^ 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 + (IntegerExpression^ 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); + + /// 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, IntegerExpression^ 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 - (IntegerExpression^ 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); + + /// 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, IntegerExpression^ 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 * (IntegerExpression^ 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); + + /// 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, IntegerExpression^ 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 / (IntegerExpression^ 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); + + /// 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(); + + /// Inverts the number (1/source). + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// If the new denominator is zero, a division by zero is thrown. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation + MPEXPR_NAME^ Invert(); + + #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. + /// + /// 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. + /// + /// 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 the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Numerator of the number to compare the source with + /// Denominator of the number to compare the source with + /// A positive number if the source is greater than / , negative if less, and zero if they are equal. + int CompareTo(mpir_si numerator, mpir_ui denominator); + + /// Compares two numbers. + /// If the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Numerator of the number to compare the source with + /// Denominator of the number to compare the source with + /// A positive number if the source is greater than / , negative if less, and zero if they are equal. + int CompareTo(mpir_ui numerator, mpir_ui denominator); + + /// 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. + /// + /// 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. + /// If the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Numerator of the number to compare the source with + /// Denominator of the number to compare the source with + /// true if the values of the source and / are equal, false otherwise. + bool Equals(mpir_si numerator, mpir_ui denominator); + + /// Compares two numbers. + /// If the source number is an expression, it is evaluated into a temporary variable before the comparison is performed. + /// + /// Numerator of the number to compare the source with + /// Denominator of the number to compare the source with + /// true if the values of the source and / are equal, false otherwise. + bool Equals(mpir_ui numerator, mpir_ui denominator); + + /// 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 rational 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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->Equals(b); } + + /// 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 endregion + + #pragma region concrete expressions + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Add, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Rat, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Rat, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Rat, IExpr) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Rat, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Rat, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Rat, IExpr) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, IExpr, Rat) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Multiply, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Rat, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Rat, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Rat, IExpr) + + DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Divide, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Rat, Ui) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Ui, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Rat, Si) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Si, Rat) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Rat, IExpr) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, IExpr, Rat) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Rat, Bits) + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftRight, Rat, Bits) + + DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Rat, Ui) + + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Rat) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Rat) + DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Invert, Rat) + + #pragma endregion + + #pragma region HugeRational class + + /// + /// Multi-precision Rational 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); + String^ ToString(int base, bool lowercase, int maxDigits); + + internal: + 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 rational instance and sets its value to 0/1 + /// + MPTYPE(); + + /// + /// Initializes a new rational instance, allocating enough memory to hold at least + bits, and sets its value to 0/1. + /// This is only the initial space, rational 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 for the numerator + /// Minimum number of bits the initially allocated memory should hold for the denominator + /// the newly constructed instance + static MPTYPE^ Allocate(mp_bitcnt_t numeratorBits, mp_bitcnt_t denominatorBits); + + /// + /// Initializes a new rational 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 rational 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 rational 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 rational 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); + + /// + /// Constructs and returns a new rational instance with its value set to / . + /// If the fraction is not in canonical form, Canonicalize() must be called. + /// + /// Numerator for the initial value for the new rational instance + /// Denominator for the initial value for the new rational instance + MPTYPE(IntegerExpression^ numerator, IntegerExpression^ denominator); + + /// + /// Constructs and returns a new rational instance with its value set to / . + /// If the fraction is not in canonical form, Canonicalize() must be called. + /// + /// Numerator for the initial value for the new rational instance + /// Denominator for the initial value for the new rational instance + MPTYPE(mpir_si numerator, mpir_ui denominator); + + /// + /// Constructs and returns a new rational instance with its value set to / . + /// If the fraction is not in canonical form, Canonicalize() must be called. + /// + /// Numerator for the initial value for the new rational instance + /// Denominator for the initial value for the new rational instance + MPTYPE(mpir_ui numerator, mpir_ui denominator); + + /// + /// Constructs and returns a new rational instance with its value set to the parameter. + /// There is no rounding, this conversion is exact. + /// + /// Initial value for the new rational instance. This is an exact conversion. + MPTYPE(double value); + + /// + /// Removes any factors that are common to the numerator and denominator, and makes the denominator positive. + /// Because this operation is expensive for large numbers, it must be called manually only when needed. + /// Constructors do not automatically canonicalize the new instance. + /// Changing the numerator or denominator directly may, obviously, violate canonical form. + /// Normal rational operations assume canonical form of all operands and guarantee it for the result. + /// + void Canonicalize() { MP(canonicalize)(_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); } + + /// + /// 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); } + + /// + /// 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); } + + /// + /// Gets the numerator of this rational. + /// The numerator can be used as a regular integer for any read or write operations. It does not need to be disposed of. + /// If setting the Value of the numerator is not known to maintain canonical form for the rational, Canonicalize() must be called. + /// Do not set the Value of the numerator while the rational object is contained in a hash table, because that changes its hash code. + /// + property HugeInt^ Numerator + { + HugeInt^ get() { return gcnew HugeIntComponent(&_value->_mp_num); } + }; + + /// + /// Gets the denominator of this rational. + /// The denominator can be used as a regular integer for any read or write operations. It does not need to be disposed of. + /// If setting the Value of the denominator is not known to maintain canonical form for the rational, Canonicalize() must be called. + /// Do not set the Value of the denominator while the rational object is contained in a hash table, because that changes its hash code. + /// + property HugeInt^ Denominator + { + HugeInt^ get() { return gcnew HugeIntComponent(&_value->_mp_den); } + }; + + #pragma endregion + + #pragma region assignment + + /// + /// When getting, returns this rational. + /// When setting, sets the value of the rational 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 rationals should be. + /// + property MPEXPR_NAME^ Value + { + void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); } + MPEXPR_NAME^ get() { return this; } + } + + /// + /// Sets the value of the rational 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. + /// + /// numerator for the new value for the object + /// denominator for the new value for the object + void SetTo(mpir_ui numerator, mpir_ui denominator) { MP(set_ui)(_value, numerator, denominator); } + + /// + /// Sets the value of the rational object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// rational value for the new value for the object + void SetTo(mpir_ui value) { SetTo(value, 1); } + + /// + /// Sets the value of the rational 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. + /// + /// numerator for the new value for the object + /// denominator for the new value for the object + void SetTo(mpir_si numerator, mpir_ui denominator) { MP(set_si)(_value, numerator, denominator); } + + /// + /// Sets the value of the rational object. + /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code. + /// + /// rational value for the new value for the object + void SetTo(mpir_si value) { SetTo(value, 1); } + + /// + /// Sets the value of the rational 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 rational 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. + /// May be an rational or a pair of rationals 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 rational 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, 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 raitonal 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) + { + value->AssignTo(&_value->_mp_num); + mpz_set_ui(&_value->_mp_den, 1); + } + + /// + /// Sets the value of the raitonal 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. + /// + /// Numerator for the new value for the object + /// Denominator for the new value for the object + void SetTo(IntegerExpression^ numerator, IntegerExpression^ denominator) + { + //use context in case source expressions reference the previous numerator or denominator of the rational + EvaluationContext context; + numerator->AssignToInteger(context); + denominator->AssignToInteger(context); + mpz_set(&_value->_mp_num, CTXTI(0)); + mpz_set(&_value->_mp_den, CTXTI(1)); + } + + /// + /// Swaps the values of two rationals. + /// 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(ptr) temp = a->_value; + a->_value = _value; + _value = temp; + } + + #pragma endregion + + #pragma region Size checks + + /// + /// 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 at most 2 characters too big. + /// If is a power of 2, the result will always be exact. + /// If the number is 0, the result is always 3. + /// 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. + /// A slash between numerator and denominator is accounted for. + /// 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 or 2 too big, not counting a leading minus. + mp_size_t ApproximateSizeInBase(int base) { return mpz_sizeinbase(&_value->_mp_num, base) + mpz_sizeinbase(&_value->_mp_den, base) + 1; } + + #pragma endregion + + #pragma region IO + + /// + /// Outputs the rational to the in raw binary format. + /// The number's numerator and denominator are written in sequence, each 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 rational value from the in raw binary format, as it would have been written by Write(Stream). + /// The number's numerator and denominator are read in sequence, each 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 rational 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 rational 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 rational 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); + + #pragma endregion + }; + + #pragma endregion +};