yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

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