com.wallstop-studios.unity-helpers 2.0.4 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Docs/DATA_STRUCTURES.md +7 -7
- package/Docs/EFFECTS_SYSTEM.md +836 -8
- package/Docs/EFFECTS_SYSTEM_TUTORIAL.md +77 -18
- package/Docs/HULLS.md +2 -2
- package/Docs/ILIST_SORTING_PERFORMANCE.md +92 -0
- package/Docs/ILIST_SORTING_PERFORMANCE.md.meta +7 -0
- package/Docs/INDEX.md +10 -1
- package/Docs/Images/random_generators.svg +7 -7
- package/Docs/RANDOM_PERFORMANCE.md +18 -15
- package/Docs/REFLECTION_HELPERS.md +1 -1
- package/Docs/RELATIONAL_COMPONENTS.md +51 -6
- package/Docs/SERIALIZATION.md +1 -1
- package/Docs/SINGLETONS.md +2 -2
- package/Docs/SPATIAL_TREES_2D_GUIDE.md +3 -3
- package/Docs/SPATIAL_TREES_3D_GUIDE.md +3 -3
- package/Docs/SPATIAL_TREE_2D_PERFORMANCE.md +64 -64
- package/Docs/SPATIAL_TREE_3D_PERFORMANCE.md +64 -64
- package/Docs/SPATIAL_TREE_SEMANTICS.md +7 -7
- package/Editor/Core/Helper/AnimationEventHelpers.cs +1 -1
- package/Editor/CustomDrawers/WShowIfPropertyDrawer.cs +131 -41
- package/Editor/Utils/ScriptableObjectSingletonCreator.cs +175 -18
- package/README.md +42 -18
- package/Runtime/Core/Extension/IListExtensions.cs +720 -12
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +2 -3
- package/Runtime/Core/Random/AbstractRandom.cs +52 -5
- package/Runtime/Core/Random/DotNetRandom.cs +3 -3
- package/Runtime/Core/Random/FlurryBurstRandom.cs +285 -0
- package/Runtime/Core/Random/FlurryBurstRandom.cs.meta +3 -0
- package/Runtime/Core/Random/IllusionFlow.cs +3 -3
- package/Runtime/Core/Random/LinearCongruentialGenerator.cs +3 -3
- package/Runtime/Core/Random/PcgRandom.cs +6 -6
- package/Runtime/Core/Random/PhotonSpinRandom.cs +387 -0
- package/Runtime/Core/Random/PhotonSpinRandom.cs.meta +3 -0
- package/Runtime/Core/Random/RomuDuo.cs +3 -3
- package/Runtime/Core/Random/SplitMix64.cs +3 -3
- package/Runtime/Core/Random/SquirrelRandom.cs +6 -4
- package/Runtime/Core/Random/StormDropRandom.cs +271 -0
- package/Runtime/Core/Random/StormDropRandom.cs.meta +3 -0
- package/Runtime/Core/Random/UnityRandom.cs +3 -3
- package/Runtime/Core/Random/WyRandom.cs +6 -4
- package/Runtime/Core/Random/XorShiftRandom.cs +3 -3
- package/Runtime/Core/Random/XoroShiroRandom.cs +3 -3
- package/Runtime/Tags/Attribute.cs +144 -24
- package/Runtime/Tags/AttributeEffect.cs +119 -16
- package/Runtime/Tags/AttributeMetadataCache.cs +312 -3
- package/Runtime/Tags/AttributeModification.cs +59 -29
- package/Runtime/Tags/AttributesComponent.cs +20 -0
- package/Runtime/Tags/EffectBehavior.cs +171 -0
- package/Runtime/Tags/EffectBehavior.cs.meta +4 -0
- package/Runtime/Tags/EffectHandle.cs +5 -0
- package/Runtime/Tags/EffectHandler.cs +385 -39
- package/Runtime/Tags/EffectStackKey.cs +79 -0
- package/Runtime/Tags/EffectStackKey.cs.meta +4 -0
- package/Runtime/Tags/PeriodicEffectDefinition.cs +102 -0
- package/Runtime/Tags/PeriodicEffectDefinition.cs.meta +4 -0
- package/Runtime/Tags/PeriodicEffectRuntimeState.cs +40 -0
- package/Runtime/Tags/PeriodicEffectRuntimeState.cs.meta +4 -0
- package/Samples~/DI - Zenject/README.md +0 -2
- package/Tests/Editor/Attributes/WShowIfPropertyDrawerTests.cs +285 -0
- package/Tests/Editor/Attributes/WShowIfPropertyDrawerTests.cs.meta +11 -0
- package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +2 -2
- package/Tests/Editor/Tags/AttributeMetadataCacheTests.cs +192 -0
- package/Tests/Editor/Tags/AttributeMetadataCacheTests.cs.meta +11 -0
- package/{node_modules.meta → Tests/Editor/Tags.meta} +1 -1
- package/Tests/Editor/Utils/ScriptableObjectSingletonTests.cs +41 -0
- package/Tests/Runtime/Extensions/IListExtensionTests.cs +187 -1
- package/Tests/Runtime/Helper/ObjectsTests.cs +3 -3
- package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +2 -2
- package/Tests/Runtime/Performance/IListSortingPerformanceTests.cs +346 -0
- package/Tests/Runtime/Performance/IListSortingPerformanceTests.cs.meta +11 -0
- package/Tests/Runtime/Performance/RandomPerformanceTests.cs +3 -0
- package/Tests/Runtime/Random/FlurryBurstRandomTests.cs +12 -0
- package/Tests/Runtime/Random/FlurryBurstRandomTests.cs.meta +3 -0
- package/Tests/Runtime/Random/PhotonSpinRandomTests.cs +12 -0
- package/Tests/Runtime/Random/PhotonSpinRandomTests.cs.meta +3 -0
- package/Tests/Runtime/Random/RandomProtoSerializationTests.cs +14 -0
- package/Tests/Runtime/Random/RandomTestBase.cs +39 -4
- package/Tests/Runtime/Random/StormDropRandomTests.cs +12 -0
- package/Tests/Runtime/Random/StormDropRandomTests.cs.meta +3 -0
- package/Tests/Runtime/Serialization/JsonSerializationTest.cs +4 -3
- package/Tests/Runtime/Serialization/ProtoInterfaceResolutionEdgeTests.cs +2 -2
- package/Tests/Runtime/Serialization/ProtoRootRegistrationTests.cs +1 -1
- package/Tests/Runtime/Serialization/ProtoSerializeBehaviorTests.cs +1 -1
- package/Tests/Runtime/Tags/AttributeEffectTests.cs +135 -0
- package/Tests/Runtime/Tags/AttributeEffectTests.cs.meta +3 -0
- package/Tests/Runtime/Tags/AttributeModificationTests.cs +137 -0
- package/Tests/Runtime/Tags/AttributeTests.cs +192 -0
- package/Tests/Runtime/Tags/AttributeTests.cs.meta +3 -0
- package/Tests/Runtime/Tags/EffectBehaviorTests.cs +184 -0
- package/Tests/Runtime/Tags/EffectBehaviorTests.cs.meta +3 -0
- package/Tests/Runtime/Tags/EffectHandlerTests.cs +618 -0
- package/Tests/Runtime/Tags/Helpers/RecordingEffectBehavior.cs +89 -0
- package/Tests/Runtime/Tags/Helpers/RecordingEffectBehavior.cs.meta +4 -0
- package/Tests/Runtime/Tags/PeriodicEffectDefinitionSerializationTests.cs +92 -0
- package/Tests/Runtime/Tags/PeriodicEffectDefinitionSerializationTests.cs.meta +3 -0
- package/package.json +1 -1
- package/scripts/lint-doc-links.ps1 +156 -11
- package/Tests/Runtime/Tags/AttributeDataTests.cs +0 -312
- /package/Tests/Runtime/Tags/{AttributeDataTests.cs.meta → AttributeModificationTests.cs.meta} +0 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Core.Random
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Runtime.Serialization;
|
|
5
|
+
using System.Text.Json.Serialization;
|
|
6
|
+
using Extension;
|
|
7
|
+
using ProtoBuf;
|
|
8
|
+
using WallstopStudios.UnityHelpers.Core.Helper;
|
|
9
|
+
using WallstopStudios.UnityHelpers.Utils;
|
|
10
|
+
|
|
11
|
+
/// <summary>
|
|
12
|
+
/// PhotonSpin32: a 20-word ring-buffer generator inspired by SHISHUA, tuned for high throughput and large period.
|
|
13
|
+
/// </summary>
|
|
14
|
+
/// <remarks>
|
|
15
|
+
/// <para>
|
|
16
|
+
/// https://github.com/wileylooper/photonspin
|
|
17
|
+
/// Ported from <c>wileylooper/photonspin</c>, this generator produces batches of 20 new 32-bit values per round,
|
|
18
|
+
/// offering a huge period (~2<sup>512</sup>) and robust statistical performance. It shines when large streams are
|
|
19
|
+
/// required, while still supporting deterministic state capture and serialization.
|
|
20
|
+
/// </para>
|
|
21
|
+
/// <para>Pros:</para>
|
|
22
|
+
/// <list type="bullet">
|
|
23
|
+
/// <item><description>Large state with excellent distribution; great for heavy simulation workloads.</description></item>
|
|
24
|
+
/// <item><description>Thread-local friendly via <see cref="ThreadLocalRandom{T}.Instance"/>.</description></item>
|
|
25
|
+
/// <item><description>Deterministic snapshots through <see cref="RandomState"/>.</description></item>
|
|
26
|
+
/// </list>
|
|
27
|
+
/// <para>Cons:</para>
|
|
28
|
+
/// <list type="bullet">
|
|
29
|
+
/// <item><description>Higher per-instance memory (~20×4 bytes).</description></item>
|
|
30
|
+
/// <item><description>Not cryptographically secure.</description></item>
|
|
31
|
+
/// </list>
|
|
32
|
+
/// <para>When to use:</para>
|
|
33
|
+
/// <list type="bullet">
|
|
34
|
+
/// <item><description>Procedural workloads that benefit from bulk generation and long non-overlapping streams.</description></item>
|
|
35
|
+
/// </list>
|
|
36
|
+
/// <para>When not to use:</para>
|
|
37
|
+
/// <list type="bullet">
|
|
38
|
+
/// <item><description>Security or adversarial scenarios.</description></item>
|
|
39
|
+
/// </list>
|
|
40
|
+
/// </remarks>
|
|
41
|
+
/// <example>
|
|
42
|
+
/// <code>
|
|
43
|
+
/// using WallstopStudios.UnityHelpers.Core.Random;
|
|
44
|
+
///
|
|
45
|
+
/// PhotonSpinRandom rng = new PhotonSpinRandom(seed: 42u);
|
|
46
|
+
/// float noise = rng.NextFloat();
|
|
47
|
+
/// Guid guid = rng.NextGuid();
|
|
48
|
+
/// </code>
|
|
49
|
+
/// </example>
|
|
50
|
+
[Serializable]
|
|
51
|
+
[DataContract]
|
|
52
|
+
[ProtoContract(SkipConstructor = true)]
|
|
53
|
+
public sealed class PhotonSpinRandom
|
|
54
|
+
: AbstractRandom,
|
|
55
|
+
IEquatable<PhotonSpinRandom>,
|
|
56
|
+
IComparable,
|
|
57
|
+
IComparable<PhotonSpinRandom>
|
|
58
|
+
{
|
|
59
|
+
private const uint Increment = 111_111U;
|
|
60
|
+
private const int BlockSize = 20;
|
|
61
|
+
private const int ElementByteSize = BlockSize * sizeof(uint);
|
|
62
|
+
|
|
63
|
+
public static PhotonSpinRandom Instance => ThreadLocalRandom<PhotonSpinRandom>.Instance;
|
|
64
|
+
|
|
65
|
+
public override RandomState InternalState
|
|
66
|
+
{
|
|
67
|
+
get
|
|
68
|
+
{
|
|
69
|
+
using PooledResource<byte[]> payloadLease = WallstopArrayPool<byte>.Get(
|
|
70
|
+
ElementByteSize,
|
|
71
|
+
out byte[] buffer
|
|
72
|
+
);
|
|
73
|
+
Buffer.BlockCopy(_elements, 0, buffer, 0, ElementByteSize);
|
|
74
|
+
|
|
75
|
+
uint packedIndex = (uint)(_index & 0x7FFFFFFF);
|
|
76
|
+
if (_hasPrimed)
|
|
77
|
+
{
|
|
78
|
+
packedIndex |= 0x80000000U;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ulong state1 = ((ulong)_a << 32) | _b;
|
|
82
|
+
ulong state2 = ((ulong)_c << 32) | packedIndex;
|
|
83
|
+
return BuildState(
|
|
84
|
+
state1,
|
|
85
|
+
state2,
|
|
86
|
+
new ArraySegment<byte>(buffer, 0, ElementByteSize)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
[ProtoMember(6)]
|
|
92
|
+
private uint[] _elements = new uint[BlockSize];
|
|
93
|
+
|
|
94
|
+
[ProtoMember(7)]
|
|
95
|
+
private uint _a;
|
|
96
|
+
|
|
97
|
+
[ProtoMember(8)]
|
|
98
|
+
private uint _b;
|
|
99
|
+
|
|
100
|
+
[ProtoMember(9)]
|
|
101
|
+
private uint _c;
|
|
102
|
+
|
|
103
|
+
[ProtoMember(10)]
|
|
104
|
+
private int _index;
|
|
105
|
+
|
|
106
|
+
[ProtoMember(11)]
|
|
107
|
+
private bool _hasPrimed;
|
|
108
|
+
|
|
109
|
+
public PhotonSpinRandom()
|
|
110
|
+
: this(Guid.NewGuid()) { }
|
|
111
|
+
|
|
112
|
+
public PhotonSpinRandom(Guid guid)
|
|
113
|
+
{
|
|
114
|
+
InitializeFromGuid(guid);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public PhotonSpinRandom(uint seed)
|
|
118
|
+
{
|
|
119
|
+
uint seedA = seed;
|
|
120
|
+
uint seedB = seed ^ 0x9E3779B9U;
|
|
121
|
+
if (seedB == 0)
|
|
122
|
+
{
|
|
123
|
+
seedB = 1U;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
uint seedC = seed + 0x6C8E9CF5U;
|
|
127
|
+
InitializeFromScalars(seedA, seedB, seedC);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public PhotonSpinRandom(uint seedA, uint seedB, uint seedC)
|
|
131
|
+
{
|
|
132
|
+
InitializeFromScalars(seedA, seedB == 0 ? 1U : seedB, seedC);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[JsonConstructor]
|
|
136
|
+
public PhotonSpinRandom(RandomState internalState)
|
|
137
|
+
{
|
|
138
|
+
ulong state1 = internalState.State1;
|
|
139
|
+
ulong state2 = internalState.State2;
|
|
140
|
+
|
|
141
|
+
_a = (uint)(state1 >> 32);
|
|
142
|
+
_b = (uint)state1;
|
|
143
|
+
_c = (uint)(state2 >> 32);
|
|
144
|
+
|
|
145
|
+
uint packedIndex = (uint)state2;
|
|
146
|
+
_hasPrimed = (packedIndex & 0x80000000U) != 0;
|
|
147
|
+
_index = (int)(packedIndex & 0x7FFFFFFF);
|
|
148
|
+
if (_index < 0 || _index > BlockSize)
|
|
149
|
+
{
|
|
150
|
+
_index = BlockSize;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
LoadSerializedElements(internalState._payload);
|
|
154
|
+
NormalizeIndex();
|
|
155
|
+
RestoreCommonState(internalState);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public override uint NextUint()
|
|
159
|
+
{
|
|
160
|
+
if (!_hasPrimed)
|
|
161
|
+
{
|
|
162
|
+
GenerateBlock();
|
|
163
|
+
_hasPrimed = true;
|
|
164
|
+
_index = BlockSize;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (_index >= BlockSize)
|
|
168
|
+
{
|
|
169
|
+
GenerateBlock();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
uint value = _elements[_index];
|
|
173
|
+
_index += 1;
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public override IRandom Copy()
|
|
178
|
+
{
|
|
179
|
+
return new PhotonSpinRandom(InternalState);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public override bool Equals(object obj)
|
|
183
|
+
{
|
|
184
|
+
return Equals(obj as PhotonSpinRandom);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public bool Equals(PhotonSpinRandom other)
|
|
188
|
+
{
|
|
189
|
+
if (other == null)
|
|
190
|
+
{
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (_a != other._a || _b != other._b || _c != other._c)
|
|
195
|
+
{
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (_index != other._index || _hasPrimed != other._hasPrimed)
|
|
200
|
+
{
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!_elements.AsSpan().SequenceEqual(other._elements))
|
|
205
|
+
{
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
|
210
|
+
return _cachedGaussian == other._cachedGaussian;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public override int GetHashCode()
|
|
214
|
+
{
|
|
215
|
+
return Objects.HashCode(_a, _b, _c, _index, _hasPrimed);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
public override string ToString()
|
|
219
|
+
{
|
|
220
|
+
return this.ToJson();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
public int CompareTo(object obj)
|
|
224
|
+
{
|
|
225
|
+
return CompareTo(obj as PhotonSpinRandom);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
public int CompareTo(PhotonSpinRandom other)
|
|
229
|
+
{
|
|
230
|
+
if (other == null)
|
|
231
|
+
{
|
|
232
|
+
return -1;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
int comparison = _a.CompareTo(other._a);
|
|
236
|
+
if (comparison != 0)
|
|
237
|
+
{
|
|
238
|
+
return comparison;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
comparison = _b.CompareTo(other._b);
|
|
242
|
+
if (comparison != 0)
|
|
243
|
+
{
|
|
244
|
+
return comparison;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
comparison = _c.CompareTo(other._c);
|
|
248
|
+
if (comparison != 0)
|
|
249
|
+
{
|
|
250
|
+
return comparison;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
comparison = _index.CompareTo(other._index);
|
|
254
|
+
if (comparison != 0)
|
|
255
|
+
{
|
|
256
|
+
return comparison;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
comparison = _hasPrimed.CompareTo(other._hasPrimed);
|
|
260
|
+
if (comparison != 0)
|
|
261
|
+
{
|
|
262
|
+
return comparison;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
for (int i = 0; i < BlockSize; ++i)
|
|
266
|
+
{
|
|
267
|
+
comparison = _elements[i].CompareTo(other._elements[i]);
|
|
268
|
+
if (comparison != 0)
|
|
269
|
+
{
|
|
270
|
+
return comparison;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private void LoadSerializedElements(byte[] payload)
|
|
278
|
+
{
|
|
279
|
+
if (_elements == null || _elements.Length != BlockSize)
|
|
280
|
+
{
|
|
281
|
+
_elements = new uint[BlockSize];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (payload != null && payload.Length >= ElementByteSize)
|
|
285
|
+
{
|
|
286
|
+
Buffer.BlockCopy(payload, 0, _elements, 0, ElementByteSize);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
Array.Clear(_elements, 0, _elements.Length);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private void NormalizeIndex()
|
|
294
|
+
{
|
|
295
|
+
if (_index < 0 || _index > BlockSize)
|
|
296
|
+
{
|
|
297
|
+
_index = BlockSize;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private void InitializeFromGuid(Guid guid)
|
|
302
|
+
{
|
|
303
|
+
(ulong seed0, ulong seed1) = RandomUtilities.GuidToUInt64Pair(guid);
|
|
304
|
+
InitializeFromUlongs(seed0, seed1);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
private void InitializeFromScalars(uint seedA, uint seedB, uint seedC)
|
|
308
|
+
{
|
|
309
|
+
ulong seed0 = ((ulong)seedA << 32) | seedB;
|
|
310
|
+
ulong seed1 = ((ulong)seedC << 32) | (seedB ^ 0xA5A5A5A5U);
|
|
311
|
+
InitializeFromUlongs(seed0, seed1);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private void InitializeFromUlongs(ulong seed0, ulong seed1)
|
|
315
|
+
{
|
|
316
|
+
if (_elements == null || _elements.Length != BlockSize)
|
|
317
|
+
{
|
|
318
|
+
_elements = new uint[BlockSize];
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
ulong mixer = seed0 ^ (seed1 << 1) ^ 0x9E3779B97F4A7C15UL;
|
|
322
|
+
|
|
323
|
+
for (int i = 0; i < BlockSize; ++i)
|
|
324
|
+
{
|
|
325
|
+
_elements[i] = Mix32(ref mixer);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
_a = Mix32(ref mixer);
|
|
329
|
+
_b = Mix32(ref mixer);
|
|
330
|
+
_c = Mix32(ref mixer);
|
|
331
|
+
|
|
332
|
+
_index = BlockSize;
|
|
333
|
+
_hasPrimed = false;
|
|
334
|
+
NormalizeIndex();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
private void GenerateBlock()
|
|
338
|
+
{
|
|
339
|
+
unchecked
|
|
340
|
+
{
|
|
341
|
+
Span<uint> mix = stackalloc uint[4];
|
|
342
|
+
int baseIndex = (int)(_a & 15U);
|
|
343
|
+
mix[0] = _elements[baseIndex];
|
|
344
|
+
mix[1] = _elements[(baseIndex + 3) & 15];
|
|
345
|
+
mix[2] = _elements[(baseIndex + 6) & 15];
|
|
346
|
+
mix[3] = _elements[(baseIndex + 9) & 15];
|
|
347
|
+
|
|
348
|
+
_a += Increment;
|
|
349
|
+
|
|
350
|
+
int k = 0;
|
|
351
|
+
for (int i = 0; i < 4; ++i)
|
|
352
|
+
{
|
|
353
|
+
_b += _a;
|
|
354
|
+
_c ^= _a;
|
|
355
|
+
mix[i] += RotateLeft(_b, 9);
|
|
356
|
+
|
|
357
|
+
for (int j = 0; j < 5; ++j)
|
|
358
|
+
{
|
|
359
|
+
_elements[k] += RotateLeft(mix[i], 25);
|
|
360
|
+
_elements[k] ^= _c;
|
|
361
|
+
mix[i] += _elements[k];
|
|
362
|
+
k++;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (
|
|
366
|
+
_elements[k - 1] == _elements[k - 2]
|
|
367
|
+
&& _elements[k - 3] == _elements[k - 4]
|
|
368
|
+
)
|
|
369
|
+
{
|
|
370
|
+
_elements[k - 1] += mix[i] ^ 81_016U;
|
|
371
|
+
_elements[k - 2] += mix[i] ^ 297_442_265U;
|
|
372
|
+
_elements[k - 3] += (mix[i] ^ 5_480U) | (mix[i] & 1U);
|
|
373
|
+
_elements[k - 4] += mix[i] ^ 19_006_808U;
|
|
374
|
+
_elements[k - 5] += mix[i];
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
_b += RotateLeft(mix[0], 23);
|
|
379
|
+
_b ^= mix[1];
|
|
380
|
+
_c += RotateLeft(mix[2], 13);
|
|
381
|
+
_c ^= mix[3];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
_index = 0;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
@@ -8,9 +8,6 @@ namespace WallstopStudios.UnityHelpers.Core.Random
|
|
|
8
8
|
using Helper;
|
|
9
9
|
using ProtoBuf;
|
|
10
10
|
|
|
11
|
-
[Serializable]
|
|
12
|
-
[DataContract]
|
|
13
|
-
[ProtoContract]
|
|
14
11
|
/// <summary>
|
|
15
12
|
/// A member of the ROMU family (RomuDuo) emphasizing high speed and good statistical quality on modern CPUs.
|
|
16
13
|
/// </summary>
|
|
@@ -48,6 +45,9 @@ namespace WallstopStudios.UnityHelpers.Core.Random
|
|
|
48
45
|
/// double normal = rng.NextGaussian(0.0, 1.0);
|
|
49
46
|
/// </code>
|
|
50
47
|
/// </example>
|
|
48
|
+
[Serializable]
|
|
49
|
+
[DataContract]
|
|
50
|
+
[ProtoContract]
|
|
51
51
|
public sealed class RomuDuo
|
|
52
52
|
: AbstractRandom,
|
|
53
53
|
IEquatable<RomuDuo>,
|
|
@@ -5,9 +5,6 @@ namespace WallstopStudios.UnityHelpers.Core.Random
|
|
|
5
5
|
using System.Text.Json.Serialization;
|
|
6
6
|
using ProtoBuf;
|
|
7
7
|
|
|
8
|
-
[Serializable]
|
|
9
|
-
[DataContract]
|
|
10
|
-
[ProtoContract]
|
|
11
8
|
/// <summary>
|
|
12
9
|
/// A fast 64-bit SplitMix generator often used as a high-quality seeding/mixing PRNG.
|
|
13
10
|
/// </summary>
|
|
@@ -45,6 +42,9 @@ namespace WallstopStudios.UnityHelpers.Core.Random
|
|
|
45
42
|
/// int v = seeded.Next(0, 10);
|
|
46
43
|
/// </code>
|
|
47
44
|
/// </example>
|
|
45
|
+
[Serializable]
|
|
46
|
+
[DataContract]
|
|
47
|
+
[ProtoContract]
|
|
48
48
|
public sealed class SplitMix64
|
|
49
49
|
: AbstractRandom,
|
|
50
50
|
IEquatable<SplitMix64>,
|
|
@@ -5,15 +5,14 @@ namespace WallstopStudios.UnityHelpers.Core.Random
|
|
|
5
5
|
using System.Text.Json.Serialization;
|
|
6
6
|
using ProtoBuf;
|
|
7
7
|
|
|
8
|
-
// https://youtu.be/LWFzPP8ZbdU?t=2673
|
|
9
|
-
[DataContract]
|
|
10
|
-
[Serializable]
|
|
11
|
-
[ProtoContract]
|
|
12
8
|
/// <summary>
|
|
13
9
|
/// A hash-based PRNG inspired by Squirrel Eiserloh's "Squirrel Noise" approach for deterministic noise.
|
|
14
10
|
/// </summary>
|
|
15
11
|
/// <remarks>
|
|
16
12
|
/// <para>
|
|
13
|
+
/// Reference implementation: https://youtu.be/LWFzPP8ZbdU?t=2673
|
|
14
|
+
/// </para>
|
|
15
|
+
/// <para>
|
|
17
16
|
/// Squirrel-style generators are simple, stateless transformations that can produce deterministic pseudo-noise
|
|
18
17
|
/// values from integer coordinates or an advancing internal position. This implementation exposes both a sequential
|
|
19
18
|
/// <see cref="NextUint()"/> and coordinate-based noise via <see cref="NextNoise(int, int)"/> without advancing state.
|
|
@@ -49,6 +48,9 @@ namespace WallstopStudios.UnityHelpers.Core.Random
|
|
|
49
48
|
/// int val = rng.Next(0, 100);
|
|
50
49
|
/// </code>
|
|
51
50
|
/// </example>
|
|
51
|
+
[Serializable]
|
|
52
|
+
[DataContract]
|
|
53
|
+
[ProtoContract]
|
|
52
54
|
public sealed class SquirrelRandom : AbstractRandom
|
|
53
55
|
{
|
|
54
56
|
private const uint BitNoise1 = 0xB5297A4D;
|