Float Random methods. 2 TODOs.

This commit is contained in:
Alex Dyachenko 2014-06-27 16:28:09 -04:00
parent 11e33c7140
commit 76907497f0
10 changed files with 167 additions and 8 deletions

View File

@ -155,6 +155,7 @@
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeInt.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeRational.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\Random.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\RandomFloat.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\Stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>

View File

@ -56,6 +56,9 @@
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeFloat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\mpir.net\mpir.net\RandomFloat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\..\mpir.net\mpir.net\ReadMe.txt" />

View File

@ -62,6 +62,14 @@ namespace MPIR.Tests.HugeFloatTests
VerifyPartialResult(r, expr, -19);
expr = expr - (a / 4).Floor() + (b / 3).Ceiling() - (a / b).Truncate();
VerifyPartialResult(r, expr, -12);
expr = expr + (r.GetFloatBits(64) * 10).Ceiling();
VerifyPartialResult(r, expr, -10);
expr = expr + (r.GetFloatLimbsChunky(2, 4) << 233).Ceiling();
VerifyPartialResult(r, expr, -6);
expr = expr + (r.GetFloat() * 10).Floor();
VerifyPartialResult(r, expr, -2);
expr = expr + (r.GetFloatChunky(3) << 101).Truncate();
VerifyPartialResult(r, expr, 13);
MarkExpressionsUsed(allExpressions, expr);
}

View File

@ -75,6 +75,7 @@ namespace MPIR.Tests.HugeIntTests
var contents = File.ReadAllText(path);
contents = Regex.Replace(contents, "<paramref[^>]*>", "paramref");
contents = Regex.Replace(contents, "</?para>", "");
contents = contents.Replace("!System.Runtime.CompilerServices.IsLong", "");
var serializer = new XmlSerializer(typeof(XmlCommentsDoc));
using (var reader = new StringReader(contents))

View File

@ -184,5 +184,53 @@ namespace MPIR.Tests.RandomTests
Assert.AreEqual("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000000000000000000007F", a.ToString(16));
}
}
[TestMethod]
public void RandomHugeFloat()
{
using(var r = MpirRandom.Default())
using(var a = HugeFloat.Allocate(256))
{
r.Seed(12345789);
a.Value = r.GetFloat();
Assert.AreEqual("0.9E056474F27BEDF9AE62FB31A30B68DFA0B96F29D0C8767A88F8937D6F3A00FD@0", a.ToString(16));
}
}
[TestMethod]
public void RandomHugeFloatBits()
{
using(var r = MpirRandom.Default())
using(var a = HugeFloat.Allocate(256))
{
r.Seed(12345789);
a.Value = r.GetFloatBits(128);
Assert.AreEqual("0.A0B96F29D0C8767A88F8937D6F3A00FD@0", a.ToString(16));
}
}
[TestMethod]
public void RandomHugeFloatChunky()
{
using(var r = MpirRandom.Default())
using(var a = HugeFloat.Allocate(256))
{
r.Seed(12345789);
a.Value = r.GetFloatChunky(100);
Assert.AreEqual("0.7FFFFFFF0180000000000000000007FFFFFFFFFFFFFFFFFFF@-2EF", a.ToString(16));
}
}
[TestMethod]
public void RandomHugeFloatLimbsChunky()
{
using(var r = MpirRandom.Default())
using(var a = HugeFloat.Allocate(256))
{
r.Seed(12345789);
a.Value = r.GetFloatLimbsChunky(2, 100);
Assert.AreEqual("0.7FFFFFF8000007FFF@2C1", a.ToString(16));
}
}
}
}

View File

@ -21,7 +21,6 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
#include "HugeInt.h"
#include "HugeRational.h"
#include "HugeFloat.h"
//#include "Random.h"
using namespace System::Runtime::InteropServices;
using namespace System::Text;

View File

@ -767,6 +767,11 @@ namespace MPIR
DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Ceiling, Flt)
DEFINE_UNARY_EXPRESSION_WITH_ONE (MPEXPR_NAME, Truncate, Flt)
DEFINE_UNARY_EXPRESSION (MPEXPR_NAME, Random, MpirRandom^)
DEFINE_BINARY_EXPRESSION (MPEXPR_NAME, RandomBits, MpirRandom^, mp_bitcnt_t)
DEFINE_BINARY_EXPRESSION (MPEXPR_NAME, RandomChunky, MpirRandom^, mp_exp_t)
DEFINE_TERNARY_EXPRESSION (MPEXPR_NAME, RandomLimbsChunky, MpirRandom^, mp_size_t, mp_exp_t)
#pragma endregion
#pragma region HugeFloat class

View File

@ -26,16 +26,16 @@ namespace MPIR
DEFINE_ASSIGNMENT_PROLOG(Random)
{
IN_CONTEXT(Right);
mpz_urandomm(destination, Left->_value, context.IntArgs[0]);
MP(urandomm)(destination, Left->_value, context.IntArgs[0]);
}
DEFINE_ASSIGNMENT_PROLOG(RandomBits)
{
mpz_urandomb(destination, Left->_value, Right);
MP(urandomb)(destination, Left->_value, Right);
}
DEFINE_ASSIGNMENT_PROLOG(RandomBitsChunky)
{
mpz_rrandomb(destination, Left->_value, Right);
MP(rrandomb)(destination, Left->_value, Right);
}
};

View File

@ -23,8 +23,6 @@ using namespace System;
namespace MPIR
{
ref class MpirRandom;
/// <summary>
/// This class encapsulates a random number generator algorithm and state
/// </summary>
@ -234,5 +232,46 @@ namespace MPIR
IntegerExpression^ GetInt(IntegerExpression^ max) { return gcnew IntegerRandomExpression(this, max); }
#pragma endregion
#pragma region Random Float
/// <summary>
/// Generates a uniformly distributed random float in the range 0 &lt;= n &lt; 1, using the precision of the destination.
/// <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>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
FloatExpression^ GetFloat();
/// <summary>
/// Generates a uniformly distributed random float in the range 0 &lt;= n &lt; 1 with the specified number of significant bits in the mantissa.
/// <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="bitCount">number of mantissa bits to generate</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
FloatExpression^ GetFloatBits(mp_bitcnt_t bitCount);
/// <summary>
/// Generates a random float with long strings of zeros and ones in the binary representation, using the precision of the destination.
/// <para>Useful for testing functions and algorithms, since this kind of random numbers have proven
/// to be more likely to trigger corner-case bugs.
/// </para>As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
/// </summary>
/// <param name="maxExponent">The maximum absolute value for the exponent of the generated number. Generated exponent may be positive or negative.</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
FloatExpression^ GetFloatChunky(mp_exp_t maxExponent);
/// <summary>
/// Generates a random float with long strings of zeros and ones in the binary representation, and the specified number of significant limbs in the mantissa.
/// <para>Useful for testing functions and algorithms, since this kind of random numbers have proven
/// to be more likely to trigger corner-case bugs.
/// </para>As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method.
/// </summary>
/// <param name="limbCount">number of mantissa limbs to generate.
/// <para>The sign of this parameter determines the sign of the generated mantissa.</para></param>
/// <param name="maxExponent">The maximum absolute value for the exponent of the generated number. Generated exponent may be positive or negative.</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
FloatExpression^ GetFloatLimbsChunky(mp_size_t limbCount, mp_exp_t maxExponent);
#pragma endregion
};
};

View File

@ -0,0 +1,55 @@
/*
Copyright 2014 Alex Dyachenko
This file is part of the MPIR Library.
The MPIR Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
The MPIR Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
*/
#include "StdAfx.h"
#include "HugeInt.h"
#include "Random.h"
#include "HugeRational.h"
#include "HugeFloat.h"
namespace MPIR
{
MPEXPR_NAME^ MpirRandom::GetFloat() { return gcnew FloatRandomExpression(this); }
MPEXPR_NAME^ MpirRandom::GetFloatBits(mp_bitcnt_t bitCount) { return gcnew FloatRandomBitsExpression(this, bitCount); }
MPEXPR_NAME^ MpirRandom::GetFloatChunky(mp_exp_t maxExponent) { return gcnew FloatRandomChunkyExpression(this, maxExponent); }
MPEXPR_NAME^ MpirRandom::GetFloatLimbsChunky(mp_size_t limbCount, mp_exp_t maxExponent) { return gcnew FloatRandomLimbsChunkyExpression(this, limbCount, maxExponent); }
DEFINE_ASSIGNMENT_PROLOG(Random)
{
MP(urandomb)(destination, Operand->_value, MP(get_prec)(destination));
}
DEFINE_ASSIGNMENT_PROLOG(RandomBits)
{
MP(urandomb)(destination, Left->_value, Right);
}
DEFINE_ASSIGNMENT_PROLOG(RandomChunky)
{
MP(rrandomb)(destination, Left->_value, BITS_TO_LIMBS(MP(get_prec)(destination)), Right);
}
//TODO investigate why exponent does not seem to be in the promised range
//TODO implement "precision of destination" for context ops
DEFINE_ASSIGNMENT_PROLOG(RandomLimbsChunky)
{
MP(rrandomb)(destination, Left->_value, Middle, Right);
}
};