From 36cdf4ad965e363bd2f938bebeb046e04dc017d5 Mon Sep 17 00:00:00 2001 From: Alex Dyachenko Date: Mon, 24 Jun 2019 17:48:13 -0400 Subject: [PATCH] MPIR.Net CompareTo updated to use mpf_cmp_z for mixed float/int comparisons --- doc/mpir.texi | 11 +++++++---- .../HugeFloatTests/Comparisons.cs | 18 ++++++++++++++++++ .../mpir.net-tests/HugeIntTests/Comparisons.cs | 18 ++++++++++++++++++ mpir.net/mpir.net/HugeFloat.cpp | 7 +++++++ mpir.net/mpir.net/HugeRational.cpp | 10 ++++++++++ mpir.net/mpir.net/HugeRational.h | 1 + 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/doc/mpir.texi b/doc/mpir.texi index 6535cd50..bbc8f5a6 100644 --- a/doc/mpir.texi +++ b/doc/mpir.texi @@ -7390,8 +7390,9 @@ Operator @code{^} serves dual purposes: when the right operand is a single limb, if the right operand is an @code{IntegerExpression} it performs a bitwise XOR. Comparison operators (@code{==}, @code{!=}, @code{<}, @code{<=}, @code{>}, @code{>=}) accept @code{IntegerExpression}, -single-limb, or double arguments, but do not accept @code{RationalExpression} because that would require an awkward explicit cast +single-limb, or double arguments, but do not accept @code{RationalExpression} or @code{FloatExpression} because that would require an awkward explicit cast when comparing with null. +Use the @code{CompareTo(object)} method for cross-comparisons, which does accept both @code{RationalExpression} and @code{FloatExpression}. @deftypefn Method int CompareTo (IntegerExpression @var{a}) @deftypefnx Method bool Equals (IntegerExpression @var{a}) @@ -7725,8 +7726,9 @@ and the bitwise operators (@code{&}, @code{|}, @code{^}, @code{~}). Operator @code{^} raises the source number to the specified power. Comparison operators (@code{==}, @code{!=}, @code{<}, @code{<=}, @code{>}, @code{>=}) accept @code{RationalExpression}, -single-limb, or double arguments, but do not accept integer or float expressions because that would require an awkward explicit cast -when comparing with null. Use the @code{CompareTo(object)} method for cross-comparisons. +single-limb, or double arguments, but do not accept @code{IntegerExpression} or @code{FloatExpression} because that would require an awkward explicit cast +when comparing with null. +Use the @code{CompareTo(object)} method for cross-comparisons with integers. Direct comparisons between rationals and floats are not available in MPIR. @deftypefn Method int CompareTo (RationalExpression @var{a}) @deftypefnx Method bool Equals (RationalExpression @var{a}) @@ -7940,8 +7942,9 @@ The modulo operator (@code{%}) and the bitwise operators (@code{&}, @code{|}, @c Operator @code{^} raises the source number to the specified power. Comparison operators (@code{==}, @code{!=}, @code{<}, @code{<=}, @code{>}, @code{>=}) accept @code{FloatExpression}, -single-limb, or double arguments, but do not accept integer or rational expressions +single-limb, or double arguments, but do not accept @code{RationalExpression} or @code{IntegerExpression} because that would require an awkward explicit cast when comparing with null. +Use the @code{CompareTo(object)} method for cross-comparisons with integers. Direct comparisons between rationals and floats are not available in MPIR. @deftypefn Method int CompareTo (FloatExpression @var{a}) @deftypefnx Method bool Equals (FloatExpression @var{a}) diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/Comparisons.cs b/mpir.net/mpir.net-tests/HugeFloatTests/Comparisons.cs index bdcdb3f8..d9a2d332 100644 --- a/mpir.net/mpir.net-tests/HugeFloatTests/Comparisons.cs +++ b/mpir.net/mpir.net-tests/HugeFloatTests/Comparisons.cs @@ -66,6 +66,24 @@ namespace MPIR.Tests.HugeFloatTests } } + [TestMethod] + public void FloatCompareToHugeIntExpression() + { + using (var a = new HugeFloat("-222509832503450298345039835740293845721345345354")) + using (var b = new HugeInt("222509832503450298345039835740293845721345345353")) + { + Assert.AreEqual(-1, Math.Sign(a.CompareTo(b))); + Assert.AreEqual(-1, Math.Sign(a.CompareTo(-b))); + Assert.AreEqual(0, Math.Sign(a.CompareTo(-b - 1))); + Assert.AreEqual(1, Math.Sign(a.CompareTo(-b - 2))); + + Assert.AreEqual(-1, Math.Sign((a + 1).CompareTo(b))); + Assert.AreEqual(0, Math.Sign((a + 1).CompareTo(-b))); + Assert.AreEqual(-1, Math.Sign((a + 1).CompareTo(1 - b))); + Assert.AreEqual(1, Math.Sign((a + 1).CompareTo(-b - 1))); + } + } + [TestMethod] [ExpectedException(typeof(ArgumentException))] public void FloatCompareToNonExpression() diff --git a/mpir.net/mpir.net-tests/HugeIntTests/Comparisons.cs b/mpir.net/mpir.net-tests/HugeIntTests/Comparisons.cs index d044de31..4340db25 100644 --- a/mpir.net/mpir.net-tests/HugeIntTests/Comparisons.cs +++ b/mpir.net/mpir.net-tests/HugeIntTests/Comparisons.cs @@ -66,6 +66,24 @@ namespace MPIR.Tests.HugeIntTests } } + [TestMethod] + public void IntCompareToHugeFloatExpression() + { + using (var a = new HugeInt("-222509832503450298345039835740293845721345345354")) + using (var b = new HugeFloat("222509832503450298345039835740293845721345345353")) + { + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(b))); + Assert.AreEqual(-1, System.Math.Sign(a.CompareTo(-b))); + Assert.AreEqual(0, System.Math.Sign(a.CompareTo(-b - 1))); + Assert.AreEqual(1, System.Math.Sign(a.CompareTo(-b - 2))); + + Assert.AreEqual(-1, System.Math.Sign((a + 1).CompareTo(b))); + Assert.AreEqual(0, System.Math.Sign((a + 1).CompareTo(-b))); + Assert.AreEqual(-1, System.Math.Sign((a + 1).CompareTo(1 - b))); + Assert.AreEqual(1, System.Math.Sign((a + 1).CompareTo(-b - 1))); + } + } + [TestMethod] [ExpectedException(typeof(ArgumentException))] public void IntCompareToNonExpression() diff --git a/mpir.net/mpir.net/HugeFloat.cpp b/mpir.net/mpir.net/HugeFloat.cpp index 505bad17..cac90944 100644 --- a/mpir.net/mpir.net/HugeFloat.cpp +++ b/mpir.net/mpir.net/HugeFloat.cpp @@ -210,6 +210,13 @@ namespace MPIR auto f = dynamic_cast(this); auto precision = IS_NULL(f) ? MPTYPE::DefaultPrecision : f->Precision; + WHEN_IS(2, a, IntegerExpression) + { + IN_SPECIFIC_CONTEXT(precision, this); + x2->AssignToInteger(context); + return MP(cmp_z)(CTXT(0), CTXTI(1)); + } + if(a->GetType() == mpir_ui::typeid) { IN_SPECIFIC_CONTEXT(precision, this); diff --git a/mpir.net/mpir.net/HugeRational.cpp b/mpir.net/mpir.net/HugeRational.cpp index 95bd91bd..73c03c9b 100644 --- a/mpir.net/mpir.net/HugeRational.cpp +++ b/mpir.net/mpir.net/HugeRational.cpp @@ -468,6 +468,16 @@ namespace MPIR return -MP(cmp_z)(CTXT(0), CTXTI(1)); } + WHEN_IS(3, a, FloatExpression) + { + auto const f = dynamic_cast(a); + context.FloatPrecision = IS_NULL(f) ? HugeFloat::DefaultPrecision : f->Precision; + + x3->AssignToFloat(context); + AssignToInteger(context); + return -mpf_cmp_z(CTXTF(0), CTXTI(1)); + } + if (a->GetType() == mpir_ui::typeid) { AssignToInteger(context); diff --git a/mpir.net/mpir.net/HugeRational.h b/mpir.net/mpir.net/HugeRational.h index cd403690..e093b1cd 100644 --- a/mpir.net/mpir.net/HugeRational.h +++ b/mpir.net/mpir.net/HugeRational.h @@ -49,6 +49,7 @@ using namespace System::Runtime::InteropServices; #define MPEXPR(x) LIT(MPTYPE_NAME)##x##Expression #define CTXT(x) context.RationalArgs[x] #define CTXTI(x) context.IntArgs[x] +#define CTXTF(x) context.FloatArgs[x] #define ASSIGN_TO CONCAT(AssignTo, LIT(MPTYPE_NAME)) #define SET_CONTEXT_PRECISION #include "ExpressionMacros.h"