summaryrefslogtreecommitdiff
path: root/numpy/random/src/mt19937/mt19937.h
blob: 1b39e0b6434c3f292e58b4059d62afe33f352659 (plain)
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
58
59
60
61
#pragma once
#include <math.h>
#include <stdint.h>

#ifdef _WIN32
#define inline __forceinline
#endif

#define RK_STATE_LEN 624

#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL
#define UPPER_MASK 0x80000000UL
#define LOWER_MASK 0x7fffffffUL

typedef struct s_mt19937_state {
  uint32_t key[RK_STATE_LEN];
  int pos;
} mt19937_state;

extern void mt19937_seed(mt19937_state *state, uint32_t seed);

extern void mt19937_gen(mt19937_state *state);

/* Slightly optimized reference implementation of the Mersenne Twister */
static inline uint32_t mt19937_next(mt19937_state *state) {
  uint32_t y;

  if (state->pos == RK_STATE_LEN) {
    // Move to function to help inlining
    mt19937_gen(state);
  }
  y = state->key[state->pos++];

  /* Tempering */
  y ^= (y >> 11);
  y ^= (y << 7) & 0x9d2c5680UL;
  y ^= (y << 15) & 0xefc60000UL;
  y ^= (y >> 18);

  return y;
}

extern void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key,
                                  int key_length);

static inline uint64_t mt19937_next64(mt19937_state *state) {
  return (uint64_t)mt19937_next(state) << 32 | mt19937_next(state);
}

static inline uint32_t mt19937_next32(mt19937_state *state) {
  return mt19937_next(state);
}

static inline double mt19937_next_double(mt19937_state *state) {
  int32_t a = mt19937_next(state) >> 5, b = mt19937_next(state) >> 6;
  return (a * 67108864.0 + b) / 9007199254740992.0;
}

void mt19937_jump(mt19937_state *state);