00001 00032 #include "linden_common.h" 00033 00034 #include "llrand.h" 00035 #include "lluuid.h" 00036 00066 // *NOTE: The system rand implementation is probably not correct. 00067 #define LL_USE_SYSTEM_RAND 0 00068 00069 #if LL_USE_SYSTEM_RAND 00070 #include <cstdlib> 00071 #endif 00072 00073 #if LL_USE_SYSTEM_RAND 00074 class LLSeedRand 00075 { 00076 public: 00077 LLSeedRand() 00078 { 00079 #if LL_WINDOWS 00080 srand(LLUUID::getRandomSeed()); 00081 #else 00082 srand48(LLUUID::getRandomSeed()); 00083 #endif 00084 } 00085 }; 00086 static LLSeedRand sRandomSeeder; 00087 inline F64 ll_internal_random_double() 00088 { 00089 #if LL_WINDOWS 00090 return (F64)rand() / (F64)RAND_MAX; 00091 #else 00092 return drand48(); 00093 #endif 00094 } 00095 inline F32 ll_internal_random_float() 00096 { 00097 #if LL_WINDOWS 00098 return (F32)rand() / (F32)RAND_MAX; 00099 #else 00100 return (F32)drand48(); 00101 #endif 00102 } 00103 #else 00104 static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); 00105 inline F64 ll_internal_random_double() 00106 { 00107 // *HACK: Through experimentation, we have found that dual core 00108 // CPUs (or at least multi-threaded processes) seem to 00109 // occasionally give an obviously incorrect random number -- like 00110 // 5^15 or something. Sooooo, clamp it as described above. 00111 F64 rv = gRandomGenerator(); 00112 if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0); 00113 return rv; 00114 } 00115 00116 inline F32 ll_internal_random_float() 00117 { 00118 // The clamping rules are described above. 00119 F32 rv = (F32)gRandomGenerator(); 00120 if(!((rv >= 0.0f) && (rv < 1.0f))) return fmod(rv, 1.f); 00121 return rv; 00122 } 00123 #endif 00124 00125 S32 ll_rand() 00126 { 00127 return ll_rand(RAND_MAX); 00128 } 00129 00130 S32 ll_rand(S32 val) 00131 { 00132 // The clamping rules are described above. 00133 S32 rv = (S32)(ll_internal_random_double() * val); 00134 if(rv == val) return 0; 00135 return rv; 00136 } 00137 00138 F32 ll_frand() 00139 { 00140 return ll_internal_random_float(); 00141 } 00142 00143 F32 ll_frand(F32 val) 00144 { 00145 // The clamping rules are described above. 00146 F32 rv = ll_internal_random_float() * val; 00147 if(val > 0) 00148 { 00149 if(rv >= val) return 0.0f; 00150 } 00151 else 00152 { 00153 if(rv <= val) return 0.0f; 00154 } 00155 return rv; 00156 } 00157 00158 F64 ll_drand() 00159 { 00160 return ll_internal_random_double(); 00161 } 00162 00163 F64 ll_drand(F64 val) 00164 { 00165 // The clamping rules are described above. 00166 F64 rv = ll_internal_random_double() * val; 00167 if(val > 0) 00168 { 00169 if(rv >= val) return 0.0; 00170 } 00171 else 00172 { 00173 if(rv <= val) return 0.0; 00174 } 00175 return rv; 00176 }