SISCone  2.0.5
siscone/ranlux.cpp
00001 // file: ranlux.xpp
00002 #include "ranlux.h"
00003 #include <stdlib.h>
00004 #include <stdio.h>
00005 
00006 /* This is a lagged fibonacci generator with skipping developed by Luescher.
00007    The sequence is a series of 24-bit integers, x_n, 
00008 
00009    x_n = d_n + b_n
00010 
00011    where d_n = x_{n-10} - x_{n-24} - c_{n-1}, b_n = 0 if d_n >= 0 and
00012    b_n = 2^24 if d_n < 0, c_n = 0 if d_n >= 0 and c_n = 1 if d_n < 0,
00013    where after 24 samples a group of p integers are "skipped", to
00014    reduce correlations. By default p = 199, but can be increased to
00015    365.
00016 
00017    The period of the generator is around 10^171. 
00018 
00019    From: M. Luescher, "A portable high-quality random number generator
00020    for lattice field theory calculations", Computer Physics
00021    Communications, 79 (1994) 100-110.
00022 
00023    Available on the net as hep-lat/9309020 at http://xxx.lanl.gov/
00024 
00025    See also,
00026 
00027    F. James, "RANLUX: A Fortran implementation of the high-quality
00028    pseudo-random number generator of Luscher", Computer Physics
00029    Communications, 79 (1994) 111-114
00030 
00031    Kenneth G. Hamilton, F. James, "Acceleration of RANLUX", Computer
00032    Physics Communications, 101 (1997) 241-248
00033 
00034    Kenneth G. Hamilton, "Assembler RANLUX for PCs", Computer Physics
00035    Communications, 101 (1997) 249-253  */
00036 
00037 namespace siscone{
00038 
00039 static const unsigned long int mask_lo = 0x00ffffffUL;  // 2^24 - 1
00040 static const unsigned long int mask_hi = ~0x00ffffffUL;
00041 static const unsigned long int two24 = 16777216;        // 2^24
00042 
00043 
00044 // internal generator structure
00045 //------------------------------
00046 typedef struct {
00047   unsigned int i;
00048   unsigned int j;
00049   unsigned int n;
00050   unsigned int skip;
00051   unsigned int carry;
00052   unsigned long int u[24];
00053 } ranlux_state_t;
00054 
00055 
00056 // internal generator state
00057 //--------------------------
00058 ranlux_state_t local_ranlux_state;
00059 
00060 
00061 // incrementation of the generator state
00062 //---------------------------------------
00063 static inline unsigned long int increment_state(){
00064   unsigned int i = local_ranlux_state.i;
00065   unsigned int j = local_ranlux_state.j;
00066   long int delta = local_ranlux_state.u[j] - local_ranlux_state.u[i] 
00067     - local_ranlux_state.carry;
00068 
00069   if (delta & mask_hi){
00070     local_ranlux_state.carry = 1;
00071     delta &= mask_lo;
00072   } else {
00073     local_ranlux_state.carry = 0;
00074   }
00075 
00076   local_ranlux_state.u[i] = delta;
00077   
00078   if (i==0)
00079     i = 23;
00080   else
00081     i--;
00082 
00083   local_ranlux_state.i = i;
00084 
00085   if (j == 0)
00086     j = 23;
00087   else
00088     j--;
00089 
00090   local_ranlux_state.j = j;
00091 
00092   return delta;
00093 }
00094 
00095 
00096 // set generator state
00097 //---------------------
00098 static void ranlux_set(unsigned long int s){
00099   int i;
00100   long int seed;
00101   
00102   if (s==0)
00103     s = 314159265;      /* default seed is 314159265 */
00104   
00105   seed = s;
00106   
00107   /* This is the initialization algorithm of F. James, widely in use
00108      for RANLUX. */
00109 
00110   for (i=0;i<24;i++){
00111     unsigned long int k = seed/53668;
00112     seed = 40014*(seed-k*53668)-k*12211;
00113     if (seed<0){
00114       seed += 2147483563;
00115     }
00116     local_ranlux_state.u[i] = seed%two24;
00117   }
00118 
00119   local_ranlux_state.i = 23;
00120   local_ranlux_state.j = 9;
00121   local_ranlux_state.n = 0;
00122   local_ranlux_state.skip = 389-24; // 389 => best decorrelation
00123 
00124   if (local_ranlux_state.u[23]&mask_hi){
00125     local_ranlux_state.carry = 1;
00126   } else {
00127     local_ranlux_state.carry = 0;
00128   }
00129 }
00130 
00131 
00132 // generator initialization
00133 //--------------------------
00134 void ranlux_init(){
00135   // seed the generator
00136   ranlux_set(0);
00137 }
00138 
00139 
00140 // get random number
00141 //-------------------
00142 unsigned long int ranlux_get(){
00143   const unsigned int skip = local_ranlux_state.skip;
00144   unsigned long int r = increment_state();
00145   
00146   local_ranlux_state.n++;
00147 
00148   if (local_ranlux_state.n == 24){
00149     unsigned int i;
00150     local_ranlux_state.n = 0;
00151     for (i = 0; i < skip; i++)
00152       increment_state();
00153   }
00154 
00155   return r;
00156 }
00157 
00158 // print generator state
00159 //-----------------------
00160 void ranlux_print_state(){
00161   size_t i;
00162   unsigned char *p = (unsigned char *) (&local_ranlux_state);
00163   const size_t n = sizeof (ranlux_state_t);
00164 
00165   for (i=0;i<n;i++){
00166     /* FIXME: we're assuming that a char is 8 bits */
00167     printf("%.2x", *(p+i));
00168   }
00169 }
00170 
00171 }
The SISCone project has been developed by Gavin Salam and Gregory Soyez
Documentation generated on Mon Jun 4 2012 18:23:38 for SISCone by  Doxygen 1.7.6.1