|
SISCone
2.0.5
|
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 }