Float construction and disposal tests.

This commit is contained in:
Alex Dyachenko 2014-06-16 16:08:01 -04:00
parent 3fda7f427e
commit 49775dbedb
4 changed files with 136 additions and 186 deletions

View File

@ -20,267 +20,148 @@ 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.AreEqual(0, a.NumberOfLimbsUsed());
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreNotEqual(IntPtr.Zero, a.Limbs());
Assert.AreEqual(0, a.Exponent());
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.NumberOfLimbsUsed());
Assert.AreEqual(0, a.Precision());
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)))
var n = 0x3123456789123456L;
using (var a = new HugeFloat(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(128UL, a._allocatedPrecision);
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(1, a.Exponent());
Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16));
}
}
[TestMethod]
public void RationalConstructorFromLongNegative()
public void FloatConstructorFromLongNegative()
{
var n = "-123456789123456";
var d = "12764787846358441471";
using (var a = new HugeRational(long.Parse(n), ulong.Parse(d)))
var n = 0x3123456789123456L;
using(var a = new HugeFloat(-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(128UL, a._allocatedPrecision);
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(1, a.Exponent());
Assert.AreEqual("-0." + n.ToString("X") + "@16", a.ToString(16));
}
}
[TestMethod]
public void RationalConstructorFromULong()
public void FloatConstructorFromULong()
{
var d = "12764787846358441471";
using (var a = new HugeRational(ulong.MaxValue, ulong.Parse(d)))
var n = ulong.MaxValue;
using(var a = new HugeFloat(n))
{
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(128UL, a._allocatedPrecision);
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(1, a.Exponent());
Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16));
}
}
[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());
FloatAssert.AreEqual("123456789123456.75", a);
}
}
[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());
FloatAssert.AreEqual("-123456789123456.75", a);
}
}
[TestMethod]
public void RationalAllocate()
public void FloatAllocate()
{
using (var a = HugeRational.Allocate(129, 193))
using (var a = HugeFloat.Allocate(193))
{
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(5, a.Precision());
Assert.AreEqual(256UL, a._allocatedPrecision);
Assert.AreEqual("0", a.ToString());
}
}
[TestMethod]
public void RationalCanonicalize()
public void FloatStringConstructor()
{
using (var a = new HugeRational(198, 15))
var n = "5432109876543212345789.70515331128527330659";
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(n, a.ToString());
}
}
[TestMethod]
public void RationalStringConstructorNumeratorOnly()
{
var n = "5432109876543212345789023245987";
using(var a = new HugeRational(n))
{
Assert.AreEqual(2, a.NumeratorNumberOfLimbsUsed());
Assert.AreEqual(n + "/1", a.ToString());
FloatAssert.AreEqual(n, a);
}
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void RationalStringConstructorInvalid()
public void FloatStringConstructorInvalid()
{
var a = new HugeRational("12345A");
var a = new HugeFloat("12345A");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void RationalStringConstructorInvalid2()
public void FloatStringConstructorHex()
{
var a = new HugeRational("12345/54321A");
}
[TestMethod]
public void RationalStringConstructorHex()
{
using (var i = new HugeInt("362736035870515331128527330659"))
var n = "143210ABCDEF32123457ACDB324.59879";
using (var a = new HugeFloat(n, 16))
{
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);
}
Assert.AreEqual("0.143210ABCDEF32123457ACDB32459879@27", a.ToString(16));
}
}
[TestMethod]
public void RationalStringConstructorHexPrefix()
public void FloatConstructorFromExpression()
{
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("29340273582305894258424059.2345293574"))
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 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);
FloatAssert.AreEqual("2340958273409578234095823045723490588.", b);
}
}
}

View File

@ -38,7 +38,7 @@ namespace MPIR.Tests
_intPtrConstructor = typeof(IntPtr).GetConstructor(new[] { Type.GetType("System.Void*") });
}
private static FieldInfo GetAccessor(string name)
internal static FieldInfo GetAccessor(string name)
{
return typeof(T).GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
}
@ -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 Precision(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**)((int*)_value(x).ToPointer() + 3));
}
}
}
}

View File

@ -33,19 +33,24 @@ namespace MPIR
{
AllocateStruct();
MP(init)(_value);
_allocatedPrecision = MP(get_prec)(_value);
}
MPTYPE::MPTYPE(bool initialize)
{
AllocateStruct();
if(initialize)
{
MP(init)(_value);
_allocatedPrecision = MP(get_prec)(_value);
}
}
MPTYPE::MPTYPE(MPEXPR_NAME^ value)
{
AllocateStruct();
MP(init)(_value);
_allocatedPrecision = MP(get_prec)(_value);
value->AssignTo(_value);
}
@ -53,6 +58,7 @@ namespace MPIR
{
AllocateStruct();
MP(init)(_value);
_allocatedPrecision = MP(get_prec)(_value);
SetTo(value);
}
@ -60,6 +66,7 @@ namespace MPIR
{
auto result = gcnew MPTYPE(false);
MP(init2)(result->_value, precision);
result->_allocatedPrecision = MP(get_prec)(result->_value);
return result;
}
@ -67,6 +74,7 @@ namespace MPIR
{
AllocateStruct();
MP(init)(_value);
_allocatedPrecision = MP(get_prec)(_value);
IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
bool success = 0 == MP(set_str)(_value, (char*)(void*)ptr, base);
@ -93,18 +101,21 @@ namespace MPIR
{
AllocateStruct();
MP(init_set_si)(_value, value);
_allocatedPrecision = MP(get_prec)(_value);
}
MPTYPE::MPTYPE(mpir_ui value)
{
AllocateStruct();
MP(init_set_ui)(_value, value);
_allocatedPrecision = MP(get_prec)(_value);
}
MPTYPE::MPTYPE(double value)
{
AllocateStruct();
MP(init_set_d)(_value, value);
_allocatedPrecision = MP(get_prec)(_value);
}
#pragma endregion

View File

@ -759,8 +759,6 @@ namespace MPIR
void AllocateStruct()
{
_value = (MP(ptr))((*__gmp_allocate_func)(sizeof(MPSTRUCT)));
//todo: move this to wherever init is called
_allocatedPrecision = MP(get_prec)(_value);
}
void FromString(String^ value, int base);
MPTYPE(bool initialize);
@ -794,6 +792,12 @@ namespace MPIR
DefaultPrecision = sizeof(mpir_ui) * 8 * 2; //2 limbs
}
/// <summary>
/// Gets or sets the default precision of a float variable in bits.
/// <para>The actual precision may be slightly greater if the value is not a whole limb multiple.
/// </para>All subsequently constructed variables will use this precision, but previously constructed variables are unaffected.
/// <para>The initial default value is 2 limbs.
/// </para></summary>
static property mp_bitcnt_t DefaultPrecision
{
mp_bitcnt_t get() { return MP(get_default_prec)(); }
@ -801,8 +805,9 @@ namespace MPIR
}
/// <summary>
/// Initializes a new float instance and sets its value to 0/1
/// </summary>
/// Initializes a new float instance and sets its value to 0/1.
/// <para>The precision of the new variable's mantissa is set from the static DefaultPrecision property.
/// </para></summary>
MPTYPE();
/// <summary>
@ -1271,6 +1276,7 @@ namespace MPIR
/// <summary>Computes the square root of the source number.
/// <para>As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
/// </para></summary>
/// <param name="a">source number to take the square root of</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, computes the requested operation</returns>
static MPEXPR_NAME^ SquareRoot(mpir_ui a) { return gcnew MPEXPR(SquareRootUi)(a); }