src/Utility/RNGXDiv.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 #ifndef RNG_XDIV_H
00012 #define RNG_XDIV_H
00013 
00014 /***********************************************************************
00015  * 
00016  * class RNGXDiv
00017  * class RNGXDivSequence : public SequenceGen<RNGXDiv>
00018  *
00019  * Simple class that implements random number generator from LANL
00020  * X-Division folks, in the range [0...1].  The first class may be
00021  * used standalone, or as a template parameter to SequenceGen.  The
00022  * second class is derived from SequenceGen, and makes it easier to
00023  * use this RNG in expressions.
00024  * Use RNGXDiv as a scalar or container element, and use
00025  * RNGXDivSequence when you need a sequence of numbers to fill a container.
00026  *
00027  ***********************************************************************/
00028 
00029 // include files
00030 #include "Utility/SequenceGen.h"
00031 
00032 
00033 class RNGXDiv {
00034 
00035 public:
00036   // return type
00037   typedef double Return_t;
00038 
00039 public:
00040   // default constructor
00041   RNGXDiv(int advance = 0) {
00042     // set the first random number, composed of
00043     // SeedUpper (top 24 bits) and SeedLower (bottom 24 bits).
00044     SeedUpper = long(FirstSeed * INV_SQR_RANMAX);
00045     SeedLower = FirstSeed - SeedUpper * SQR_RANMAX;
00046     AdvanceSeed(advance);  // advance the seed
00047   }
00048 
00049   // copy constructor
00050   RNGXDiv(const RNGXDiv& rng)
00051     : SeedLower(rng.SeedLower), SeedUpper(rng.SeedUpper),
00052       RandLower(rng.RandLower), RandUpper(rng.RandUpper) {}
00053 
00054   // destructor
00055   ~RNGXDiv(void) {}
00056 
00057   // advance indicates number of times to advance random number source
00058   inline void AdvanceSeed(int advance = 0) {
00059     for (int iadv=0; iadv<advance; iadv++)
00060       advijk();
00061     // set sequence to new source
00062     RandLower = SeedLower;
00063     RandUpper = SeedUpper;
00064   }
00065 
00066   // set seed to user-specified value, plus shift to ensure it is large
00067   inline void SetSeed(unsigned long seed) {
00068     Return_t rijk = Return_t(seed) + FirstSeed;
00069     SeedUpper = long(rijk * INV_SQR_RANMAX);
00070     SeedLower = rijk - SeedUpper * SQR_RANMAX;
00071     // set sequence to new source
00072     RandLower = SeedLower;
00073     RandUpper = SeedUpper;
00074   }
00075 
00076   // get seed value
00077   inline unsigned long GetSeed(void) const {
00078     // invert process for setting seed
00079     Return_t rijk = SeedLower + SeedUpper * SQR_RANMAX;
00080     unsigned long seed = (unsigned long) (rijk - FirstSeed);
00081     return seed;
00082   }
00083 
00084   // return the next pseudo-random number
00085   inline Return_t GetRandom(void) const {
00086     Return_t a = RandMultLower * RandLower;
00087     Return_t b = RandMultUpper * RandLower +
00088       RandMultLower * RandUpper + long(a * INV_SQR_RANMAX);
00089     RandLower = a - long(a * INV_SQR_RANMAX) * SQR_RANMAX;
00090     RandUpper = b - long(b * INV_SQR_RANMAX) * SQR_RANMAX;
00091     return ( (RandUpper * SQR_RANMAX + RandLower) * INV_RANMAX );
00092   }
00093 
00094   // pseudonym for GetRandom()
00095   inline Return_t operator()(void) const { return GetRandom(); }
00096 
00097   // conversion to Return_t, same as GetRandom()
00098   inline operator Return_t() const { return GetRandom(); }
00099 
00100   // return the period of the RNG
00101   static Return_t GetRandMax(void) { return Return_t(RANDOM_MAX); }
00102 
00103 private:
00104   double SeedLower, SeedUpper;
00105   mutable double RandLower, RandUpper;
00106 
00107   // advance random number seed for sequence
00108   inline void advijk(void) {
00109     Return_t a = SeedMultLower * SeedLower;
00110     Return_t b = (SeedMultUpper * SeedLower -
00111       long(SeedMultUpper * SeedLower * INV_SQR_RANMAX) * SQR_RANMAX) +
00112       (SeedMultLower * SeedUpper -
00113       long(SeedMultLower * SeedUpper * INV_SQR_RANMAX) * SQR_RANMAX) +
00114       long(a * INV_SQR_RANMAX);
00115     SeedLower = a - long(a * INV_SQR_RANMAX) * SQR_RANMAX;
00116     SeedUpper = b - long(b * INV_SQR_RANMAX) * SQR_RANMAX;
00117   }
00118 
00119   static const double RANDOM_MAX;
00120   static const double SQR_RANMAX;
00121   static const double INV_SQR_RANMAX;
00122   static const double INV_RANMAX;
00123   static const double SeedMultUpper;
00124   static const double SeedMultLower;
00125   static const double RandMultUpper;
00126   static const double RandMultLower;
00127   static const double FirstSeed;
00128 };
00129 
00130 RNG_BASIC_MATH(RNGXDiv)
00131 
00132 
00133 // A version of SequenceGen with extra constructors to make using this
00134 // class easier.  This is the version that people should use to fill
00135 // containers with a random number sequence in an expression.  This
00136 // class is PETE-aware via its inheritance from SequenceGen.
00137 
00138 class RNGXDivSequence : public SequenceGen<RNGXDiv> {
00139 
00140 public:
00141   // default constructor
00142   RNGXDivSequence(int advance = 0)
00143     : SequenceGen<RNGXDiv>(RNGXDiv(advance)) {}
00144 
00145   // copy constructor
00146   RNGXDivSequence(const RNGXDivSequence& rngseq)
00147     : SequenceGen<RNGXDiv>(rngseq.getGenerator()) {}
00148 
00149   // destructor
00150   ~RNGXDivSequence(void) {}
00151 
00152   // wrappers around RNG generator functions
00153   inline void     AdvanceSeed(int adv = 0) { getGenerator().AdvanceSeed(adv); }
00154   inline void     SetSeed(unsigned long seed) { getGenerator().SetSeed(seed); }
00155   inline unsigned long GetSeed(void) const { return getGenerator().GetSeed(); }
00156   inline Return_t GetRandom(void) { return getGenerator().GetRandom(); }
00157   inline Return_t operator()(void) { return getGenerator().GetRandom(); }
00158   static Return_t GetRandMax(void) { return RNGXDiv::GetRandMax(); }
00159 };
00160 
00161 
00162 #endif // RNG_XDIV_H
00163 
00164 /***************************************************************************
00165  * $RCSfile: RNGXDiv.h,v $   $Author: adelmann $
00166  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00167  * IPPL_VERSION_ID: $Id: RNGXDiv.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00168  ***************************************************************************/
00169 

Generated on Mon Jan 16 13:23:59 2006 for IPPL by  doxygen 1.4.6