Float construction/disposal tests. Implemented float ToString().

This commit is contained in:
Alex Dyachenko 2014-11-19 12:51:21 -05:00
parent 45071bb9d1
commit d74453427c
5 changed files with 177 additions and 197 deletions

View File

@ -94,6 +94,9 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeFloatTests\ConstructionAndDisposal.cs">
<Link>HugeFloatTests\ConstructionAndDisposal.cs</Link>
</Compile>
<Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeIntTests\Arithmetic.cs">
<Link>HugeIntTests\Arithmetic.cs</Link>
</Compile>
@ -164,9 +167,7 @@
<Name>mpir.net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="HugeFloatTests\" />
</ItemGroup>
<ItemGroup />
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>

View File

@ -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());
}
}
}

View File

@ -163,4 +163,56 @@ namespace MPIR.Tests
}
}
}
internal static class FloatAccessors
{
internal static IntPtr _value(this HugeFloat x)
{
return Accessors<HugeFloat>._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]);
}
}
}
}

View File

@ -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()

View File

@ -803,14 +803,12 @@ namespace MPIR
/// <summary>
/// Constructs and returns a new float instance with its value set to <paramref name="value"/>.
/// <para>If the fraction is not in canonical form, Canonicalize() must be called.</para>
/// </summary>
/// <param name="value">value for the initial value for the new float instance</param>
MPTYPE(mpir_si value);
/// <summary>
/// Constructs and returns a new float instance with its value set to <paramref name="value"/>.
/// <para>If the fraction is not in canonical form, Canonicalize() must be called.</para>
/// </summary>
/// <param name="value">value for the initial value for the new float instance</param>
MPTYPE(mpir_ui value);
@ -950,16 +948,14 @@ namespace MPIR
/// <summary>
/// Sets the value of the float object.
/// <para>Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
/// </para>If the fraction is not in canonical form, Canonicalize() must be called.
/// </summary>
/// </para></summary>
/// <param name="value">value for the new value for the object</param>
void SetTo(mpir_ui value) { MP(set_ui)(_value, value); }
/// <summary>
/// Sets the value of the float object.
/// <para>Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
/// </para>If the fraction is not in canonical form, Canonicalize() must be called.
/// </summary>
/// </para></summary>
/// <param name="value">value for the new value for the object</param>
void SetTo(mpir_si value) { MP(set_si)(_value, value); }
@ -973,8 +969,7 @@ namespace MPIR
/// <summary>
/// Sets the value of the float object.
/// <para>Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
/// </para>If the fraction is not in canonical form, Canonicalize() must be called.
/// </summary>
/// </para></summary>
/// <param name="value">new value for the object.
/// <para>May be an float or a pair of floats separated by a slash.
/// </para>The string's leading characters may indicate base:
@ -984,8 +979,7 @@ namespace MPIR
/// <summary>
/// Sets the value of the float object.
/// <para>Do not change the value of an object while it is contained in a hash table, because that changes its hash code.
/// </para>If the fraction is not in canonical form, Canonicalize() must be called.
/// </summary>
/// </para></summary>
/// <param name="value">new value for the object</param>
/// <param name="base">base the <paramref name="value"/> string is in.
/// <para>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.