00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef LUX_RANDOM_H
00036 #define LUX_RANDOM_H
00037
00038 #include "lux.h"
00039
00040 #include <boost/thread/tss.hpp>
00041
00042 namespace lux
00043 {
00044 void *AllocAligned(size_t size);
00045 void FreeAligned(void *);
00046 }
00047
00048 #define LCG(n) ((69069UL * n) & 0xffffffffUL)
00049 #define MASK 0xffffffffUL
00050
00051 #define RAN_BUFFER_AMOUNT 2048
00052
00053 namespace lux
00054 {
00055
00056 namespace random
00057 {
00058
00059 class RandomGenerator
00060 {
00061 public:
00062 RandomGenerator() {
00063 buf = (unsigned long int *)lux::AllocAligned(
00064 RAN_BUFFER_AMOUNT * sizeof(unsigned long int));
00065 bufid = RAN_BUFFER_AMOUNT;
00066 }
00067
00068 ~RandomGenerator() { lux::FreeAligned(buf); }
00069
00070 void taus113_set(unsigned long int s) {
00071 if (!s) s = 1UL;
00072
00073 z1 = LCG (s); if (z1 < 2UL) z1 += 2UL;
00074 z2 = LCG (z1); if (z2 < 8UL) z2 += 8UL;
00075 z3 = LCG (z2); if (z3 < 16UL) z3 += 16UL;
00076 z4 = LCG (z3); if (z4 < 128UL) z4 += 128UL;
00077
00078
00079 for(int i=0; i<10; i++) nobuf_generateUInt();
00080 }
00081
00082 inline unsigned long nobuf_generateUInt() {
00083 const unsigned long b1 = ((((z1 << 6UL) & MASK) ^ z1) >> 13UL);
00084 z1 = ((((z1 & 4294967294UL) << 18UL) & MASK) ^ b1);
00085
00086 const unsigned long b2 = ((((z2 << 2UL) & MASK) ^ z2) >> 27UL);
00087 z2 = ((((z2 & 4294967288UL) << 2UL) & MASK) ^ b2);
00088
00089 const unsigned long b3 = ((((z3 << 13UL) & MASK) ^ z3) >> 21UL);
00090 z3 = ((((z3 & 4294967280UL) << 7UL) & MASK) ^ b3);
00091
00092 const unsigned long b4 = ((((z4 << 3UL) & MASK) ^ z4) >> 12UL);
00093 z4 = ((((z4 & 4294967168UL) << 13UL) & MASK) ^ b4);
00094
00095 return (z1 ^ z2 ^ z3 ^ z4);
00096 }
00097
00098 inline unsigned long generateUInt() {
00099
00100 if(bufid == RAN_BUFFER_AMOUNT) {
00101 for(int i=0; i<RAN_BUFFER_AMOUNT; i++)
00102 buf[i] = nobuf_generateUInt();
00103 bufid = 0;
00104 }
00105
00106 unsigned long int ii = buf[bufid];
00107 bufid++;
00108 return ii;
00109 }
00110
00111 private:
00112 unsigned long int z1, z2, z3, z4;
00113 unsigned long int *buf;
00114 int bufid;
00115 };
00116
00117
00118 extern boost::thread_specific_ptr<RandomGenerator> myGen;
00119
00120 static const float invUI = ((float)1.0/(float)4294967296.0);
00121
00122 inline void init(int tn) {
00123 if(!myGen.get())
00124 myGen.reset(new RandomGenerator);
00125
00126 myGen->taus113_set(tn);
00127 }
00128
00129
00130 inline float floatValue() {
00131 return myGen->generateUInt() * invUI;
00132 }
00133 inline unsigned long uintValue() {
00134 return myGen->generateUInt();
00135 }
00136
00137 static RandomGenerator* PGen;
00138
00139 inline float floatValueP() {
00140 if(!PGen) {
00141 PGen = new RandomGenerator();
00142 PGen->taus113_set(1);
00143 }
00144 return PGen->nobuf_generateUInt() * invUI;
00145 }
00146 inline unsigned long uintValueP() {
00147 if(!PGen) {
00148 PGen = new RandomGenerator();
00149 PGen->taus113_set(1);
00150 }
00151 return PGen->nobuf_generateUInt();
00152 }
00153
00154 }
00155 }
00156
00157 #endif //LUX_RANDOM_H