00001 /*************************************************************************** 00002 * Copyright (C) 1998-2008 by authors (see AUTHORS.txt ) * 00003 * * 00004 * This file is part of LuxRender. * 00005 * * 00006 * Lux Renderer is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 3 of the License, or * 00009 * (at your option) any later version. * 00010 * * 00011 * Lux Renderer is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 00018 * * 00019 * This project is based on PBRT ; see http://www.pbrt.org * 00020 * Lux Renderer website : http://www.luxrender.net * 00021 ***************************************************************************/ 00022 00023 // Tausworthe (taus113) random numbergenerator by radiance 00024 // Based on code from GSL (GNU Scientific Library) 00025 // MASK assures 64bit safety 00026 00027 // Usage in luxrender: 00028 // lux::random::floatValue() returns a random float 00029 // lux::random::uintValue() returns a random uint 00030 // 00031 // NOTE: calling random values outside of a renderthread will result in a crash 00032 // thread safety/uniqueness using thread specific ptr (boost) 00033 // Before renderthreads execute, use floatValueP() and uintValueP() instead. 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; // default seed is 1 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 // Calling RNG ten times to satify recurrence condition 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 // Repopulate buffer if necessary 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 // thread local pointer to boost random generator 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 // request RN's during render threads (uses per thread rangen/seed) 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 // request RN's during engine initialization (pre threads) 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 } // random 00155 } // lux 00156 00157 #endif //LUX_RANDOM_H