mRandom.cpp
Engine/source/math/mRandom.cpp
Public Variables
Public Functions
Detailed Description
Public Variables
MRandomLCG gRandGen
U32 gRandGenSeed
U32 msSeed
Public Functions
generateSeed()
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "math/mRandom.h" 26#include "core/util/journal/journal.h" 27 28MRandomLCG gRandGen; 29U32 gRandGenSeed = 1376312589; 30 31void MRandomLCG::setGlobalRandSeed(U32 seed) 32{ 33 if (Journal::IsPlaying()) 34 Journal::Read(&gRandGenSeed); 35 else 36 { 37 gRandGenSeed = seed; 38 if (Journal::IsRecording()) 39 Journal::Write(gRandGenSeed); 40 } 41 42 //now actually set the seed 43 gRandGen.setSeed(gRandGenSeed); 44} 45 46static U32 msSeed = 1376312589; 47 48inline U32 generateSeed() 49{ 50 // A very, VERY crude LCG but good enough to generate 51 // a nice range of seed values 52 msSeed = (msSeed * 0x015a4e35L) + 1; 53 msSeed = (msSeed>>16)&0x7fff; 54 return (msSeed); 55} 56 57//-------------------------------------- 58void MRandomGenerator::setSeed() 59{ 60 setSeed(generateSeed()); 61} 62 63 64//-------------------------------------- 65const S32 MRandomLCG::msQuotient = S32_MAX / 16807L; 66const S32 MRandomLCG::msRemainder = S32_MAX % 16807L; 67 68 69//-------------------------------------- 70MRandomLCG::MRandomLCG() 71{ 72 setSeed(generateSeed()); 73} 74 75MRandomLCG::MRandomLCG(S32 s) 76{ 77 setSeed(s); 78} 79 80 81//-------------------------------------- 82void MRandomLCG::setSeed(S32 s) 83{ 84 mSeed = s; 85} 86 87 88//-------------------------------------- 89U32 MRandomLCG::randI() 90{ 91 if ( mSeed <= msQuotient ) 92 mSeed = (mSeed * 16807) % S32_MAX; 93 else 94 { 95 S32 high_part = mSeed / msQuotient; 96 S32 low_part = mSeed % msQuotient; 97 98 S32 test = (16807 * low_part) - (msRemainder * high_part); 99 100 if ( test > 0 ) 101 mSeed = test; 102 else 103 mSeed = test + S32_MAX; 104 105 } 106 return mSeed; 107} 108 109 110 111//-------------------------------------- 112MRandomR250::MRandomR250() 113{ 114 setSeed(generateSeed()); 115} 116 117MRandomR250::MRandomR250(S32 s) 118{ 119 setSeed(s); 120} 121 122 123//-------------------------------------- 124void MRandomR250::setSeed(S32 s) 125{ 126 mSeed = s; 127 MRandomLCG lcg( s ); 128 mIndex = 0; 129 130 S32 j; 131 for (j = 0; j < 250; j++) // fill r250 buffer with bit values 132 mBuffer[j] = lcg.randI(); 133 134 for (j = 0; j < 250; j++) // set some MSBs to 1 135 if ( lcg.randI() > 0x40000000L ) 136 mBuffer[j] |= 0x80000000L; 137 138 139 U32 msb = 0x80000000; // turn on diagonal bit 140 U32 mask = 0xffffffff; // turn off the leftmost bits 141 142 for (j = 0; j < 32; j++) 143 { 144 S32 k = 7 * j + 3; // select a word to operate on 145 mBuffer[k] &= mask; // turn off bits left of the diagonal 146 mBuffer[k] |= msb; // turn on the diagonal bit 147 mask >>= 1; 148 msb >>= 1; 149 } 150} 151 152 153//-------------------------------------- 154U32 MRandomR250::randI() 155{ 156 S32 j; 157 158 // wrap pointer around 159 if ( mIndex >= 147 ) j = mIndex - 147; 160 else j = mIndex + 103; 161 162 U32 new_rand = mBuffer[ mIndex ] ^ mBuffer[ j ]; 163 mBuffer[ mIndex ] = new_rand; 164 165 // increment pointer for next time 166 if ( mIndex >= 249 ) mIndex = 0; 167 else mIndex++; 168 169 return new_rand >> 1; 170} 171 172 173