00001 00009 #ifndef __SHUFFLEDRAND_H__ 00010 #define __SHUFFLEDRAND_H__ 00011 00012 #include <cassert> 00013 #include <cmath> 00014 #include <stdlib.h> 00015 00016 #ifdef ANSI_COMPATIBLE 00017 #define NO_RAND48_AVAIL 00018 #endif 00019 00020 00021 00035 template<class T> 00036 class ShuffledRandom { 00037 public: 00038 00040 static void reset() { 00041 for (int i=1; i<=197; i++) v[i]= plain_rand(); 00042 y = plain_rand(); 00043 is_initialized = true; 00044 } 00045 00047 static T next() { 00048 if (!is_initialized) reset(); 00049 int i = (int)floor(1.0 + 197.0 * y); /* Compute a random index into v */ 00050 assert(!(i > 197 || i < 1)); 00051 y = v[i]; /* Pick the number at the index */ 00052 v[i] = plain_rand(); /* Restock with new random number*/ 00053 return(y); 00054 } 00055 00057 static int default_seed; 00058 00060 static T plain_rand(); 00061 00063 static void plain_rand_seed(long int seedval); 00064 00065 private: 00066 static T y; 00067 static T v[198]; 00068 static bool is_initialized; 00069 00075 ShuffledRandom() {}; 00076 }; 00077 00078 00080 template<class T> T ShuffledRandom<T>::y; 00081 template<class T> T ShuffledRandom<T>::v[198]; 00082 template<class T> bool ShuffledRandom<T>::is_initialized=false; 00083 template<class T> int ShuffledRandom<T>::default_seed=87654321; 00084 00085 00086 template<class T> T 00087 ShuffledRandom<T>::plain_rand() 00088 { 00089 #ifdef NO_RAND48_AVAIL 00090 00096 return (rand()/(RAND_MAX+1.0)); 00097 #else 00098 return drand48(); 00099 #endif 00100 } 00101 00102 00103 00104 template<class T> void 00105 ShuffledRandom<T>::plain_rand_seed(long int seedval) 00106 { 00107 #ifdef NO_RAND48_AVAIL 00108 /* Should match the definition of plain_rand() */ 00109 srand(seedval); 00110 #else 00111 srand48(seedval); 00112 #endif 00113 } 00114 00115 00116 00118 inline double shuffled_rand() 00119 { return ShuffledRandom<double>::next(); } 00120 00121 00123 inline void shuffled_rand_reset(long int new_seed=ShuffledRandom<double>::default_seed) 00124 { 00125 ShuffledRandom<double>::plain_rand_seed(new_seed); 00126 ShuffledRandom<double>::reset(); 00127 ShuffledRandom<double>::next(); 00128 } 00129 00130 00131 #endif /* __SHUFFLEDRAND_H__ */