//================================================================================================== // S t a n d a r d Interface // R a n d o m _ n u m b e r // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This 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 Library General Public License for more details (http://www.gnu.org). // // This file is just an adaptation of MT19937 coded by Takuji Nishimura, considering the // suggestions by Topher Cooper and Marc Rieffel in July-August 1997. It is originally a GNU // Library General Public License with the following copyright: // // "Copyright (c) 1997 Makoto Matsumoto and Takuji Nishimura. // Any feedback is very welcome. For any question, comments, // see http://www.math.keio.ac.jp/matumoto/emt.html or e-mail // matumoto@math.keio.ac.jp."
/*DESCRIPTION*/ /* This module provides a random number generator (integer and real). It is just an adaptation of MT19937 coded by Takuji Nishimura, considering the suggestions by Topher Cooper and Marc Rieffel in July-August 1997. It is originally a GNU Library General Public License with the following copyright.<BR><BR> <BLOCKQUOTE><I>Copyright (c) 1997 Makoto Matsumoto and Takuji Nishimura.<BR> Any feedback is very welcome. For any question, comments,<BR> see <A HREF="http://www.math.keio.ac.jp/matumoto/emt.html" TARGET="new_window"> http://www.math.keio.ac.jp/matumoto/emt.html</A> or e-mail<BR> matumoto@math.keio.ac.jp.</I></BLOCKQUOTE> */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "standard/random_number.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guStandardRandomNumber #define guStandardRandomNumber
// Headers //--------------------------------------------------------------------------------------- #include <bpp/standard/maths.hpp> /*INCLUDE*/
namespace bpp {
// Importation/Exportation //----------------------------------------------------------------------- #ifdef STANDARD_DLL #define dll_export DLL_EXPORT #else #define dll_export DLL_IMPORT #endif
// Namespaces //------------------------------------------------------------------------------------ #define public_area standardRandomNumber #define private_area standardRandomNumber_private
namespace public_area { /*NAMESPACE*/ using namespace standardMaths; } namespace private_area { using namespace public_area; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniStandardRandomNumber has_initializer;
// Macrocommands //---------------------------------------------------------------------------------
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { class clRandomGenerator; } namespace private_area {}
// Functions Interface //--------------------------------------------------------------------------- namespace public_area { inline tyCardinal randomCardinal(tyCardinal); inline tyReal randomReal(void); }
namespace private_area { testing_mode ( function void test(void); ) }
// Errors //---------------------------------------------------------------------------------------- namespace public_area { /*ERROR*/ extern_error erRandomSeedParameterMissing; /* The <CODE>random_seed</CODE> parameter is missing in the initialization file. */ }
// Constants & Variables //------------------------------------------------------------------------- extern_dynamic_constant(private,clRandomGenerator,goRandomGenerator,?); extern_static_constant(private,clMutex,goMutex,?);
// R a n d o m G e n e r a t o r Interface //------------------------------------------------------ namespace public_area { /*CLASS clRandomGenerator */ /* Represents a random number generator. */ class clRandomGenerator { //-------------------------------------------------------------------------------------------Types /*TYPE clRandomGenerator */ /* Type of the seed of the random generator. */ public_property typedef unsigned long tySeed; //-----------------------------------------------------------------------------------------Private private_property constructor clRandomGenerator(const clRandomGenerator &); private_property const clRandomGenerator operator = (const clRandomGenerator &);
private_property tyCardinal mag01[2]; private_property tyCardinal mt[624]; private_property tyInteger mti; //------------------------------------------------------------------------------------------Public /*ATTRIBUTE clRandomGenerator */ /* Seed of the random generator. */ read_only_attribute(tySeed,atSeed,seed);
public_property constructor clRandomGenerator(tySeed); public_property destructor clRandomGenerator(void);
public_property tyCardinal nextCardinal(void); public_property tyReal nextCeilingReal(void); public_property tyReal nextFloorReal(void); public_property tyReal nextReal(void); }; }
// R a n d o m G e n e r a t o r Inline //--------------------------------------------------------- namespace public_area { //---------------------------------------------------------------------------------------Destructor /*METHOD clRandomGenerator */ /* Destructs the random generator. */ inline clRandomGenerator::~clRandomGenerator(void) {} //----------------------------------------------------------------------------------NextCeilingReal /*METHOD clRandomGenerator */ /* Returns the next real number in the random sequence. The value is generated between zero (excluded) and one (included). */ inline tyReal clRandomGenerator::nextCeilingReal(void) { return (1.0-(tyReal)nextCardinal()/(tyReal)4294967296.0); } //------------------------------------------------------------------------------------NextFloorReal /*METHOD clRandomGenerator */ /* Returns the next real number in the random sequence. The value is generated between zero (included) and one (excluded). */ inline tyReal clRandomGenerator::nextFloorReal(void) { return ((tyReal)nextCardinal()/(tyReal)4294967296.0); } //-----------------------------------------------------------------------------------------NextReal /*METHOD clRandomGenerator */ /* Returns the next real number in the random sequence. The value is generated between zero (included) and one (included). */ inline tyReal clRandomGenerator::nextReal(void) { return ((tyReal)nextCardinal()/(tyReal)4294967295.0); } }
// Functions Inline //------------------------------------------------------------------------------ namespace public_area { //-----------------------------------------------------------------------------------RandomCardinal /*FUNCTION*/ /* Returns a random integer number within a given range (<CODE>0</CODE> to <CODE>range-1</CODE>). */ inline tyCardinal randomCardinal(tyCardinal agRange) { tyCardinal lcNumber;
if (agRange==0) send_inline_error(erZeroDivision,"randomCardinal"); safe_yes ( private_area::goMutex.lock(); ) lcNumber=private_area::goRandomGenerator->nextCardinal(); safe_yes ( private_area::goMutex.release(); ) return (lcNumber%agRange); } //---------------------------------------------------------------------------------------RandomReal /*FUNCTION*/ /* Returns a random real number. */ inline tyReal randomReal(void) { tyReal lcNumber;
safe_yes ( private_area::goMutex.lock(); ) lcNumber=private_area::goRandomGenerator->nextReal(); safe_yes ( private_area::goMutex.release(); ) return (lcNumber); } }
namespace private_area {}
// End //------------------------------------------------------------------------------------------- } #undef dll_export #undef public_area #undef private_area #endif |
//================================================================================================== // S t a n d a r d Implementation // R a n d o m _ n u m b e r // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This 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 Library General Public License for more details (http://www.gnu.org). // // This file is just an adaptation of MT19937 coded by Takuji Nishimura, considering the // suggestions by Topher Cooper and Marc Rieffel in July-August 1997. It is originally a GNU // Library General Public License with the following copyright: // // "Copyright (c) 1997 Makoto Matsumoto and Takuji Nishimura. // Any feedback is very welcome. For any question, comments, // see http://www.math.keio.ac.jp/matumoto/emt.html or e-mail // matumoto@math.keio.ac.jp."
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "standard/random_number.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define STANDARD_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/standard/random_number.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area standardRandomNumber #define private_area standardRandomNumber_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Standard/Random_number");
// Initialization //-------------------------------------------------------------------------------- #undef iniStandardRandomNumber static_constant(private_area::clInitializer,goInitializer);
// Errors //---------------------------------------------------------------------------------------- namespace public_area { static_error erRandomSeedParameterMissing; }
// Constants & Variables //------------------------------------------------------------------------- dynamic_constant(clRandomGenerator,goRandomGenerator); static_constant(clMutex,goMutex);
// Static Members //-------------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// Functions Implementation //---------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// R a n d o m G e n e r a t o r Implementation //------------------------------------------------- namespace public_area { #define N 624 #define M 397 #define MATRIX_A 0x9908B0DF #define UPPER_MASK 0x80000000 #define LOWER_MASK 0x7FFFFFFF #define TEMPERING_MASK_B 0x9D2C5680 #define TEMPERING_MASK_C 0xEFC60000 #define TEMPERING_SHIFT_U(y) (y>>11) #define TEMPERING_SHIFT_S(y) (y<<7) #define TEMPERING_SHIFT_T(y) (y<<15) #define TEMPERING_SHIFT_L(y) (y>>18) //--------------------------------------------------------------------------------------Constructor /*METHOD clRandomGenerator */ /* Builds a new random generator with a given seed. If the seed is zero, the seed is built from the internal clock of the computer. */ property clRandomGenerator::clRandomGenerator(tySeed agSeed) { mag01[0]=0x0; mag01[1]=MATRIX_A; if (agSeed==0) agSeed=(tySeed)time(nil); atSeed=agSeed; mt[0]=agSeed&0xFFFFFFFF; for (mti=1;mti<N;mti++) mt[mti]=(69069*mt[mti-1])&0xFFFFFFFF; } //-------------------------------------------------------------------------------------NextCardinal /*METHOD clRandomGenerator */ /* Returns the next integer number in the random sequence. */ property tyCardinal clRandomGenerator::nextCardinal(void) { tyInteger kk; tyCardinal y;
if (mti>=N) { for (kk=0;kk<N-M;kk++) { y=(mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); mt[kk]=mt[kk+M]^(y>>1)^mag01[y&0x1]; }
for (;kk<N-1;kk++) { y=(mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); mt[kk]=mt[kk+(M-N)]^(y>>1)^mag01[y&0x1]; }
y=(mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[N-1]=mt[M-1]^(y>>1)^mag01[y&0x1]; mti=0; }
y=mt[mti++]; y^=TEMPERING_SHIFT_U(y); y^=TEMPERING_SHIFT_S(y)&TEMPERING_MASK_B; y^=TEMPERING_SHIFT_T(y)&TEMPERING_MASK_C; y^=TEMPERING_SHIFT_L(y);
return (y); } }
// I n i t i a l i z e r Implementation //--------------------------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------------Start property void clInitializer::start(void) { if (atCounter++ == 0) { try { #include <bpp/modules.hpp> /*NEED*/ registerStop(this); environment::informInitialization(goModuleName);
method_name("initializer::constructor");
erRandomSeedParameterMissing.create("The 'random_seed' parameter is missing.");
if (environment::parameters().count(clString("random_seed"))==0) send_error(erRandomSeedParameterMissing);
goRandomGenerator = new_object(clRandomGenerator(cardinal( environment::parameter(clString("random_seed")).data())));
bpp::low::string::toString(environment_private::goRandomSeed, tyInteger(goRandomGenerator->seed())); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { try { environment::informTermination(goModuleName);
delete_object(goRandomGenerator); }
initializer_catch; } }
// End //------------------------------------------------------------------------------------------- } |
|