forked from okamumu/JMTRandom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMT64.java
132 lines (116 loc) · 2.83 KB
/
MT64.java
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
package com.github.okamumu.jmtrandom;
/**
* Mersenne Twister 64bit
*
* The original program, mt19937-64, is provided under 3-clause BSD license.
* The copyright holders of the original program are Makoto Matsumoto
* and Takuji Nishimura.
*
* See Lisence.txt of mt19937-64 program.
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
*
*/
public final class MT64 extends MTRand64 {
private final int NN = 312;
private final int MM = 156;
private final long MATRIX_A = 0xB5026F5AA96619E9L;
private final long UM = 0xFFFFFFFF80000000L;
private final long LM = 0x000000007FFFFFFFL;
private final long[] mag01 = new long[] {0L, MATRIX_A};
private final long mt[];
private int mti;
/*
* A common constructor which is used for the other constructors.
*/
private MT64() {
mt = new long [NN];
mti = NN + 1;
}
/**
* Constructor
* @param seed A long integer as a seed.
*/
public MT64(long seed) {
this();
this.initGenRand64(seed);
}
/**
* Constructor
* @param initKey A array of long integers used as a seed.
*/
public MT64(long[] initKey) {
this();
this.initByArray64(initKey);
}
/*
* The method to set a seed which is called from the constructor.
* @param seed A long integer
*/
private void initGenRand64(long seed) {
mt[0] = seed;
for (mti=1; mti<NN; mti++) {
mt[mti] = (6364136223846793005L * (mt[mti-1] ^ (mt[mti-1] >>> 62)) + mti);
}
}
/*
* The method to set an initial array which is called from the constructor.
* @param initKey An array of long integers
*/
private void initByArray64(long[] initKey) {
int keyLength = initKey.length;
this.initGenRand64(19650218L);
int i = 1;
int j = 0;
int k = (NN > keyLength) ? NN : keyLength;
for (; k>0; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^(mt[i-1] >>> 62)) * 3935559000370003845L))
+ initKey[j] + j;
i++;
j++;
if (i >= NN) {
mt[0] = mt[NN-1];
i = 1;
}
if (j >= keyLength) {
j = 0;
}
}
for (k=NN-1; k>0; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 62)) * 2862933555777941757L))
- i;
i++;
if (i >= NN) {
mt[0] = mt[NN-1];
i = 1;
}
}
mt[0] = 1L << 63;
}
@Override
public long genRand64() {
int i;
long x;
if (mti >= NN) {
if (mti == NN+1) {
this.initGenRand64(5489L);
}
for (i=0; i<NN-MM; i++) {
x = (mt[i] & UM) | (mt[i+1] & LM);
mt[i] = mt[i+MM] ^ (x >>> 1) ^ mag01[(int) (x & 1L)];
}
for (; i<NN-1; i++) {
x = (mt[i] & UM) | (mt[i+1] & LM);
mt[i] = mt[i + (MM-NN)] ^ (x >>> 1) ^ mag01[(int) (x & 1L)];
}
x = (mt[NN-1] & UM) | (mt[0] & LM);
mt[NN-1] = mt[MM-1] ^ (x >>> 1) ^ mag01[(int) (x & 1L)];
mti = 0;
}
x = mt[mti++];
x ^= (x >>> 29) & 0x5555555555555555L;
x ^= (x << 17) & 0x71D67FFFEDA60000L;
x ^= (x << 37) & 0xFFF7EEE000000000L;
x ^= (x >>> 43);
return x;
}
}