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
+};