diff --git a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj index 4fb6a606..0599225f 100644 --- a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj +++ b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj @@ -155,6 +155,7 @@ + Create Create diff --git a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters index a423f954..5d6a08a6 100644 --- a/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters +++ b/build.vc11/mpir.net/mpir.net/mpir.net.vcxproj.filters @@ -56,6 +56,9 @@ Source Files + + Source Files + diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/ExpressionTests.cs b/mpir.net/mpir.net-tests/HugeFloatTests/ExpressionTests.cs index d1c9d3f5..157674a2 100644 --- a/mpir.net/mpir.net-tests/HugeFloatTests/ExpressionTests.cs +++ b/mpir.net/mpir.net-tests/HugeFloatTests/ExpressionTests.cs @@ -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); } diff --git a/mpir.net/mpir.net-tests/IntegrationTests/XmlCommentsTests.cs b/mpir.net/mpir.net-tests/IntegrationTests/XmlCommentsTests.cs index e170da5b..c34d7e8c 100644 --- a/mpir.net/mpir.net-tests/IntegrationTests/XmlCommentsTests.cs +++ b/mpir.net/mpir.net-tests/IntegrationTests/XmlCommentsTests.cs @@ -75,6 +75,7 @@ namespace MPIR.Tests.HugeIntTests var contents = File.ReadAllText(path); contents = Regex.Replace(contents, "]*>", "paramref"); contents = Regex.Replace(contents, "", ""); + contents = contents.Replace("!System.Runtime.CompilerServices.IsLong", ""); var serializer = new XmlSerializer(typeof(XmlCommentsDoc)); using (var reader = new StringReader(contents)) diff --git a/mpir.net/mpir.net-tests/RandomTests/Random.cs b/mpir.net/mpir.net-tests/RandomTests/Random.cs index 8e1d3d8e..8661d37b 100644 --- a/mpir.net/mpir.net-tests/RandomTests/Random.cs +++ b/mpir.net/mpir.net-tests/RandomTests/Random.cs @@ -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)); + } + } } } diff --git a/mpir.net/mpir.net/HugeFloat.cpp b/mpir.net/mpir.net/HugeFloat.cpp index 514d2b9d..5d861aa9 100644 --- a/mpir.net/mpir.net/HugeFloat.cpp +++ b/mpir.net/mpir.net/HugeFloat.cpp @@ -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; diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h index 994cab1d..3dcfb406 100644 --- a/mpir.net/mpir.net/HugeFloat.h +++ b/mpir.net/mpir.net/HugeFloat.h @@ -87,7 +87,7 @@ namespace MPIR auto ptr = &context.Temp[context.Index].MPTYPE_NAME; CTXT(context.Index++) = ptr; MP(init)(ptr); - AssignTo(ptr); + AssignTo(ptr); } private: @@ -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 diff --git a/mpir.net/mpir.net/Random.cpp b/mpir.net/mpir.net/Random.cpp index ea406abc..f1862e58 100644 --- a/mpir.net/mpir.net/Random.cpp +++ b/mpir.net/mpir.net/Random.cpp @@ -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); } -}; \ No newline at end of file +}; diff --git a/mpir.net/mpir.net/Random.h b/mpir.net/mpir.net/Random.h index 08130792..4df7b518 100644 --- a/mpir.net/mpir.net/Random.h +++ b/mpir.net/mpir.net/Random.h @@ -23,8 +23,6 @@ using namespace System; namespace MPIR { - ref class MpirRandom; - /// /// This class encapsulates a random number generator algorithm and state /// @@ -234,5 +232,46 @@ namespace MPIR IntegerExpression^ GetInt(IntegerExpression^ max) { return gcnew IntegerRandomExpression(this, max); } #pragma endregion + + #pragma region Random Float + + /// + /// Generates a uniformly distributed random float in the range 0 <= n < 1, using the precision of the destination. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number + FloatExpression^ GetFloat(); + + /// + /// Generates a uniformly distributed random float in the range 0 <= n < 1 with the specified number of significant bits in the mantissa. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// number of mantissa bits to generate + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number + FloatExpression^ GetFloatBits(mp_bitcnt_t bitCount); + + /// + /// Generates a random float with long strings of zeros and ones in the binary representation, using the precision of the destination. + /// Useful for testing functions and algorithms, since this kind of random numbers have proven + /// to be more likely to trigger corner-case bugs. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// The maximum absolute value for the exponent of the generated number. Generated exponent may be positive or negative. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number + FloatExpression^ GetFloatChunky(mp_exp_t maxExponent); + + /// + /// 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. + /// Useful for testing functions and algorithms, since this kind of random numbers have proven + /// to be more likely to trigger corner-case bugs. + /// As with all expressions, the result is not computed until the expression is assigned to the Value property or consumed by a method. + /// + /// number of mantissa limbs to generate. + /// The sign of this parameter determines the sign of the generated mantissa. + /// The maximum absolute value for the exponent of the generated number. Generated exponent may be positive or negative. + /// An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number + FloatExpression^ GetFloatLimbsChunky(mp_size_t limbCount, mp_exp_t maxExponent); + + #pragma endregion }; }; diff --git a/mpir.net/mpir.net/RandomFloat.cpp b/mpir.net/mpir.net/RandomFloat.cpp new file mode 100644 index 00000000..f19a46f0 --- /dev/null +++ b/mpir.net/mpir.net/RandomFloat.cpp @@ -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); + } +};