@@ -12,10 +12,55 @@ struct Rand48
12
12
13
13
@safe @nogc nothrow :
14
14
15
- void defaultSeed ()
15
+ void defaultSeed () @trusted
16
16
{
17
- import ctime = core.stdc.time : time;
18
- seed(cast (uint )ctime.time(null ));
17
+ version (D_InlineAsm_X86_64 )
18
+ {
19
+ // RDTSC takes around 22 clock cycles.
20
+ ulong result = void ; // Workaround for LDC issue #950, cannot access struct members in DMD asm.
21
+ asm @nogc nothrow
22
+ {
23
+ rdtsc;
24
+ // RAX: low 32 bits are low bits of timestamp, high 32 bits are 0.
25
+ // RDX: low 32 bits are high bits of timestamp, high 32 bits are 0.
26
+ // We combine these into a 48 bit value instead of a full 64 bits
27
+ // because `front` and `popFront` only make use of the bottom 48
28
+ // bits of `rng_state`.
29
+ shl RDX , 16 ;
30
+ xor RDX , RAX ;
31
+ mov result, RDX ;
32
+ }
33
+ rng_state = result;
34
+ popFront();
35
+ }
36
+ // else version(D_InlineAsm_X86)
37
+ // {
38
+ // // We don't use `rdtsc` with version(D_InlineAsm_X86) because
39
+ // // some x86 processors don't support `rdtsc` and because on
40
+ // // x86 (but not x86-64) Linux `prctl` can disable a process's
41
+ // // ability to use `rdtsc`.
42
+ // static assert(0);
43
+ // }
44
+ else version (Windows )
45
+ {
46
+ // QueryPerformanceCounter takes about 1/4 the time of ctime.time.
47
+ import core.sys.windows.winbase : QueryPerformanceCounter;
48
+ QueryPerformanceCounter(cast (long * ) &rng_state);
49
+ popFront();
50
+ }
51
+ else version (OSX )
52
+ {
53
+ // mach_absolute_time is much faster than ctime.time.
54
+ import core.time : mach_absolute_time;
55
+ rng_state = mach_absolute_time();
56
+ popFront();
57
+ }
58
+ else
59
+ {
60
+ // Fallback to libc timestamp in seconds.
61
+ import ctime = core.stdc.time : time;
62
+ seed((cast (uint ) ctime.time(null )));
63
+ }
19
64
}
20
65
21
66
pure :
0 commit comments