|
3 | 3 | #include <math.h> |
4 | 4 | #include "kmath.h" |
5 | 5 |
|
6 | | -/************************************** |
7 | | - *** Pseudo-random number generator *** |
8 | | - **************************************/ |
9 | | - |
10 | | -/* |
11 | | - 64-bit Mersenne Twister pseudorandom number generator. Adapted from: |
12 | | -
|
13 | | - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c |
14 | | -
|
15 | | - which was written by Takuji Nishimura and Makoto Matsumoto and released |
16 | | - under the 3-clause BSD license. |
17 | | -*/ |
18 | | - |
19 | | -#define KR_NN 312 |
20 | | -#define KR_MM 156 |
21 | | -#define KR_UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ |
22 | | -#define KR_LM 0x7FFFFFFFULL /* Least significant 31 bits */ |
23 | | - |
24 | | -struct _krand_t { |
25 | | - int mti, n_iset; |
26 | | - double n_gset; |
27 | | - krint64_t mt[KR_NN]; |
28 | | -}; |
29 | | - |
30 | | -static void kr_srand0(krint64_t seed, krand_t *kr) |
31 | | -{ |
32 | | - kr->mt[0] = seed; |
33 | | - for (kr->mti = 1; kr->mti < KR_NN; ++kr->mti) |
34 | | - kr->mt[kr->mti] = 6364136223846793005ULL * (kr->mt[kr->mti - 1] ^ (kr->mt[kr->mti - 1] >> 62)) + kr->mti; |
35 | | -} |
36 | | - |
37 | | -krand_t *kr_srand(krint64_t seed) |
38 | | -{ |
39 | | - krand_t *kr; |
40 | | - kr = (krand_t*)calloc(1, sizeof(krand_t)); |
41 | | - kr_srand0(seed, kr); |
42 | | - return kr; |
43 | | -} |
44 | | - |
45 | | -krint64_t kr_rand(krand_t *kr) |
46 | | -{ |
47 | | - krint64_t x; |
48 | | - static const krint64_t mag01[2] = { 0, 0xB5026F5AA96619E9ULL }; |
49 | | - if (kr->mti >= KR_NN) { |
50 | | - int i; |
51 | | - if (kr->mti == KR_NN + 1) kr_srand0(5489ULL, kr); |
52 | | - for (i = 0; i < KR_NN - KR_MM; ++i) { |
53 | | - x = (kr->mt[i] & KR_UM) | (kr->mt[i+1] & KR_LM); |
54 | | - kr->mt[i] = kr->mt[i + KR_MM] ^ (x>>1) ^ mag01[(int)(x&1)]; |
55 | | - } |
56 | | - for (; i < KR_NN - 1; ++i) { |
57 | | - x = (kr->mt[i] & KR_UM) | (kr->mt[i+1] & KR_LM); |
58 | | - kr->mt[i] = kr->mt[i + (KR_MM - KR_NN)] ^ (x>>1) ^ mag01[(int)(x&1)]; |
59 | | - } |
60 | | - x = (kr->mt[KR_NN - 1] & KR_UM) | (kr->mt[0] & KR_LM); |
61 | | - kr->mt[KR_NN - 1] = kr->mt[KR_MM - 1] ^ (x>>1) ^ mag01[(int)(x&1)]; |
62 | | - kr->mti = 0; |
63 | | - } |
64 | | - x = kr->mt[kr->mti++]; |
65 | | - x ^= (x >> 29) & 0x5555555555555555ULL; |
66 | | - x ^= (x << 17) & 0x71D67FFFEDA60000ULL; |
67 | | - x ^= (x << 37) & 0xFFF7EEE000000000ULL; |
68 | | - x ^= (x >> 43); |
69 | | - return x; |
70 | | -} |
71 | | - |
72 | | -double kr_normal(krand_t *kr) |
73 | | -{ |
74 | | - if (kr->n_iset == 0) { |
75 | | - double fac, rsq, v1, v2; |
76 | | - do { |
77 | | - v1 = 2.0 * kr_drand(kr) - 1.0; |
78 | | - v2 = 2.0 * kr_drand(kr) - 1.0; |
79 | | - rsq = v1 * v1 + v2 * v2; |
80 | | - } while (rsq >= 1.0 || rsq == 0.0); |
81 | | - fac = sqrt(-2.0 * log(rsq) / rsq); |
82 | | - kr->n_gset = v1 * fac; |
83 | | - kr->n_iset = 1; |
84 | | - return v2 * fac; |
85 | | - } else { |
86 | | - kr->n_iset = 0; |
87 | | - return kr->n_gset; |
88 | | - } |
89 | | -} |
90 | | - |
91 | | -#ifdef _KR_MAIN |
92 | | -int main(int argc, char *argv[]) |
93 | | -{ |
94 | | - long i, N = 200000000; |
95 | | - krand_t *kr; |
96 | | - if (argc > 1) N = atol(argv[1]); |
97 | | - kr = kr_srand(11); |
98 | | - for (i = 0; i < N; ++i) kr_rand(kr); |
99 | | -// for (i = 0; i < N; ++i) lrand48(); |
100 | | - free(kr); |
101 | | - return 0; |
102 | | -} |
103 | | -#endif |
104 | | - |
105 | 6 | /****************************** |
106 | 7 | *** Non-linear programming *** |
107 | 8 | ******************************/ |
|
0 commit comments