File: splitmix.c

package info (click to toggle)
libuuid-perl 0.37-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,092 kB
  • sloc: ansic: 2,374; perl: 580; makefile: 5
file content (57 lines) | stat: -rw-r--r-- 1,238 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifdef __cplusplus
extern "C" {
#endif

#include "ulib/splitmix.h"
#include "ulib/gettime.h"

#ifdef __cplusplus
}
#endif

/* based on splitmix64
 * https://xorshift.di.unimi.it/splitmix64.c
*/

void sm_srand(pUCXT, Pid_t pid) {
  unsigned int  n;
  UV            ptod[2];

  /*
   * The idea is to just have a unique value here,
   * so system time and process id should be enough.
   * (Provided system time doesn't repeat!)
   *
   * But, since Unix epoch time with usec resolution
   * is 51 bits, that only leaves 13 bits for pid.
   *
   * So, lets initially seed with TOD, mix, add the PID,
   * then mix again.
  */

  /* gettimeofday(&tv, 0); */
  (*UCXT.myU2time)(aTHX_ (UV*)&ptod);
  UCXT.sm_x = (U64)ptod[0] * 1000000
    + (U64)ptod[1];

  /* stir 16 - 31 times, pid-based */
  n = 16 + (pid & 0x0f);
  while (n-- > 0)
    (void)sm_rand(aUCXT);

  UCXT.sm_x ^= (U64)pid;

  /* stir 16 - 31 times, time-based */
  n = 16 + ((ptod[0] ^ ptod[1]) & 0x0f);
  while (n-- > 0)
    (void)sm_rand(aUCXT);
}

U64 sm_rand(pUCXT) {
  U64 z = (UCXT.sm_x += 0x9e3779b97f4a7c15ULL);
  z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
  z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
  return z ^ (z >> 31);
}

/* ex:set ts=2 sw=2 itab=spaces: */