00001 /*************************************************************************** 00002 * Copyright (C) 1998-2009 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 "memory.h" 00039 00040 #define MASK 0xffffffffUL 00041 #define FLOATMASK 0x00ffffffUL 00042 00043 #define RAN_BUFFER_AMOUNT 2048 00044 00045 static const float invUI = (1.f / (FLOATMASK + 1UL)); 00046 00047 namespace lux 00048 { 00049 00050 class RandomGenerator 00051 { 00052 public: 00053 RandomGenerator() { 00054 buf = lux::AllocAligned<unsigned long>(RAN_BUFFER_AMOUNT); 00055 bufid = RAN_BUFFER_AMOUNT; 00056 } 00057 00058 ~RandomGenerator() { lux::FreeAligned(buf); } 00059 00060 inline void init(unsigned long tn) { 00061 taus113_set(tn); 00062 } 00063 00064 inline unsigned long uintValue() { 00065 // Repopulate buffer if necessary 00066 if (bufid == RAN_BUFFER_AMOUNT) { 00067 for(int i = 0; i < RAN_BUFFER_AMOUNT; ++i) 00068 buf[i] = nobuf_generateUInt(); 00069 bufid = 0; 00070 } 00071 00072 return buf[bufid++]; 00073 } 00074 00075 inline float floatValue() { 00076 return (uintValue() & FLOATMASK) * invUI; 00077 } 00078 00079 private: 00080 inline unsigned long LCG(const unsigned long n) { 00081 return 69069UL * n; // The result is clamped to 32 bits (long) 00082 } 00083 void taus113_set(unsigned long s) { 00084 if (!s) 00085 s = 1UL; // default seed is 1 00086 00087 z1 = LCG(s); 00088 if (z1 < 2UL) 00089 z1 += 2UL; 00090 z2 = LCG (z1); 00091 if (z2 < 8UL) 00092 z2 += 8UL; 00093 z3 = LCG (z2); 00094 if (z3 < 16UL) 00095 z3 += 16UL; 00096 z4 = LCG (z3); 00097 if (z4 < 128UL) 00098 z4 += 128UL; 00099 00100 // Calling RNG ten times to satify recurrence condition 00101 for(int i = 0; i < 10; ++i) 00102 nobuf_generateUInt(); 00103 } 00104 00105 inline unsigned long nobuf_generateUInt() { 00106 const unsigned long b1 = ((((z1 << 6UL) & MASK) ^ z1) >> 13UL); 00107 z1 = ((((z1 & 4294967294UL) << 18UL) & MASK) ^ b1); 00108 00109 const unsigned long b2 = ((((z2 << 2UL) & MASK) ^ z2) >> 27UL); 00110 z2 = ((((z2 & 4294967288UL) << 2UL) & MASK) ^ b2); 00111 00112 const unsigned long b3 = ((((z3 << 13UL) & MASK) ^ z3) >> 21UL); 00113 z3 = ((((z3 & 4294967280UL) << 7UL) & MASK) ^ b3); 00114 00115 const unsigned long b4 = ((((z4 << 3UL) & MASK) ^ z4) >> 12UL); 00116 z4 = ((((z4 & 4294967168UL) << 13UL) & MASK) ^ b4); 00117 00118 return (z1 ^ z2 ^ z3 ^ z4); 00119 } 00120 00121 unsigned long z1, z2, z3, z4; 00122 unsigned long *buf; 00123 int bufid; 00124 }; 00125 00126 namespace random { 00127 00128 static RandomGenerator* PGen; 00129 // request RN's during engine initialization (pre threads) 00130 inline unsigned long uintValueP() { 00131 if (!PGen) { 00132 PGen = new RandomGenerator(); 00133 PGen->init(1); 00134 } 00135 return PGen->uintValue(); 00136 } 00137 inline float floatValueP() { 00138 if (!PGen) { 00139 PGen = new RandomGenerator(); 00140 PGen->init(1); 00141 } 00142 return PGen->floatValue(); 00143 } 00144 00145 } // random 00146 00147 } // lux 00148 00149 #endif //LUX_RANDOM_H