File: tinymt64.c

package info (click to toggle)
moarvm 2020.12%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 18,652 kB
  • sloc: ansic: 268,178; perl: 8,186; python: 1,316; makefile: 768; sh: 287
file content (133 lines) | stat: -rw-r--r-- 3,601 bytes parent folder | download | duplicates (3)
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
/**
 * @file tinymt64.h
 *
 * @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
 *
 * @file tinymt64.c
 *
 * @brief 64-bit 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 <platform/inttypes.h>
#include "tinymt64.h"

#define TINYMT64_SH0 12
#define TINYMT64_SH1 11
#define TINYMT64_SH8 8
#define TINYMT64_MASK UINT64_C(0x7fffffffffffffff)
#define TINYMT64_MUL (1.0 / 9007199254740992.0)

/*
 * tinymt64 default parameters
 */
#ifndef TINYMT64_MAT1
#  define TINYMT64_MAT1 0x7a840f50
#endif
#ifndef TINYMT64_MAT2
#  define TINYMT64_MAT2 0xf3d8fcf6
#endif
#ifndef TINYMT64_TMAT
#  define TINYMT64_TMAT 0x9746beffffbffffe
#endif

/*
 * Initialization loop
 */
#define MIN_LOOP 8

static const uint32_t mat1 = TINYMT64_MAT1;
static const uint32_t mat2 = TINYMT64_MAT2;
static const uint64_t tmat = TINYMT64_TMAT;

/**
 * This function changes internal state of tinymt64.
 * Users should not call this function directly.
 * @param random tinymt internal status
 */
static void tinymt64_next_state(uint64_t * random) {
    uint64_t x;

    random[0] &= TINYMT64_MASK;
    x = random[0] ^ random[1];
    x ^= x << TINYMT64_SH0;
    x ^= x >> 32;
    x ^= x << 32;
    x ^= x << TINYMT64_SH1;
    random[0] = random[1];
    random[1] = x;
    random[0] ^= -((int64_t)(x & 1)) & mat1;
    random[1] ^= -((int64_t)(x & 1)) & (((uint64_t)mat2) << 32);
}

/**
 * This function outputs 64-bit unsigned integer from internal state.
 * Users should not call this function directly.
 * @param random tinymt internal status
 * @return 64-bit unsigned pseudorandom number
 */
static uint64_t uint64_temper(uint64_t * random) {
    uint64_t x;
    x = random[0] + random[1];
    x ^= random[0] >> TINYMT64_SH8;
    x ^= -((int64_t)(x & 1)) & tmat;
    return x;
}

/**
 * This function outputs 64-bit unsigned integer from internal state.
 * @param random tinymt internal status
 * @return 64-bit unsigned integer r (0 <= r < 2^64)
 */
uint64_t tinymt64_generate_uint64(uint64_t * random) {
    tinymt64_next_state(random);
    return uint64_temper(random);
}

/**
 * This function outputs floating point number from internal state.
 * This function is implemented using multiplying by 1 / 2^64.
 * @param random tinymt internal status
 * @return floating point number r (0.0 <= r < 1.0)
 */
double tinymt64_generate_double(uint64_t * random) {
    tinymt64_next_state(random);
    return (uint64_temper(random) >> 11) * TINYMT64_MUL;
}

/**
 * This function initializes the internal state array with a 64-bit
 * unsigned integer seed.
 * @param random tinymt state vector.
 * @param seed a 64-bit unsigned integer used as a seed.
 */
void tinymt64_init(uint64_t * random, uint64_t seed) {
    int i;
    random[0] = seed ^ ((uint64_t)mat1 << 32);
    random[1] = mat2 ^ tmat;
    for (i = 1; i < MIN_LOOP; i++) {
        random[i & 1] ^= i + UINT64_C(6364136223846793005)
            * (random[(i - 1) & 1]
               ^ (random[(i - 1) & 1] >> 62));
    }
}