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 65a8c1c6..87dd371e 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
@@ -94,6 +94,9 @@
+
+ HugeFloatTests\ConstructionAndDisposal.cs
+
HugeIntTests\Arithmetic.cs
@@ -164,9 +167,7 @@
mpir.net
-
-
-
+
diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs b/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs
index da55ceb7..8094258a 100644
--- a/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs
+++ b/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs
@@ -20,267 +20,160 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-namespace MPIR.Tests.HugeRationalTests
+namespace MPIR.Tests.HugeFloatTests
{
[TestClass]
public class ConstructionAndDisposal
{
[TestMethod]
- public void RationalDefaultConstructor()
+ public void FloatDefaultConstructor()
{
- using (var a = new HugeRational())
+ using (var a = new HugeFloat())
{
- Assert.AreNotEqual(0, a.NumeratorNumberOfLimbsAllocated());
- Assert.AreEqual(0, a.NumeratorNumberOfLimbsUsed());
- Assert.AreNotEqual(IntPtr.Zero, a.NumeratorLimbs());
- Assert.AreEqual("0", a.Numerator.ToString());
-
- Assert.AreNotEqual(0, a.DenominatorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsUsed());
- Assert.AreNotEqual(IntPtr.Zero, a.DenominatorLimbs());
- Assert.AreEqual("1", a.Denominator.ToString());
+ Assert.AreNotEqual(0, a.NumberOfLimbsAllocated());
+ Assert.AreEqual(0, a.NumberOfLimbsUsed());
+ Assert.AreEqual(0, a.Exponent());
+ Assert.AreNotEqual(IntPtr.Zero, a.Limbs());
+ Assert.AreEqual("0", a.ToString());
}
}
[TestMethod]
- public void RationalNumerator()
+ public void FloatDispose()
{
- using (var a = new HugeRational())
- {
- a.Numerator.Dispose();
- Assert.AreNotEqual(0, a.Numerator.NumberOfLimbsAllocated());
- Assert.AreEqual("0", a.Numerator.ToString());
- }
- }
-
- [TestMethod]
- public void RationalDenominator()
- {
- using (var a = new HugeRational())
- {
- a.Denominator.Dispose();
- Assert.AreNotEqual(0, a.Denominator.NumberOfLimbsAllocated());
- Assert.AreEqual("1", a.Denominator.ToString());
- }
- }
-
- [TestMethod]
- public void RationalDispose()
- {
- var a = new HugeRational();
+ var a = new HugeFloat();
a.Dispose();
-
- Assert.AreEqual(0, a.NumeratorNumberOfLimbsAllocated());
- Assert.AreEqual(0, a.NumeratorNumberOfLimbsUsed());
- Assert.AreEqual(IntPtr.Zero, a.NumeratorLimbs());
- Assert.AreEqual(0, a.DenominatorNumberOfLimbsAllocated());
- Assert.AreEqual(0, a.DenominatorNumberOfLimbsUsed());
- Assert.AreEqual(IntPtr.Zero, a.DenominatorLimbs());
+ Assert.AreEqual(0, a.NumberOfLimbsAllocated());
+ Assert.AreEqual(0, a.NumberOfLimbsUsed());
+ Assert.AreEqual(IntPtr.Zero, a.Limbs());
}
[TestMethod]
- public void RationalConstructorFromLong()
+ public void FloatConstructorFromLong()
{
var n = "123456789123456";
- var d = "12764787846358441471";
- using (var a = new HugeRational(long.Parse(n), ulong.Parse(d)))
+ using (var a = new HugeFloat(long.Parse(n)))
{
- Assert.AreEqual(1, a.NumeratorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.NumeratorNumberOfLimbsUsed());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsUsed());
- Assert.AreEqual(n + "/" + d, a.ToString());
+ Assert.AreEqual(2, a.NumberOfLimbsAllocated());
+ Assert.AreEqual(1, a.NumberOfLimbsUsed());
+ Assert.IsTrue(a.Exponent() > 0);
+ Assert.AreEqual("0." + n + "@15", a.ToString());
}
}
[TestMethod]
- public void RationalConstructorFromLongNegative()
+ public void FloatConstructorFromLongNegative()
{
var n = "-123456789123456";
- var d = "12764787846358441471";
- using (var a = new HugeRational(long.Parse(n), ulong.Parse(d)))
+ using (var a = new HugeFloat(long.Parse(n)))
{
- Assert.AreEqual(1, a.NumeratorNumberOfLimbsAllocated());
- Assert.AreEqual(-1, a.NumeratorNumberOfLimbsUsed());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsUsed());
- Assert.AreEqual(n + "/" + d, a.ToString());
+ Assert.AreEqual(2, a.NumberOfLimbsAllocated());
+ Assert.AreEqual(-1, a.NumberOfLimbsUsed());
+ Assert.IsTrue(a.Exponent() > 0);
+ Assert.AreEqual("-0." + n.Substring(1) + "@15", a.ToString());
}
}
[TestMethod]
- public void RationalConstructorFromULong()
+ public void FloatConstructorFromULong()
{
- var d = "12764787846358441471";
- using (var a = new HugeRational(ulong.MaxValue, ulong.Parse(d)))
+ using (var a = new HugeFloat(ulong.MaxValue))
{
- Assert.AreEqual(1, a.NumeratorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.NumeratorNumberOfLimbsUsed());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsUsed());
- Assert.AreEqual(ulong.MaxValue.ToString(), a.Numerator.ToString());
- Assert.AreEqual(ulong.MaxValue.ToString() + "/" + d, a.ToString());
+ Assert.AreEqual(2, a.NumberOfLimbsAllocated());
+ Assert.AreEqual(1, a.NumberOfLimbsUsed());
+ Assert.IsTrue(a.Exponent() > 0);
+ var n = ulong.MaxValue.ToString();
+ Assert.AreEqual("0." + n + "@" + n.Length, a.ToString());
}
}
[TestMethod]
- public void RationalConstructorFromDouble()
+ public void FloatConstructorFromDouble()
{
- using (var a = new HugeRational(123456789123456.75))
+ using (var a = new HugeFloat(123456789123456.75))
{
- Assert.AreEqual("493827156493827/4", a.ToString());
+ Assert.AreEqual("0.12345678912345675@15", a.ToString());
}
}
[TestMethod]
- public void RationalConstructorFromDoubleNegative()
+ public void FloatConstructorFromDoubleNegative()
{
- using (var a = new HugeRational(-123456789123456.75))
+ using (var a = new HugeFloat(-123456789123456.75))
{
- Assert.AreEqual("-493827156493827/4", a.ToString());
+ Assert.AreEqual("-0.12345678912345675@15", a.ToString());
}
}
[TestMethod]
- public void RationalAllocate()
+ public void FloatAllocate()
{
- using (var a = HugeRational.Allocate(129, 193))
+ using (var a = HugeFloat.Allocate(129))
{
- Assert.AreEqual(3, a.NumeratorNumberOfLimbsAllocated());
- Assert.AreEqual(0, a.NumeratorNumberOfLimbsUsed());
- Assert.AreEqual(4, a.DenominatorNumberOfLimbsAllocated());
- Assert.AreEqual(1, a.DenominatorNumberOfLimbsUsed());
- Assert.AreEqual("0/1", a.ToString());
+ Assert.AreEqual(4, a.NumberOfLimbsAllocated());
+ Assert.AreEqual(0, a.NumberOfLimbsUsed());
+ Assert.AreEqual("0", a.ToString());
+
+ var n = "234095827340957823409582587";
+ a.SetTo(n);
+ Assert.AreEqual("0." + n + "@" + n.Length, a.ToString());
}
}
[TestMethod]
- public void RationalCanonicalize()
+ public void FloatStringConstructor()
{
- using (var a = new HugeRational(198, 15))
+ var n = "0.54321098765432123457@28";
+ using (var a = new HugeFloat(n))
{
- a.Denominator.Value = -a.Denominator;
- Assert.AreEqual("198/-15", a.ToString());
- a.Canonicalize();
- Assert.AreEqual("-66/5", a.ToString());
- }
- }
-
- [TestMethod]
- public void RationalStringConstructor()
- {
- var n = "5432109876543212345789023245987/362736035870515331128527330659";
- using (var a = new HugeRational(n))
- {
- Assert.AreEqual(2, a.NumeratorNumberOfLimbsUsed());
+ Assert.AreEqual(2, a.NumberOfLimbsAllocated());
Assert.AreEqual(n, a.ToString());
}
}
[TestMethod]
- public void RationalStringConstructorNumeratorOnly()
+ [ExpectedException(typeof(ArgumentException))]
+ public void FloatStringConstructorInvalid()
{
- var n = "5432109876543212345789023245987";
- using(var a = new HugeRational(n))
+ var a = new HugeFloat("12345A");
+ }
+
+ [TestMethod]
+ public void FloatStringConstructorHex()
+ {
+ var n = "143210ABCDEF321234";
+ using (var a = new HugeFloat(n, 16))
{
- Assert.AreEqual(2, a.NumeratorNumberOfLimbsUsed());
- Assert.AreEqual(n + "/1", a.ToString());
+ Assert.AreEqual("0." + n + "@18", a.ToString(16));
}
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
- public void RationalStringConstructorInvalid()
+ public void FloatStringConstructorHexPrefix()
{
- var a = new HugeRational("12345A");
+ var n = "0x143210ABCDEF32123457ACDB324598799";
+ var a = new HugeFloat(n);
}
[TestMethod]
- [ExpectedException(typeof(ArgumentException))]
- public void RationalStringConstructorInvalid2()
+ public void FloatConstructorFromExpression()
{
- var a = new HugeRational("12345/54321A");
- }
-
- [TestMethod]
- public void RationalStringConstructorHex()
- {
- using (var i = new HugeInt("362736035870515331128527330659"))
- {
- var d = i.ToString(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);
- }
- }
- }
-
- [TestMethod]
- public void RationalStringConstructorHexPrefix()
- {
- using (var i = new HugeInt("362736035870515331128527330659"))
- {
- var d = i.ToString(16);
- var n = "143210ABCDEF32123457ACDB324598799";
- using (var a = new HugeRational("0x" + n + "/0x" + d))
- {
- Assert.AreEqual(n + "/" + d, a.ToString(16));
- Assert.AreEqual(i, a.Denominator);
- }
- }
- }
-
- [TestMethod]
- public void RationalStringAssignmentHexPrefix()
- {
- using (var i = new HugeInt("362736035870515331128527330659"))
- {
- var d = i.ToString(16);
- var n = "143210ABCDEF32123457ACDB324598799";
- using (var a = new HugeRational("0x" + n + "/0x" + d))
- {
- Assert.AreEqual(n + "/" + d, a.ToString(16));
- Assert.AreEqual(n + "/" + d, a.ToString(16, false));
- Assert.AreEqual((n + "/" + d).ToLower(), a.ToString(16, true));
- a.SetTo("-0x" + n + "/0x17");
- Assert.AreEqual("-" + n + "/17", a.ToString(16));
- }
- }
- }
-
- [TestMethod]
- public void RationalConstructorFromExpression()
- {
- using (var a = new HugeRational("2340958273409578234095823045723490587/362736035870515331128527330659"))
- using (var b = new HugeRational(a + 1))
+ using (var a = new HugeFloat("2340958273409578234095823045.5"))
+ using (var b = new HugeFloat(a + 1))
{
Assert.AreEqual(a + 1, b);
}
}
[TestMethod]
- public void RationalConstructorFromIntExpression()
+ public void FloatConstructorFromIntExpression()
{
- using (var a = new HugeInt("2340958273409578234095823045723490587"))
- using (var b = new HugeRational(a + 1))
+ using (var a = new HugeInt("234095827340957823409582587"))
+ using (var b = new HugeFloat(a + 1))
{
- Assert.AreEqual("2340958273409578234095823045723490588/1", b.ToString());
- }
- }
-
- [TestMethod]
- public void RationalConstructorFromIntExpression2()
- {
- using (var a = new HugeInt("2340958273409578234095823045723490587"))
- using (var d = new HugeInt("362736035870515331128527330659"))
- using (var b = new HugeRational(a + 2, d * 2))
- {
- Assert.AreEqual(a + 2, b.Numerator);
- Assert.AreEqual(d * 2, b.Denominator);
+ Assert.AreEqual("0.23409582734095782341@27", b.ToString());
}
}
}
diff --git a/mpir.net/mpir.net-tests/Utilities/Accessors.cs b/mpir.net/mpir.net-tests/Utilities/Accessors.cs
index b11b464d..65506600 100644
--- a/mpir.net/mpir.net-tests/Utilities/Accessors.cs
+++ b/mpir.net/mpir.net-tests/Utilities/Accessors.cs
@@ -163,4 +163,56 @@ namespace MPIR.Tests
}
}
}
+
+ internal static class FloatAccessors
+ {
+ internal static IntPtr _value(this HugeFloat x)
+ {
+ return Accessors._value(x);
+ }
+
+ internal static int NumberOfLimbsAllocated(this HugeFloat x)
+ {
+ if (_value(x) == IntPtr.Zero)
+ return 0;
+
+ unsafe
+ {
+ return ((int*)_value(x).ToPointer())[0];
+ }
+ }
+
+ internal static int NumberOfLimbsUsed(this HugeFloat x)
+ {
+ if (_value(x) == IntPtr.Zero)
+ return 0;
+
+ unsafe
+ {
+ return ((int*)_value(x).ToPointer())[1];
+ }
+ }
+
+ internal static int Exponent(this HugeFloat x)
+ {
+ if (_value(x) == IntPtr.Zero)
+ return 0;
+
+ unsafe
+ {
+ return ((int*)_value(x).ToPointer())[2];
+ }
+ }
+
+ internal static IntPtr Limbs(this HugeFloat x)
+ {
+ if (_value(x) == IntPtr.Zero)
+ return IntPtr.Zero;
+
+ unsafe
+ {
+ return new IntPtr(((void**)_value(x).ToPointer())[2]);
+ }
+ }
+ }
}
diff --git a/mpir.net/mpir.net/HugeFloat.cpp b/mpir.net/mpir.net/HugeFloat.cpp
index 1c3fedf8..2ec593fe 100644
--- a/mpir.net/mpir.net/HugeFloat.cpp
+++ b/mpir.net/mpir.net/HugeFloat.cpp
@@ -113,11 +113,51 @@ namespace MPIR
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();
+ size_t allocated;
+ mp_exp_t exponent;
+ bool negative = false;
+ bool truncated = false;
+ char* allocatedStr = NULL;
+ EvaluationContext context;
+ auto result = gcnew StringBuilder(maxDigits + 20);
+
+ ASSIGN_TO(context);
+
+ if(maxDigits > 0)
+ {
+ allocated = maxDigits + 2;
+ allocatedStr = (char*)(*__gmp_allocate_func)(allocated);
+ }
+ else
+ {
+ allocated = 0;
+ }
+
+ allocatedStr = MP(get_str)(allocatedStr, &exponent, (base <= 36 && !lowercase) ? -base : base, maxDigits, CTXT(0));
+
+ char* str = allocatedStr;
+
+ if(*str == '-')
+ result->Append((wchar_t)*str++);
+
+ result->Append((wchar_t)'0');
+ if (*str != 0)
+ {
+ result->Append((wchar_t)'.');
+
+ while (*str != 0)
+ result->Append((wchar_t)*str++);
+ }
+
+ if (exponent != 0)
+ result->Append((wchar_t)'@')->Append(exponent);
+
+ if (allocated == 0)
+ allocated = str - allocatedStr + 1;
+
+ (*__gmp_free_func)(allocatedStr, allocated);
+
+ return result->ToString();
}
int MPEXPR_NAME::GetHashCode()
diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h
index 785e8b18..10c34f0a 100644
--- a/mpir.net/mpir.net/HugeFloat.h
+++ b/mpir.net/mpir.net/HugeFloat.h
@@ -803,14 +803,12 @@ namespace MPIR
///
/// 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);
@@ -950,16 +948,14 @@ namespace MPIR
///
/// 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); }
@@ -973,8 +969,7 @@ namespace MPIR
///
/// 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:
@@ -984,8 +979,7 @@ namespace MPIR
///
/// 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.