yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1 2#include "slang-random-generator.h" 3 4namespace Slang 5{ 6 7/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! RandomGenerator !!!!!!!!!!!!!!!!!!!!!!!! */ 8 9float RandomGenerator ::nextUnitFloat32 () 10{ 11int32_t intValue = nextInt32 (); 12return (intValue & 0x7fffffff )* (1.0f /float (0x7fffffff )); 13} 14 15bool RandomGenerator ::nextBool () 16{ 17uint32_t bits = uint32_t (nextInt32 ()); 18 19// Xor together all bits in each byte 20bits = ((bits & 0xaaaaaaaa ) >>1 ) ^ (bits & 0x55555555 ); 21bits = ((bits & 0x44444444 ) >>2 ) ^ (bits & 0x11111111 ); 22bits = ((bits & 0x10101010 ) >>4 ) ^ (bits & 0x01010101 ); 23 24// In effect is the xor of all the bits of the original last byte 25return (bits & 1 )!= 0 ; 26} 27 28int64_t RandomGenerator ::nextInt64 () 29{ 30const int32_t high = nextInt32 (); 31const int32_t low = nextInt32 (); 32 33return (int64_t (high ) <<32 ) |low ; 34} 35 36uint32_t RandomGenerator ::nextUInt32InRange (uint32_t min ,uint32_t max ) 37{ 38// Make sure max is at least in 39max = (max >=min ) ?max :min ; 40 41// Make 64 bit so can be lazier than having to take care of 32 bit overflow/underflow issues 42uint32_t diff = max - min ; 43if (diff <=1 ) 44 { 45return min ; 46 } 47return (nextUInt32 () %diff )+ min ; 48} 49 50 51int32_t RandomGenerator ::nextInt32InRange (int32_t min ,int32_t max ) 52{ 53// Make sure max is at least in 54max = (max >=min ) ?max :min ; 55 56// Make 64 bit so can be lazier than having to take care of 32 bit overflow/underflow issues 57uint32_t diff = uint32_t (int64_t (max )- int64_t (min )); 58if (diff <=1 ) 59 { 60return min ; 61 } 62return int32_t (int64_t (nextUInt32 () %diff )+ min ); 63} 64 65int64_t RandomGenerator ::nextInt64InRange (int64_t min ,int64_t max ) 66{ 67int64_t diff = max - min ; 68if (diff <=1 ) 69 { 70return min ; 71 } 72return (nextPositiveInt64 () %diff )+ min ; 73} 74 75static uint8_t * _nextData (RandomGenerator * rand ,uint8_t * out ,size_t size ) 76{ 77if (size ) 78 { 79SLANG_ASSERT (size <=4 ); 80uint32_t v = uint32_t (rand -> nextInt32 ()); 81uint8_t * dst = (uint8_t * )out ; 82for (size_t i = 0 ;i < size ;++ i ) 83 { 84dst [i ]= uint8_t (v ); 85v >>=8 ; 86 } 87 } 88return out + size ; 89} 90 91void RandomGenerator ::nextData (void * out ,size_t size ) 92{ 93uint8_t * dst = (uint8_t * )out ; 94uint8_t * const end = dst + size ; 95 96// For short runs just output 97if (size <=4 ) 98 { 99_nextData (this ,dst ,size ); 100return ; 101 } 102 103 { 104const size_t preAlign = size_t (((size_t (dst )+ 3 )& ~size_t (3 ))- size_t (dst )); 105dst = _nextData (this ,dst ,preAlign ); 106 } 107 108// Check invariants 109SLANG_ASSERT ((size_t (dst )& 3 )== 0 && end >=dst ); 110 111 { 112const size_t middleCount = size_t (end - dst ) >>2 ; 113if (middleCount ) 114 { 115nextInt32s ((int32_t * )dst ,middleCount ); 116dst += middleCount * sizeof (int32_t ); 117 } 118 } 119 120// Check invariants 121SLANG_ASSERT ((size_t (dst )& 3 )== 0 && end >=dst ); 122 123_nextData (this ,dst ,size_t (end - dst )); 124} 125 126/* static */ RandomGenerator * RandomGenerator ::create (int32_t seed ) 127{ 128return new DefaultRandomGenerator (seed ); 129} 130 131/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! Mt19937RandomGenerator !!!!!!!!!!!!!!!!!!!!!!!! */ 132 133Mt19937RandomGenerator ::Mt19937RandomGenerator () 134{ 135reset (21452 ); 136} 137 138Mt19937RandomGenerator ::Mt19937RandomGenerator (const ThisType & rhs ) 139{ 140* this = rhs ; 141} 142 143Mt19937RandomGenerator ::Mt19937RandomGenerator (int32_t seed ) 144{ 145reset (seed ); 146} 147 148void Mt19937RandomGenerator ::_generate () 149{ 150const uint32_t xorValue = 2567483615u ; 151for (int i = 0 ;i < kNumEntries - 1 ;++ i ) 152 { 153const uint32_t y = (m_mt [i ]& 0x80000000 )+ (m_mt [i + 1 ]& 0x7fffffff ); 154 155// o = (i + 397) % kNumEntries 156int32_t o = i + 397 ; 157o = (o >=kNumEntries ) ? (o - kNumEntries ) :o ; 158 159m_mt [i ]= m_mt [o ] ^ (y >>1 ); 160// If y is odd 161if (y & 1 ) 162 { 163m_mt [i ]= m_mt [i ] ^xorValue ; 164 } 165 } 166 167// Last 168 { 169const int i = kNumEntries - 1 ; 170const uint32_t y = (m_mt [i ]& 0x80000000 )+ (m_mt [0 ]& 0x7fffffff ); 171const int32_t o = ((i + 397 )- kNumEntries ); 172 173m_mt [i ]= m_mt [o ] ^ (y >>1 ); 174// If y is odd 175if (y & 1 ) 176 { 177m_mt [i ]= m_mt [i ] ^xorValue ; 178 } 179 } 180 181m_index = 0 ; 182} 183 184void Mt19937RandomGenerator ::reset (int32_t seedIn ) 185{ 186m_index = 0 ; 187m_mt [0 ]= uint32_t (seedIn ); 188for (int i = 1 ;i < kNumEntries ;++ i ) 189 { 190m_mt [i ]= (1812433253 * (m_mt [i - 1 ] ^ (m_mt [i - 1 ] >>30 ))+ i ); 191 } 192} 193 194int32_t Mt19937RandomGenerator ::nextInt32 () 195{ 196if (m_index >=kNumEntries ) 197 { 198_generate (); 199 } 200 201uint32_t y = m_mt [m_index ++ ]; 202y = y ^ (y >>11 ); 203y = y ^ ((y <<7 )& uint32_t (0x9d2c5680u )); 204y = y ^ ((y <<15 )& uint32_t (0xefc6000u )); 205y = y ^ (y >>18 ); 206 207return int32_t (y ); 208} 209 210void Mt19937RandomGenerator ::nextInt32s (int32_t * dst ,size_t count ) 211{ 212while (count ) 213 { 214if (m_index >=kNumEntries ) 215 { 216_generate (); 217 } 218 219const size_t remaining = kNumEntries - m_index ; 220const size_t run = (count < remaining ) ?count :remaining ; 221 222const uint32_t * src = m_mt + m_index ; 223for (size_t i = 0 ;i < run ;i ++ ) 224 { 225uint32_t y = src [i ]; 226y = y ^ (y >>11 ); 227y = y ^ ((y <<7 )& uint32_t (0x9d2c5680u )); 228y = y ^ ((y <<15 )& uint32_t (0xefc6000u )); 229y = y ^ (y >>18 ); 230 231dst [i ]= int32_t (y ); 232 } 233 234m_index += int (run ); 235dst += run ; 236count -= run ; 237 } 238} 239 240}// namespace Slang