src/Utility/RNGXCI.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_XCI_H
00012 #define RNG_XCI_H
00013 
00014 /***********************************************************************
00015  * 
00016  * class RNGXCI
00017  * class RNGXCISequence : public SequenceGen<RNGXCI>
00018  *
00019  * RNGXCI is a simple class that implements random number generator from LANL
00020  * XCI group (Forrest Brown), in the range (0...1).  The first class is used 
00021  * as a scalar, as an element of a Field or ParticleAttrib, or as a template
00022  * parameter to SequenceGen.  The second class is derived from SequenceGen,
00023  * and makes it easier to use this RNG in an expression as a sequence of
00024  * numbers that will fill a Field or ParticleAttrib container.
00025  * Use RNGXCI as a scalar or container element, and use
00026  * RNGXCISequence when you need a sequence of numbers to fill a container.
00027  *
00028  ***********************************************************************/
00029 
00030 // include files
00031 #include "Utility/SequenceGen.h"
00032 
00033 // define type that we ensure is 8 bytes long
00034 #define LONG_IS_8_BYTES (((1L<<16)<<16)<<16)
00035 #if defined(IPPL_LONGLONG)
00036   typedef long long  RNlong;
00037 #else
00038   #if LONG_IS_8_BYTES
00039     typedef long     RNlong;
00040   #else
00041     error
00042   #endif
00043 #endif
00044 
00045 class RNGXCI {
00046 
00047 public:
00048   // return type
00049   typedef double Return_t;
00050 
00051 public:
00052   // default constructor
00053   RNGXCI(RNlong advance = 0L)
00054     : Seed(1L) { AdvanceSeed(advance); }
00055 
00056   // copy constructor
00057   RNGXCI(const RNGXCI& rng)
00058     : Seed(rng.Seed) {}
00059 
00060   // destructor
00061   ~RNGXCI(void) {}
00062 
00063   // advance seed for random number generator n times
00064   inline void AdvanceSeed(RNlong n = 0L) {
00065     //  skip ahead n RNs:   Seed*RN_MULT^n mod RN_MOD
00066     while( n<0 )  n += RN_PERIOD;  // add period till >0
00067     n &= RN_MASK;                  // mod RN_MOD
00068     RNlong  gen=1L,  g=RN_MULT;    // get gen=RN_MULT^n,  in
00069     for( ; n; n>>=1 ) {            //    log2(n) ops, not n ops !
00070       if( n&1 ) gen = gen*g & RN_MASK;
00071       g = g*g & RN_MASK;
00072     }
00073     Seed = gen*Seed & RN_MASK;
00074     return;
00075   }
00076 
00077   // set seed to user-specified value
00078   inline void SetSeed(RNlong s) {
00079     Seed = (s|1) & RN_MASK;        // must be odd to get full period
00080   }
00081 
00082   // get seed value
00083   inline RNlong GetSeed(void) const { return Seed; }
00084 
00085   // return the next pseudo-random number (from 0 ... 1)
00086   inline Return_t GetRandom(void) const {
00087     Return_t r = Seed*RN_NORM;
00088     Seed = Seed*RN_MULT & RN_MASK;
00089     return r;
00090   }
00091 
00092   // pseudonym for GetRandom()
00093   inline Return_t operator()(void) const { return GetRandom(); }
00094 
00095   // conversion to Return_t, same as GetRandom()
00096   inline operator Return_t() const { return GetRandom(); }
00097 
00098   // return the period of the RNG
00099   static Return_t GetRandMax(void) { return Return_t(RN_MASK); }
00100 
00101 private:
00102   mutable RNlong Seed;
00103 
00104   // constants for RN gen:       Seed = Seed*RN_MULT mod RN_MOD
00105   static const RNlong RN_MULT;   // 5^19 
00106   static const RNlong RN_MOD;    // 2^48 
00107   static const RNlong RN_PERIOD; // period
00108   static const double RN_NORM;   // normalize to (0,1)
00109   static const RNlong RN_MASK;   // 48-bit mask
00110 };
00111 
00112 RNG_BASIC_MATH(RNGXCI)
00113 
00114 
00115 // A version of SequenceGen with extra constructors to make using this
00116 // class easier.  This is the version that people should use to fill
00117 // containers with a random number sequence in an expression.  This
00118 // class is PETE-aware via its inheritance from SequenceGen.
00119 
00120 class RNGXCISequence : public SequenceGen<RNGXCI> {
00121 
00122 public:
00123   // default constructor
00124   RNGXCISequence(int advance = 0)
00125     : SequenceGen<RNGXCI>(RNGXCI(advance)) {}
00126 
00127   // copy constructor
00128   RNGXCISequence(const RNGXCISequence& rngseq)
00129     : SequenceGen<RNGXCI>(rngseq.getGenerator()) {}
00130 
00131   // destructor
00132   ~RNGXCISequence(void) {}
00133 
00134   // wrappers around RNG generator functions
00135   inline void AdvanceSeed(RNlong adv = 0L) {
00136     getGenerator().AdvanceSeed(adv);
00137   }
00138   inline void     SetSeed(RNlong seed) { getGenerator().SetSeed(seed); }
00139   inline RNlong GetSeed(void) const { return getGenerator().GetSeed(); }
00140   inline Return_t GetRandom(void) { return getGenerator().GetRandom(); }
00141   inline Return_t operator()(void) { return getGenerator().GetRandom(); }
00142   static Return_t GetRandMax(void) { return RNGXCI::GetRandMax(); }
00143 };
00144 
00145 
00146 #endif // RNG_XCI_H
00147 
00148 /***************************************************************************
00149  * $RCSfile: RNGXCI.h,v $   $Author: adelmann $
00150  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00151  * IPPL_VERSION_ID: $Id: RNGXCI.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00152  ***************************************************************************/
00153 

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