Blame view

RIOT/sys/random/tinymt32/tinymt32.c 4.11 KB
a752c7ab   elopes   add first test an...
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  /**
   * @file tinymt32.c
   *
   * @brief Tiny Mersenne Twister only 127 bit internal state
   *
   * @author Mutsuo Saito (Hiroshima University)
   * @author Makoto Matsumoto (The University of Tokyo)
   *
   * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
   * Hiroshima University and The University of Tokyo.
   * All rights reserved.
   *
   * The 3-clause BSD License is applied to this software, see
   * LICENSE.txt
   */
  #include "tinymt32.h"
  #define MIN_LOOP 8
  #define PRE_LOOP 8
  
  /**
   * This function represents a function used in the initialization
   * by init_by_array
   * @param x 32-bit integer
   * @return 32-bit integer
   */
  static uint32_t ini_func1(uint32_t x)
  {
      return (x ^ (x >> 27)) * UINT32_C(1664525);
  }
  
  /**
   * This function represents a function used in the initialization
   * by init_by_array
   * @param x 32-bit integer
   * @return 32-bit integer
   */
  static uint32_t ini_func2(uint32_t x)
  {
      return (x ^ (x >> 27)) * UINT32_C(1566083941);
  }
  
  /**
   * This function certificate the period of 2^127-1.
   * @param random tinymt state vector.
   */
  static void period_certification(tinymt32_t *random)
  {
      if ((random->status[0] & TINYMT32_MASK) == 0 &&
          random->status[1] == 0 &&
          random->status[2] == 0 &&
          random->status[3] == 0) {
          random->status[0] = 'T';
          random->status[1] = 'I';
          random->status[2] = 'N';
          random->status[3] = 'Y';
      }
  }
  
  /**
   * This function initializes the internal state array with a 32-bit
   * unsigned integer seed.
   * @param random tinymt state vector.
   * @param seed a 32-bit unsigned integer used as a seed.
   */
  void tinymt32_init(tinymt32_t *random, uint32_t seed)
  {
      random->status[0] = seed;
      random->status[1] = random->mat1;
      random->status[2] = random->mat2;
      random->status[3] = random->tmat;
      for (int i = 1; i < MIN_LOOP; i++) {
          random->status[i & 3] ^= i + UINT32_C(1812433253)
                                   * (random->status[(i - 1) & 3]
                                      ^ (random->status[(i - 1) & 3] >> 30));
      }
      period_certification(random);
      for (int i = 0; i < PRE_LOOP; i++) {
          tinymt32_next_state(random);
      }
  }
  
  /**
   * This function initializes the internal state array,
   * with an array of 32-bit unsigned integers used as seeds
   * @param random tinymt state vector.
   * @param init_key the array of 32-bit integers, used as a seed.
   * @param key_length the length of init_key.
   */
  void tinymt32_init_by_array(tinymt32_t *random, uint32_t init_key[],
                              int key_length)
  {
      const int lag = 1;
      const int mid = 1;
      const int size = 4;
      int i, j;
      int count;
      uint32_t r;
      uint32_t *st = &random->status[0];
  
      st[0] = 0;
      st[1] = random->mat1;
      st[2] = random->mat2;
      st[3] = random->tmat;
      if (key_length + 1 > MIN_LOOP) {
          count = key_length + 1;
      }
      else {
          count = MIN_LOOP;
      }
      r = ini_func1(st[0] ^ st[mid % size]
                    ^ st[(size - 1) % size]);
      st[mid % size] += r;
      r += key_length;
      st[(mid + lag) % size] += r;
      st[0] = r;
      count--;
      for (i = 1, j = 0; (j < count) && (j < key_length); j++) {
          r = ini_func1(st[i % size]
                        ^ st[(i + mid) % size]
                        ^ st[(i + size - 1) % size]);
          st[(i + mid) % size] += r;
          r += init_key[j] + i;
          st[(i + mid + lag) % size] += r;
          st[i % size] = r;
          i = (i + 1) % size;
      }
      for (; j < count; j++) {
          r = ini_func1(st[i % size]
                        ^ st[(i + mid) % size]
                        ^ st[(i + size - 1) % size]);
          st[(i + mid) % size] += r;
          r += i;
          st[(i + mid + lag) % size] += r;
          st[i % size] = r;
          i = (i + 1) % size;
      }
      for (j = 0; j < size; j++) {
          r = ini_func2(st[i % size]
                        + st[(i + mid) % size]
                        + st[(i + size - 1) % size]);
          st[(i + mid) % size] ^= r;
          r -= i;
          st[(i + mid + lag) % size] ^= r;
          st[i % size] = r;
          i = (i + 1) % size;
      }
      period_certification(random);
      for (i = 0; i < PRE_LOOP; i++) {
          tinymt32_next_state(random);
      }
  }