diff --git a/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj b/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj
index 5f6e11ae..65a8c1c6 100644
--- a/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj
+++ b/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj
@@ -164,7 +164,9 @@
mpir.net
-
+
+
+
diff --git a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj
index aa1c43f7..4fb6a606 100644
--- a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj
+++ b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj
@@ -142,6 +142,7 @@
+
@@ -150,6 +151,7 @@
+
diff --git a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters
index a3d009fc..a423f954 100644
--- a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters
+++ b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters
@@ -33,6 +33,9 @@
Header Files
+
+ Header Files
+
@@ -50,6 +53,9 @@
Source Files
+
+ Source Files
+
diff --git a/mpir.net/mpir.net/HugeFloat.cpp b/mpir.net/mpir.net/HugeFloat.cpp
new file mode 100644
index 00000000..2382e45a
--- /dev/null
+++ b/mpir.net/mpir.net/HugeFloat.cpp
@@ -0,0 +1,343 @@
+/*
+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/.
+*/
+
+#include "Stdafx.h"
+#include "HugeInt.h"
+#include "HugeFloat.h"
+//#include "Random.h"
+
+using namespace System::Runtime::InteropServices;
+using namespace System::Text;
+
+namespace MPIR
+{
+ #pragma region construction
+
+ MPTYPE::MPTYPE()
+ {
+ AllocateStruct();
+ MP(init)(_value);
+ }
+
+ MPTYPE::MPTYPE(bool initialize)
+ {
+ AllocateStruct();
+ if(initialize)
+ MP(init)(_value);
+ }
+
+ MPTYPE::MPTYPE(MPEXPR_NAME^ value)
+ {
+ AllocateStruct();
+ MP(init)(_value);
+ value->AssignTo(_value);
+ }
+
+ MPTYPE::MPTYPE(IntegerExpression^ value)
+ {
+ AllocateStruct();
+ MP(init)(_value);
+ SetTo(value);
+ }
+
+ MPTYPE^ MPTYPE::Allocate(mp_bitcnt_t precision)
+ {
+ auto result = gcnew MPTYPE(false);
+ MP(init2)(result->_value, precision);
+ return result;
+ }
+
+ void MPTYPE::FromString(String^ value, int base)
+ {
+ AllocateStruct();
+ MP(init)(_value);
+
+ IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
+ bool success = 0 == MP(set_str)(_value, (char*)(void*)ptr, base);
+ Marshal::FreeHGlobal(ptr);
+
+ if(!success)
+ {
+ DeallocateStruct();
+ throw gcnew ArgumentException("Invalid number", "value");
+ }
+ }
+
+ void MPTYPE::SetTo(String^ value, int base)
+ {
+ IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
+ bool success = 0 == MP(set_str)(_value, (char*)(void*)ptr, base);
+ Marshal::FreeHGlobal(ptr);
+
+ if(!success)
+ throw gcnew ArgumentException("Invalid number", "value");
+ }
+
+ MPTYPE::MPTYPE(mpir_si value)
+ {
+ AllocateStruct();
+ MP(init_set_si)(_value, value);
+ }
+
+ MPTYPE::MPTYPE(mpir_ui value)
+ {
+ AllocateStruct();
+ MP(init_set_ui)(_value, value);
+ }
+
+ MPTYPE::MPTYPE(double value)
+ {
+ AllocateStruct();
+ MP(init_set_d)(_value, value);
+ }
+
+ #pragma endregion
+
+ #pragma region object overrides
+
+ String^ MPTYPE::ToString(int base, bool lowercase, int maxDigits)
+ {
+auto result = gcnew StringBuilder();
+//result->Append(this->Numerator->ToString(base, lowercase, maxDigits));
+//result->Append((wchar_t)'/');
+//result->Append(this->Denominator->ToString(base, lowercase, maxDigits));
+return result->ToString();
+ }
+
+ int MPEXPR_NAME::GetHashCode()
+ {
+ IN_CONTEXT(this);
+
+ mp_limb_t hash = CTXT(0)->_mp_exp;
+ mp_limb_t* ptr = CTXT(0)->_mp_d;
+ for(int i = abs(CTXT(0)->_mp_size); i > 0; i--)
+ hash ^= *ptr++;
+
+ if(CTXT(0)->_mp_size < 0)
+ hash = (mp_limb_t)-(mpir_si)hash;
+
+ return hash.GetHashCode();
+ }
+
+ #pragma endregion
+
+ #pragma region Interface implementations
+
+ int MPEXPR_NAME::CompareTo(Object^ a, bool& valid)
+ {
+ valid = true;
+
+ if (IS_NULL(a))
+ return 1;
+
+ MPEXPR_NAME^ expr = dynamic_cast(a);
+ if(!IS_NULL(expr))
+ return CompareTo(expr);
+
+ EvaluationContext context;
+
+ if(a->GetType() == mpir_ui::typeid)
+ {
+ ASSIGN_TO(context);
+ return MP(cmp_ui)(CTXT(0), (mpir_ui)a);
+ }
+
+ if(a->GetType() == mpir_si::typeid)
+ {
+ ASSIGN_TO(context);
+ return MP(cmp_si)(CTXT(0), (mpir_si)a);
+ }
+
+ if(a->GetType() == double::typeid)
+ {
+ ASSIGN_TO(context);
+ return MP(cmp_d)(CTXT(0), (double)a);
+ }
+
+ valid = false;
+ return 0;
+ }
+
+ int MPEXPR_NAME::CompareTo(Object^ a)
+ {
+ bool valid;
+ auto result = CompareTo(a, valid);
+
+ if (valid)
+ return result;
+
+ throw gcnew ArgumentException("Invalid argument type", "a");
+ }
+
+ int MPEXPR_NAME::CompareTo(MPEXPR_NAME^ a)
+ {
+ if (IS_NULL(a))
+ return 1;
+
+ IN_CONTEXT(this, a);
+ return MP(cmp)(CTXT(0), CTXT(1));
+ }
+
+ bool MPEXPR_NAME::Equals(Object^ a)
+ {
+ bool valid;
+ auto result = CompareTo(a, valid);
+
+ return valid && result == 0;
+ }
+
+ bool MPEXPR_NAME::Equals(MPEXPR_NAME^ a)
+ {
+ return CompareTo(a) == 0;
+ }
+
+ #pragma endregion
+
+ #pragma region Arithmetic
+
+ MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, +, Add, Flt, Flt)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, +, Add, Flt, Ui)
+ MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, +, Add, Flt, Ui)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, +, Add, Flt, Si)
+ MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, +, Add, Flt, Si)
+
+ MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, -, Subtract, Flt, Flt)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Flt, Ui)
+ MAKE_BINARY_OPERATOR_LLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Flt, Ui)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Flt, Si)
+ MAKE_BINARY_OPERATOR_LLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Flt, Si)
+
+ MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, *, Multiply, Flt, Flt)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, *, Multiply, Flt, Ui)
+ MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, *, Multiply, Flt, Ui)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, *, Multiply, Flt, Si)
+ MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, *, Multiply, Flt, Si)
+
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, <<, ShiftLeft, Flt, Bits)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, >>, ShiftRight, Flt, Bits)
+
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, ^, Power, Flt, Ui)
+
+ MAKE_UNARY_OPERATOR (MPEXPR_NAME, DEFINE, -, Negate, Flt)
+ MAKE_VOID_FUNCTION (MPEXPR_NAME, DEFINE, Abs, Flt)
+
+ MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, /, Divide, Flt, Flt)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, /, Divide, Flt, Ui)
+ MAKE_BINARY_OPERATOR_LLIMB (MPEXPR_NAME, DEFINE, /, Divide, Flt, Ui)
+ MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, /, Divide, Flt, Si)
+ MAKE_BINARY_OPERATOR_LLIMB (MPEXPR_NAME, DEFINE, /, Divide, Flt, Si)
+
+ DEFINE_UNARY_ASSIGNMENT_REF(Negate, Flt, MP(neg))
+ DEFINE_UNARY_ASSIGNMENT_REF(Abs, Flt, MP(abs))
+
+ DEFINE_BINARY_ASSIGNMENT_REF_REF(Add, Flt, MP(add))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Add, Flt, Ui, MP(add))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Add, Flt, Si, MP(add))
+
+ DEFINE_BINARY_ASSIGNMENT_REF_REF(Subtract, Flt, MP(sub))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Subtract, Flt, Ui, MP(sub))
+ DEFINE_BINARY_ASSIGNMENT_RATVAL_REF(Subtract, Ui, Flt, MP(sub))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Subtract, Flt, Si, MP(sub))
+ DEFINE_BINARY_ASSIGNMENT_RATVAL_REF(Subtract, Si, Flt, MP(sub))
+
+ DEFINE_BINARY_ASSIGNMENT_REF_REF(Multiply, Flt, MP(mul))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Multiply, Flt, Ui, MP(mul))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Multiply, Flt, Si, MP(mul))
+
+ DEFINE_BINARY_ASSIGNMENT_REF_REF(Divide, Flt, MP(div))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Divide, Flt, Ui, MP(div))
+ DEFINE_BINARY_ASSIGNMENT_RATVAL_REF(Divide, Ui, Flt, MP(div))
+ DEFINE_BINARY_ASSIGNMENT_REF_RATVAL(Divide, Flt, Si, MP(div))
+ DEFINE_BINARY_ASSIGNMENT_RATVAL_REF(Divide, Si, Flt, MP(div))
+
+ DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftLeft, Flt, Bits, MP(mul_2exp))
+ DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftRight, Flt, Bits, MP(div_2exp))
+
+ DEFINE_BINARY_ASSIGNMENT_REF_VAL(Power, Flt, Ui, MP(pow_ui))
+
+ #pragma endregion
+
+ #pragma region IO
+
+ #define chunkSize 1024
+
+ size_t MPTYPE::Write(Stream^ stream)
+ {
+ auto writtenNumerator = Numerator->Write(stream);
+ if(writtenNumerator == 0)
+ return 0;
+
+ auto writtenDenominator = Denominator->Write(stream);
+ if(writtenDenominator == 0)
+ return 0;
+
+ return writtenNumerator + writtenDenominator;
+ }
+
+ size_t MPTYPE::Read(Stream^ stream)
+ {
+ auto readNumerator = Numerator->Read(stream);
+ if(readNumerator == 0)
+ return 0;
+
+ auto readDenominator = Denominator->Read(stream);
+ if(readDenominator == 0)
+ return 0;
+
+ return readNumerator + readDenominator;
+ }
+
+ size_t MPTYPE::Write(TextWriter^ writer, int base, bool lowercase)
+ {
+ auto str = ToString(base, lowercase);
+ writer->Write(str);
+ return str->Length;
+ }
+
+ size_t MPTYPE::Read(TextReader^ reader, int base)
+ {
+ auto readNumerator = Numerator->Read(reader, base);
+ if(readNumerator == 0)
+ return 0;
+
+ size_t readDenominator = 0;
+ char c = reader->Peek();
+ if (c == '/')
+ {
+ reader->Read();
+ readDenominator = 1 + Denominator->Read(reader, base);
+ if(readDenominator == 1)
+ return 0;
+ }
+
+ return readNumerator + readDenominator;
+ }
+
+ #pragma endregion
+
+ #pragma region methods in other classes with rational parameters
+
+ void HugeInt::SetTo(MPEXPR_NAME^ value)
+ {
+ IN_CONTEXT(value);
+ mpz_set_f(_value, CTXT(0));
+ }
+
+ #pragma endregion
+};
\ No newline at end of file
diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h
new file mode 100644
index 00000000..e18f02bc
--- /dev/null
+++ b/mpir.net/mpir.net/HugeFloat.h
@@ -0,0 +1,1228 @@
+/*
+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 Flt
+#define CUSTOM_MP(x) custom_mpf_##x
+#define MPSTRUCT __mpf_struct
+#define MP(x) mpf_##x
+#define MPTYPE HugeFloat
+#define MPTYPE_NAME Float
+#define MPEXPR_NAME LIT(MPTYPE_NAME)Expression
+#define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression
+#define CTXT(x) context.FloatArgs[x]
+#define CTXTI(x) context.IntArgs[x]
+#define 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 FloatExpression
+
+ ///
+ /// Base class for all float expressions resulting from many float operations on MPIR types.
+ /// Expressions can be arbitrarily nested, and are lazily evaluated
+ /// when they are either assigned to the Value property of an MPIR object, or are consumed by a function or operator that returns a primitive type.
+ /// Assignment to the Value property is necessary because .Net does not support overloading the assignment operator.
+ ///
+ public ref class MPEXPR_NAME abstract : public IComparable, IComparable, IEquatable
+ {
+ internal:
+ MPEXPR_NAME() { }
+ virtual void AssignTo(MP(ptr) destination) abstract;
+ virtual void ASSIGN_TO(EvaluationContext& context)
+ {
+ context.Initialized(FloatInitialized);
+ auto ptr = &context.Temp[context.Index].MPTYPE_NAME;
+ CTXT(context.Index++) = ptr;
+ MP(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);
+
+ /// Subtracts two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to subtract from
+ /// Source value to subtract
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, MPEXPR_NAME^ b);
+
+ /// Subtracts two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to subtract from
+ /// Source value to subtract
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_ui b);
+
+ /// Subtracts two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to subtract from
+ /// Source value to subtract
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator - (mpir_ui a, MPEXPR_NAME^ b);
+
+ /// Subtracts two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to subtract from
+ /// Source value to subtract
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a, mpir_si b);
+
+ /// Subtracts two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to subtract from
+ /// Source value to subtract
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator - (mpir_si a, MPEXPR_NAME^ b);
+
+ /// Multiplies two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Source value to multiply by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, MPEXPR_NAME^ b);
+
+ /// Multiplies two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Source value to multiply by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, mpir_ui b);
+
+ /// Multiplies two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Source value to multiply by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator * (mpir_ui a, MPEXPR_NAME^ b);
+
+ /// Multiplies two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Source value to multiply by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator * (MPEXPR_NAME^ a, mpir_si b);
+
+ /// Multiplies two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Source value to multiply by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator * (mpir_si a, MPEXPR_NAME^ b);
+
+ /// Shifts the source operand to the left by , i.e. multiplies by 2^.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Number of bits to shift by, i.e. power of 2 to multiply by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator << (MPEXPR_NAME^ a, mp_bitcnt_t bits);
+
+ /// Shifts the source operand to the right by , i.e. divides by 2^.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to divide
+ /// Number of bits to shift by, i.e. power of 2 to divide by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation.
+ ///
+ static MPEXPR_NAME^ operator >> (MPEXPR_NAME^ a, mp_bitcnt_t bits);
+
+ /// Negates the source value.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to negate
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator - (MPEXPR_NAME^ a);
+
+ /// Divides two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to divide
+ /// Source value to divide by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation.
+ ///
+ static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, MPEXPR_NAME^ b);
+
+ /// Divides two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to divide
+ /// Source value to divide by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation.
+ ///
+ static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, mpir_ui b);
+
+ /// Divides two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to divide
+ /// Source value to divide by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation.
+ ///
+ static MPEXPR_NAME^ operator / (mpir_ui a, MPEXPR_NAME^ b);
+
+ /// Divides two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to divide
+ /// Source value to divide by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation.
+ ///
+ static MPEXPR_NAME^ operator / (MPEXPR_NAME^ a, mpir_si b);
+
+ /// Divides two numbers.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to divide
+ /// Source value to divide by
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation.
+ ///
+ static MPEXPR_NAME^ operator / (mpir_si a, MPEXPR_NAME^ b);
+
+ /// Raises the source value to the specified power.
+ /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
+ ///
+ /// Source value to multiply
+ /// Power to raise to
+ /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation
+ static MPEXPR_NAME^ operator ^ (MPEXPR_NAME^ a, mpir_ui power);
+
+ /// 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();
+
+ #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 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;
+
+ /// Computes the hash code of the source value.
+ /// If called on an expression, it is evaluated into a temporary variable before the comparison is performed.
+ /// Multi-precision classes are mutable with value semantics. The hash code is based on the value, and will change if the value changes.
+ /// For this reason, the value of an object must not be modified while the object is contained in a hash table.
+ /// a signed integer hash code for the value.
+ virtual int GetHashCode() override sealed;
+
+ /// Compares two numbers.
+ /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed.
+ ///
+ /// Source value to compare
+ /// Source value to compare with
+ /// A boolean result of the comparison.
+ static bool operator < (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? !IS_NULL(b) : a->CompareTo(b) < 0; }
+
+ /// Compares two numbers.
+ /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed.
+ ///
+ /// Source value to compare
+ /// Source value to compare with
+ /// A boolean result of the comparison.
+ static bool operator >= (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->CompareTo(b) >= 0; }
+
+ /// Compares two numbers.
+ /// If any argument is an expression, it is evaluated into a temporary variable before the comparison is performed.
+ ///
+ /// Source value to compare
+ /// Source value to compare with
+ /// A boolean result of the comparison.
+ static bool operator == (MPEXPR_NAME^ a, MPEXPR_NAME^ b) { return IS_NULL(a) ? IS_NULL(b) : a->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, Flt)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Flt, Ui)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Add, Flt, Si)
+
+ DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Subtract, Flt)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Flt, Ui)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Ui, Flt)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Subtract, Flt, Si)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Subtract, Si, Flt)
+
+ DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Multiply, Flt)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Flt, Ui)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Multiply, Flt, Si)
+
+ DEFINE_BINARY_EXPRESSION_WITH_TWO (MPEXPR_NAME, Divide, Flt)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Flt, Ui)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Ui, Flt)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Divide, Flt, Si)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT (MPEXPR_NAME, Divide, Si, Flt)
+
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftLeft, Flt, Bits)
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, ShiftRight, Flt, Bits)
+
+ DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT (MPEXPR_NAME, Power, Flt, Ui)
+
+ DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Negate, Flt)
+ DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Abs, Flt)
+
+ #pragma endregion
+
+ #pragma region HugeFloat class
+
+ ///
+ /// Multi-precision Float 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 float instance and sets its value to 0/1
+ ///
+ MPTYPE();
+
+ ///
+ /// Initializes a new float instance, allocating enough memory to hold at least bits, and sets its value to 0.
+ /// All float operations are performed to the precision of the destination.
+ ///
+ /// Minimum number of bits the initially allocated memory should hold for the mantissa
+ /// the newly constructed instance
+ static MPTYPE^ Allocate(mp_bitcnt_t precision);
+
+ ///
+ /// Initializes a new float instance and sets its value from the specified string, 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 float instance and sets its value from the specified string
+ ///
+ /// string representing the initial value for the new instance. Whitespace in the string is ignored.
+ /// base the string is in.
+ /// The base may vary from 2 to 62, 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 float instance and sets its value to the result of computing the source expression.
+ ///
+ /// the expression that will be computed, and the result set as the initial value of the new instance.
+ MPTYPE(MPEXPR_NAME^ value);
+
+ ///
+ /// Initializes a new float instance and sets its value to the result of computing the source expression.
+ ///
+ /// the expression that will be computed, and the result set as the initial value of the new instance.
+ MPTYPE(IntegerExpression^ value);
+
+ ///
+ /// Constructs and returns a new float instance with its value set to .
+ /// If the fraction is not in canonical form, Canonicalize() must be called.
+ ///
+ /// value for the initial value for the new float instance
+ MPTYPE(mpir_si value);
+
+ ///
+ /// Constructs and returns a new float instance with its value set to .
+ /// If the fraction is not in canonical form, Canonicalize() must be called.
+ ///
+ /// value for the initial value for the new float instance
+ MPTYPE(mpir_ui value);
+
+ ///
+ /// Constructs and returns a new float instance with its value set to the parameter.
+ /// There is no rounding, this conversion is exact.
+ ///
+ /// Initial value for the new float instance. This is an exact conversion.
+ MPTYPE(double value);
+
+ //disposal
+
+ //creating a destructor in C++ implements IDisposable.
+
+ ///
+ /// Frees all memory allocated by the instance.
+ /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory.
+ ///
+ ~MPTYPE() { this->!MPTYPE(); }
+
+ ///
+ /// Frees all memory allocated by the instance.
+ /// To minimize memory footprint, multi-precision objects should be disposed of when no longer used, instead of relying on the garbage collector to free the memory.
+ ///
+ !MPTYPE() { if(_value != 0) DeallocateStruct(); }
+
+ #pragma endregion
+
+ #pragma region conversions
+
+ ///
+ /// Converts the number to a string.
+ /// To avoid debugging performance problems, this method outputs at most the number of digits specified in MpirSettings.ToStringDigits.
+ /// If the number is larger, the least significant digits are shown with a leading ellipsis (i.e., [-]...NNNNN)
+ /// Setting MpirSettings.ToStringDigits to 0 removes the upper limit.
+ ///
+ /// A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits.
+ virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits); }
+
+ ///
+ /// 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;
+//}
+
+ #pragma endregion
+
+ #pragma region assignment
+
+ ///
+ /// When getting, returns this float.
+ /// When setting, sets the value of the float object to the value resulting from computing the supplied expression.
+ /// The getter is a no-op and never needs to be invoked directly, but makes compound operators such as +=, *=, etc. possible.
+ /// Do not set the Value of an object while it is contained in a hash table, because that changes its hash code.
+ ///
+ ///
+ /// MPIR types are implemented as reference types with value semantics.
+ /// Like Strings, the objects themselves are just lightweight pointers to data allocated elsewhere.
+ /// Unlike Strings, MPIR types are mutable.
+ /// Value semantics requires you to be able to code, a = b + c.
+ /// However, .Net (outside of C++) does not allow overloading the assignment operator,
+ /// and assigning references would necessitate some unnecessary duplication and extra memory allocations.
+ /// To solve this problem, MPIR.Net uses the property assignment.
+ /// The setter of the Value property does what an overloaded assignment operator would do in C++.
+ /// The syntax is a little different: a.Value = b + c, but it is fluent enough to become a quick habit,
+ /// and additionally reinforces the concept that an existing object can change its value while reusing internally allocated memory.
+ /// To this end, all overloaded operators and most functions that operate on MPIR types,
+ /// instead of eagerly computing a result, produce and return an expression that is basically a formula for the computation.
+ /// Expressions can then be composed using additional operators to achieve expression trees of arbitrary complexity.
+ /// All computations are deferred until an expression is assigned to the Value property of an MPIR object,
+ /// consumed by a method or operator that returns a primitive type,
+ /// or supplied as an argument to an MPIR type constructor.
+ /// The getter is a no-op defined to make possible constructs such as a.Value += 5, a.Value *= 10, etc.
+ /// Direct assignments such as a = b + c, a *= 10 will not compile because there is no implicit conversion from an expression.
+ /// Even if an implicit conversion were defined, such code would incur an extra allocation plus garbage collection,
+ /// and would not perform as well as doing the same operations on a.Value.
+ /// It would also not compile if the source were a "using" variable, as all method-local floats should be.
+ ///
+ property MPEXPR_NAME^ Value
+ {
+ void set(MPEXPR_NAME^ expr) { expr->AssignTo(_value); }
+ MPEXPR_NAME^ get() { return this; }
+ }
+
+ ///
+ /// Sets the value of the float object.
+ /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
+ /// If the fraction is not in canonical form, Canonicalize() must be called.
+ ///
+ /// value for the new value for the object
+ void SetTo(mpir_ui value) { MP(set_ui)(_value, value); }
+
+ ///
+ /// Sets the value of the float object.
+ /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
+ /// If the fraction is not in canonical form, Canonicalize() must be called.
+ ///
+ /// value for the new value for the object
+ void SetTo(mpir_si value) { MP(set_si)(_value, value); }
+
+ ///
+ /// Sets the value of the float object. This is an exact conversion, there is no rounting.
+ /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
+ ///
+ /// new value for the object
+ void SetTo(double value) { MP(set_d)(_value, value); }
+
+ ///
+ /// Sets the value of the float object.
+ /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
+ /// If the fraction is not in canonical form, Canonicalize() must be called.
+ ///
+ /// new value for the object.
+ /// May be an float or a pair of floats separated by a slash.
+ /// The string's leading characters may indicate base:
+ /// 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise
+ void SetTo(String^ value) { SetTo(value, 0); }
+
+ ///
+ /// Sets the value of the float object.
+ /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
+ /// 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)
+ {
+ EvaluationContext context;
+ value->AssignToInteger(context);
+ MP(set_z)(_value, CTXTI(0));
+ }
+
+ ///
+ /// Swaps the values of two floats.
+ /// This operation is a pointer swap and doesn't affect allocated memory.
+ /// Do not call this method while either object is contained in a hash table, because this would change their hash codes.
+ ///
+ /// Source number to swap this instance's value with
+ void Swap(MPTYPE^ a)
+ {
+ MP(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 float 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 float 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 float 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 float 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 float 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
+};
diff --git a/mpir.net/mpir.net/HugeInt.h b/mpir.net/mpir.net/HugeInt.h
index 384ecad7..bab4cb8b 100644
--- a/mpir.net/mpir.net/HugeInt.h
+++ b/mpir.net/mpir.net/HugeInt.h
@@ -55,6 +55,7 @@ namespace MPIR
{
ref class MpirRandom;
ref class RationalExpression;
+ ref class FloatExpression;
ref class MPTYPE;
ref class MPEXPR(Divide);
ref class MPEXPR(DivideUi);
@@ -1650,6 +1651,13 @@ namespace MPIR
/// new value for the object
void SetTo(RationalExpression^ value);
+ ///
+ /// Sets the value of the integer object. Any fractional portion is truncated.
+ /// Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
+ ///
+ /// new value for the object
+ void SetTo(FloatExpression^ value);
+
///
/// Swaps the values of two integers.
/// This operation is a pointer swap and doesn't affect allocated memory.