Float Changing precision. MPIR 2.7.0 section 7.1 completed.

This commit is contained in:
Alex Dyachenko 2014-06-16 16:46:14 -04:00
parent 49775dbedb
commit ef95a16dab
3 changed files with 96 additions and 17 deletions

View File

@ -31,7 +31,7 @@ namespace MPIR.Tests.HugeFloatTests
using (var a = new HugeFloat())
{
Assert.AreEqual(0, a.NumberOfLimbsUsed());
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreNotEqual(IntPtr.Zero, a.Limbs());
Assert.AreEqual(0, a.Exponent());
@ -46,7 +46,6 @@ namespace MPIR.Tests.HugeFloatTests
a.Dispose();
Assert.AreEqual(0, a.NumberOfLimbsUsed());
Assert.AreEqual(0, a.Precision());
Assert.AreEqual(IntPtr.Zero, a.Limbs());
}
@ -57,7 +56,7 @@ namespace MPIR.Tests.HugeFloatTests
using (var a = new HugeFloat(n))
{
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(1, a.Exponent());
Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16));
}
@ -70,7 +69,7 @@ namespace MPIR.Tests.HugeFloatTests
using(var a = new HugeFloat(-n))
{
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(1, a.Exponent());
Assert.AreEqual("-0." + n.ToString("X") + "@16", a.ToString(16));
}
@ -83,7 +82,7 @@ namespace MPIR.Tests.HugeFloatTests
using(var a = new HugeFloat(n))
{
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(3, a.Precision());
Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(1, a.Exponent());
Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16));
}
@ -112,7 +111,7 @@ namespace MPIR.Tests.HugeFloatTests
{
using (var a = HugeFloat.Allocate(193))
{
Assert.AreEqual(5, a.Precision());
Assert.AreEqual(256UL, a.Precision);
Assert.AreEqual(256UL, a._allocatedPrecision);
Assert.AreEqual("0", a.ToString());
}
@ -164,5 +163,61 @@ namespace MPIR.Tests.HugeFloatTests
FloatAssert.AreEqual("2340958273409578234095823045723490588.", b);
}
}
[TestMethod]
public void FloatSetPrecision()
{
using (var a = new HugeFloat(1))
using (var b = new HugeFloat())
{
a.Value = a/3;
b.Value = a;
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual("0.3333333333333333333333333333333333333333@0", a.ToString());
a.Precision = 64;
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(64UL, a.Precision);
Assert.AreEqual("0.333333333333333333333@0", a.ToString());
Assert.AreEqual(a, b);
a.Precision = 128;
Assert.AreEqual("0.3333333333333333333333333333333333333333@0", a.ToString());
a.Precision = 64;
a.SetTo(1);
a.Value = a / 3;
Assert.AreNotEqual(a, b);
Assert.AreEqual("0.333333333333333333333@0", a.ToString());
a.Precision = 128;
Assert.AreNotEqual(a, b);
}
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void FloatSettingPrecisionOverAllocated()
{
using (var a = new HugeFloat())
{
a.Precision++;
}
}
[TestMethod]
public void FloatReallocate()
{
using (var a = HugeFloat.Allocate(128))
{
Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(128UL, a.Precision);
a.Reallocate(256);
Assert.AreEqual(256UL, a._allocatedPrecision);
Assert.AreEqual(256UL, a.Precision);
}
}
}
}

View File

@ -171,17 +171,6 @@ namespace MPIR.Tests
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)

View File

@ -1070,6 +1070,41 @@ namespace MPIR
#pragma region Size checks
/// <summary>
/// Gets or sets the effective precision of the number without changing the memory allocated.
/// <para>The number of bits cannot exceed the precision with which the variable was initialized or last reallocated.
/// </para>The value of the number is unchanged, and in particular if it previously had a higher precision it will retain that higher precision.
/// <para>New values assigned to the Value property will use the new precision.
/// </para>This is an efficient way to use a float variable at different precisions during a calculation,
/// perhaps to gradually increase precision in an iteration, or just to use various different
/// precisions for different purposes during a calculation.
/// <para>The number can be safely disposed after modifying its precision (this would not be the case in unmanaged MPIR).
/// </para></summary>
property mp_bitcnt_t Precision
{
mp_bitcnt_t get() { return MP(get_prec)(_value); }
void set(mp_bitcnt_t value)
{
if(value > _allocatedPrecision)
throw gcnew ArgumentException("Cannot set precision higher than allocated");
MP(set_prec_raw)(_value, value);
}
}
/// <summary>
/// Set the precision of rop to be at least prec bits, reallocating its limbs data.
/// <para>The value in rop will be truncated to the new precision.
/// </para>This function requires a call to realloc, and so should not be used in a tight loop.
/// </summary>
/// <param name="precision">Minimum number of bits the allocated memory should hold for the mantissa.</param>
void Reallocate(mp_bitcnt_t precision)
{
MP(set_prec_raw)(_value, _allocatedPrecision);
MP(set_prec)(_value, precision);
_allocatedPrecision = precision;
}
///// <summary>
///// Returns the number of digits the number would take if written in the specified base.
///// <para>The sign of the number is ignored, just the absolute value is used.