Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
Pcg32.h
Go to the documentation of this file.
1#pragma once
2
4#include "Math/hash.h"
5
6#include <Common/primitive_type.h>
7
8namespace ph::math
9{
10
11/*
12 * The following PCG implementation is a version adapted for use in Photon. Most algorithmic parts
13 * are left as-is the original reference implementation by Melissa O'Neill and other sources (listed
14 * in the documentation of `Pcg32` class).
15 *
16 * The PCG Random Number Generator was developed by Melissa O'Neill <oneill@pcg-random.org>.
17 *
18 * Licensed under the Apache License, Version 2.0 (the "License");
19 * you may not use this file except in compliance with the License.
20 * You may obtain a copy of the License at
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Unless required by applicable law or agreed to in writing, software
25 * distributed under the License is distributed on an "AS IS" BASIS,
26 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 * See the License for the specific language governing permissions and
28 * limitations under the License.
29 *
30 * For additional information about the PCG random number generation scheme,
31 * including its license and other licensing options, visit
32 *
33 * http://www.pcg-random.org
34 */
35
43class Pcg32 final : public TUniformRandomBitGenerator<Pcg32, uint32>
44{
45public:
47
48 explicit Pcg32(uint64 initialSequence);
49
54 Pcg32(uint64 initialSequence, uint64 initialState);
55
56 uint32 impl_generate();
57 void impl_jumpAhead(uint64 distance);
58
59private:
60 uint32 generateUInt32();
61
62 inline static constexpr uint64 DEFAULT_STATE = 0x853C49E6748FEA9Bull;
63 inline static constexpr uint64 DEFAULT_STREAM_ID = 0xDA3E39CB94B95BDBull;
64 inline static constexpr uint64 MULTIPLIER = 0x5851F42D4C957F2Dull;
65
66 uint64 m_state = DEFAULT_STATE;
67
69 uint64 m_increment = DEFAULT_STREAM_ID;
70};
71
72inline Pcg32::Pcg32(const uint64 initialSequence)
73 : Pcg32(initialSequence, moremur_bit_mix_64(initialSequence))
74{}
75
76inline Pcg32::Pcg32(const uint64 initialSequence, const uint64 initialState)
77 : Pcg32()
78{
79 m_state = 0u;
80
81 // Ensure `m_increment` is odd
82 m_increment = (initialSequence << 1u) | 1u;
83
84 generateUInt32();
85 m_state += initialState;
86 generateUInt32();
87}
88
89inline uint32 Pcg32::impl_generate()
90{
91 return generateUInt32();
92}
93
94inline void Pcg32::impl_jumpAhead(const uint64 distance)
95{
96 uint64 curMult = MULTIPLIER;
97 uint64 curPlus = m_increment;
98 uint64 accMult = 1u;
99 uint64 accPlus = 0u;
100 uint64 delta = distance;
101 while(delta > 0)
102 {
103 if(delta & 1)
104 {
105 accMult *= curMult;
106 accPlus = accPlus * curMult + curPlus;
107 }
108 curPlus = (curMult + 1) * curPlus;
109 curMult *= curMult;
110 delta /= 2;
111 }
112 m_state = accMult * m_state + accPlus;
113}
114
115inline uint32 Pcg32::generateUInt32()
116{
117 // Linear congruential generator
118 const uint64 oldState = m_state;
119 m_state = oldState * MULTIPLIER + m_increment;
120
121 uint32 xorShifted = static_cast<uint32>(((oldState >> 18u) ^ oldState) >> 27u);
122 uint32 rot = static_cast<uint32>(oldState >> 59u);
123 return (xorShifted >> rot) | (xorShifted << ((~rot + 1u) & 31));
124}
125
126}// end namespace ph::math
PCG-32 generator. This is the pcg32 generator in O'Neill's original pcg-cpp implementation....
Definition Pcg32.h:44
void impl_jumpAhead(uint64 distance)
Definition Pcg32.h:94
Pcg32(uint64 initialSequence)
Definition Pcg32.h:72
uint32 impl_generate()
Definition Pcg32.h:89
PH_DEFINE_INLINE_RULE_OF_5_MEMBERS(Pcg32)
Definition TUniformRandomBitGenerator.h:30
Math functions and utilities.
Definition TransformInfo.h:10
uint64 moremur_bit_mix_64(uint64 v)
A MurmurHash3-style bit mixer that outperforms the original by quite some margin. 64-bit version.
Definition hash.ipp:104