MathgeomGLS
404 строки · 10.5 Кб
1{---------------------------------------------------------------------------}
2{ }
3{ File: Velthuis.XorShifts.pas }
4{ Function: Simple xorshift random number generators, implementing }
5{ IRandom interface from Velthuis.RandomNumbers. }
6{ Language: Delphi version XE3 or later }
7{ Author: Rudy Velthuis }
8{ Copyright: (c) 2018 Rudy Velthuis }
9{ }
10{ Literature: https://de.wikipedia.org/wiki/Xorshift }
11{ https://en.wikipedia.org/wiki/Xorshift }
12{ }
13{ Acknowledgement: }
14{ Several of the algorithms below were developed by }
15{ Sebastiano Vigna and released to the public domain, }
16{ see http://vigna.di.unimi.it/ }
17{ }
18{ License: Redistribution and use in source and binary forms, with or }
19{ without modification, are permitted provided that the }
20{ following conditions are met: }
21{ }
22{ * Redistributions of source code must retain the above }
23{ copyright notice, this list of conditions and the following }
24{ disclaimer. }
25{ * Redistributions in binary form must reproduce the above }
26{ copyright notice, this list of conditions and the following }
27{ disclaimer in the documentation and/or other materials }
28{ provided with the distribution. }
29{ }
30{ Disclaimer: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" }
31{ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT }
32{ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND }
33{ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO }
34{ EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE }
35{ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, }
36{ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
37{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, }
38{ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED }
39{ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT }
40{ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) }
41{ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF }
42{ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. }
43{ }
44{---------------------------------------------------------------------------}
45
46unit Velthuis.XorShifts;
47
48interface
49
50uses
51Velthuis.RandomNumbers;
52
53type
54TXorShift32 = class(TRandomBase)
55private
56FSeed: UInt32;
57protected
58function GetSeed: Int64; override;
59function Next(Bits: Integer): UInt32; override;
60procedure SetSeed(Seed: Int64); override;
61public
62constructor Create;
63end;
64
65TXorShift64 = class(TRandomBase64)
66private
67FSeed: UInt64;
68protected
69function GetSeed: Int64; override;
70function Next64(Bits: Integer): UInt64; override;
71procedure SetSeed(Seed: Int64); override;
72public
73constructor Create;
74end;
75
76TXorShift128 = class(TRandomBase)
77private
78FSeed: array[0..3] of UInt32;
79FSeedIndex: Integer;
80protected
81function GetSeed: Int64; override;
82function Next(Bits: Integer): UInt32; override;
83procedure SetSeed(Seed: Int64); override;
84public
85constructor Create;
86end;
87
88TXorWowState = array[0..4] of UInt32;
89
90TXorWow = class(TRandomBase)
91private
92FSeed: TXorWowState;
93FSeedIndex: Integer;
94protected
95function GetSeed: Int64; override;
96function Next(Bits: Integer): UInt32; override;
97procedure SetSeed(Seed: Int64); override;
98public
99constructor Create(const State: TXorWowState);
100end;
101
102TXorShift64Star = class(TRandomBase64)
103private
104FSeed: UInt64;
105public
106constructor Create(const State: UInt64);
107function GetSeed: Int64; override;
108function Next64(Bits: Integer): UInt64; override;
109procedure SetSeed(Seed: Int64); override;
110end;
111
112TXorShift1024Star = class(TRandomBase64)
113private
114FSeed: array[0..15] of UInt64;
115FSeedIndex: Integer;
116FNextIndex: Integer;
117protected
118function GetSeed: Int64; override;
119function Next64(Bits: Integer): UInt64; override;
120procedure SetSeed(Seed: Int64); override;
121public
122constructor Create(State: array of UInt64);
123end;
124
125TXorShift128Plus = class(TRandomBase64)
126private
127FSeed: array[0..1] of UInt64;
128FSeedIndex: Integer;
129protected
130function GetSeed: Int64; override;
131function Next64(Bits: Integer): UInt64; override;
132procedure SetSeed(Seed: Int64); override;
133public
134constructor Create(State0, State1: UInt64);
135end;
136
137implementation
138
139uses
140System.Math, Winapi.Windows;
141
142{$RANGECHECKS OFF}
143{$OVERFLOWCHECKS OFF}
144
145function SplitMix64(var X: UInt64) : UInt64;
146var
147Z: UInt64;
148begin
149Inc(X, UInt64($9E3779B97F4A7C15));
150Z := (X xor (X shr 30)) * UInt64($BF58476D1CE4E5B9);
151Z := (Z xor (Z shr 27)) * UInt64($94D049BB133111EB);
152Result := Z xor (Z shr 31);
153end;
154
155{ TXorShift32 }
156
157constructor TXorShift32.Create;
158var
159C: Int64;
160begin
161if QueryPerformanceCounter(C) then
162FSeed := UInt32(C)
163else
164FSeed := GetTickCount;
165end;
166
167function TXorShift32.GetSeed: Int64;
168begin
169Result := FSeed;
170end;
171
172function TXorShift32.Next(Bits: Integer): UInt32;
173begin
174FSeed := FSeed xor (FSeed shl 13);
175FSeed := FSeed xor (FSeed shr 17);
176FSeed := FSeed xor (FSeed shl 5);
177Result := FSeed shr (32 - Bits);
178end;
179
180procedure TXorShift32.SetSeed(Seed: Int64);
181begin
182FSeed := UInt32(Seed);
183end;
184
185{ TXorShift64 }
186
187constructor TXorShift64.Create;
188var
189C: Int64;
190begin
191if QueryPerformanceCounter(C) then
192FSeed := C
193else
194FSeed := 88172645463325252 + GetTickCount;
195end;
196
197function TXorShift64.GetSeed: Int64;
198begin
199Result := Int64(FSeed);
200end;
201
202function TXorShift64.Next64(Bits: Integer): UInt64;
203begin
204FSeed := FSeed xor (FSeed shl 13);
205FSeed := FSeed xor (FSeed shr 7);
206FSeed := FSeed xor (FSeed shl 17);
207Result := FSeed shr (64 - Bits);
208end;
209
210procedure TXorShift64.SetSeed(Seed: Int64);
211begin
212FSeed := UInt64(Seed);
213end;
214
215{ TXorShift128 }
216
217constructor TXorShift128.Create;
218begin
219FSeed[0] := 123456789;
220FSeed[1] := 362436069;
221FSeed[2] := 521288629;
222FSeed[3] := 88675123;
223FSeedIndex := 0;
224end;
225
226function TXorShift128.GetSeed: Int64;
227begin
228Result := Int64(FSeed[1]) shl 32 + FSeed[0];
229end;
230
231function TXorShift128.Next(Bits: Integer): UInt32;
232const
233X = 0;
234y = 1;
235z = 2;
236w = 3;
237var
238T: UInt32;
239begin
240T := FSeed[x] xor (FSeed[x] shl 11);
241FSeed[x] := FSeed[y];
242FSeed[y] := FSeed[z];
243FSeed[z] := FSeed[w];
244FSeed[w] := FSeed[w] xor ((FSeed[w] shr 19) xor T xor (T shr 8));
245
246Result := FSeed[w] shr (32 - Bits);
247end;
248
249// Call twice to set full seed.
250procedure TXorShift128.SetSeed(Seed: Int64);
251begin
252FSeed[FSeedIndex] := UInt32(Seed);
253FSeed[FSeedIndex + 1] := UInt32(Seed shr 32);
254FSeedIndex := (FSeedIndex + 2) and 3;
255end;
256
257{ TXorWow }
258
259constructor TXorWow.Create(const State: TXorWowState);
260begin
261FSeed := State;
262FSeedIndex := 0;
263end;
264
265function TXorWow.GetSeed: Int64;
266begin
267Result := Int64(FSeed[1]) shr 32 + FSeed[0];
268end;
269
270function TXorWow.Next(Bits: Integer): UInt32;
271var
272S, T: UInt32;
273begin
274T := FSeed[3];
275T := T xor (T shr 2);
276T := T xor (T shl 1);
277FSeed[3] := FSeed[2];
278FSeed[2] := FSeed[1];
279FSeed[1] := FSeed[0];
280S := FSeed[0];
281T := T xor S;
282T := T xor (S shl 4);
283FSeed[0] := T;
284FSeed[4] := FSeed[4] + 362437;
285Result := (T + FSeed[4]) shr (32 - Bits);
286end;
287
288// Call thrice to set full seed.
289procedure TXorWow.SetSeed(Seed: Int64);
290begin
291if FSeedIndex = 4 then
292begin
293FSeed[4] := UInt32(Seed);
294FSeedIndex := 0;
295end
296else
297begin
298FSeed[FSeedIndex] := UInt32(Seed);
299FSeed[FSeedIndex + 1] := UInt32(Seed shr 32);
300FSeedIndex := FSeedIndex + 2;
301end;
302end;
303
304{ TXorShift64Star }
305
306constructor TXorShift64Star.Create(const State: UInt64);
307begin
308FSeed := State;
309end;
310
311function TXorShift64Star.GetSeed: Int64;
312begin
313Result := Int64(FSeed);
314end;
315
316function TXorShift64Star.Next64(Bits: Integer): UInt64;
317var
318X: UInt64;
319begin
320X := FSeed;
321X := X xor (X shr 12);
322X := X xor (X shl 25);
323X := X xor (X shr 27);
324FSeed := X;
325Result := (X * UInt64($2545F4914F6CDD1D)) shr (64 - Bits);
326end;
327
328procedure TXorShift64Star.SetSeed(Seed: Int64);
329begin
330FSeed := UInt64(Seed);
331end;
332
333{ TXorShift1024Star }
334
335constructor TXorShift1024Star.Create(State: array of UInt64);
336var
337I: Integer;
338begin
339for I := 0 to Max(High(State), High(FSeed)) do
340FSeed[I] := State[I];
341FSeedIndex := 0;
342FNextIndex := 0;
343end;
344
345function TXorShift1024Star.GetSeed: Int64;
346begin
347Result := Int64(FSeed[FSeedIndex]);
348end;
349
350function TXorShift1024Star.Next64(Bits: Integer): UInt64;
351var
352S0, S1: UInt64;
353begin
354S0 := FSeed[FNextIndex];
355FNextIndex := (FNextIndex + 1) and 15;
356S1 := FSeed[FNextIndex];
357S1 := S1 xor (S1 shl 31);
358S1 := S1 xor (S1 shr 11);
359S1 := S1 xor (S0 xor (S0 shr 30));
360FSeed[FNextIndex] := S1;
361
362Result := (S1 * UInt64(1181783497276652981)) shr (64 - Bits);
363end;
364
365procedure TXorShift1024Star.SetSeed(Seed: Int64);
366begin
367FSeed[FSeedIndex] := UInt64(Seed);
368FSeedIndex := (FSeedIndex + 1) and 15;
369end;
370
371{ TXorShift182Plus }
372
373constructor TXorShift128Plus.Create(State0, State1: UInt64);
374begin
375FSeed[0] := State0;
376FSeed[1] := State1;
377FSeedIndex := 0;
378end;
379
380function TXorShift128Plus.GetSeed: Int64;
381begin
382Result := FSeed[0];
383end;
384
385function TXorShift128Plus.Next64(Bits: Integer): UInt64;
386var
387X, Y: UInt64;
388begin
389X := FSeed[0];
390Y := FSeed[1];
391FSeed[0] := Y;
392X := X xor (X shl 23);
393FSeed[1] := X xor Y xor (X shr 17) xor (Y shr 26);
394
395Result := (FSeed[1] + Y) shr (64 - Bits);
396end;
397
398procedure TXorShift128Plus.SetSeed(Seed: Int64);
399begin
400FSeed[FSeedIndex] := Seed;
401FSeedIndex := FSeedIndex xor 1;
402end;
403
404end.
405