LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
rand_state.h
浏览该文件的文档.
1/*
2 * [LAMMP]
3 * Copyright (C) [2025-2026] [HJimmyK(Jericho Knox)]
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#ifndef __LAMMP_RAND_STATE_H__
20#define __LAMMP_RAND_STATE_H__
21
22#include "../lmmp.h"
23#include "../impl/longlong.h"
24
25typedef struct {
26 mp_limb_t state[2];
27 mp_limb_t inc[2]; // 必须为奇数
29
30typedef struct {
31 mp_limb_t s[4]; // 256位状态,必须初始化为非零值
33
34#define PCG128_DEFAULT_MULTIPLIER_HI 0x2360ED051FC65DA4ULL
35#define PCG128_DEFAULT_MULTIPLIER_LO 0x4385DF649FCCF645ULL
36
37#ifndef INLINE_
38#define INLINE_ static inline
39#endif
40
41/**
42 * @brief 种子生成器
43 * @param seed 低熵种子
44 * @return 高熵种子
45 */
47 mp_limb_t z = (seed += 0x9e3779b97f4a7c15);
48 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
49 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
50 return z ^ (z >> 31);
51}
52
53INLINE_ void pcg64_128_action(mp_limb_t state[2], const mp_limb_t inc[2]) {
54 // state = (state * PCG64_MULT + inc) mod 2^128
55 mp_limb_t tmp[2] = {0, 0};
56 _umul64to128_(state[0], PCG128_DEFAULT_MULTIPLIER_LO, tmp, tmp + 1);
57 tmp[1] += state[1] * PCG128_DEFAULT_MULTIPLIER_LO;
58 tmp[1] += state[0] * PCG128_DEFAULT_MULTIPLIER_HI;
59 _u128add(state, tmp, inc);
60}
61
63 lmmp_param_assert(rng != NULL);
64
65 rng->state[0] = lmmp_seed_generator(seed);
66 rng->state[1] = lmmp_seed_generator(seed << 17);
67 rng->inc[0] = lmmp_seed_generator(seed << 7);
68 rng->inc[0] |= 1ull;
69 rng->inc[1] = lmmp_seed_generator(seed << 21);
70
71 // warm up
72 pcg64_128_action(rng->state, rng->inc);
73 pcg64_128_action(rng->state, rng->inc);
74}
75
76// (PCG-XSL-RR-128/64)
78 lmmp_param_assert(rng != NULL);
79 mp_limb_t oldstate[2] = {rng->state[0], rng->state[1]};
80 pcg64_128_action(rng->state, rng->inc);
81
82 // XSL-RR
83 mp_limb_t xsl = ((oldstate[1]) ^ oldstate[0]);
84
85 mp_byte_t rot = (mp_byte_t)(oldstate[1] >> 58);
86 return (xsl >> rot) | (xsl << ((-rot) & 63));
87}
88
90 const int shift = k & 63;
91 return (x << shift) | (x >> (64 - shift));
92}
93
95 lmmp_param_assert(rng != NULL);
96 const mp_limb_t r = rotl(rng->s[0] + rng->s[3], 23) + rng->s[0];
97 const mp_limb_t t = rng->s[1] << 17;
98
99 rng->s[2] ^= rng->s[0];
100 rng->s[3] ^= rng->s[1];
101 rng->s[1] ^= rng->s[2];
102 rng->s[0] ^= rng->s[3];
103 rng->s[2] ^= t;
104 rng->s[3] = rotl(rng->s[3], 45);
105
106 return r;
107}
108
110 lmmp_param_assert(rng != NULL);
111
112 rng->s[0] = lmmp_seed_generator(seed);
113 rng->s[1] = lmmp_seed_generator(seed << 17);
114 rng->s[2] = lmmp_seed_generator(0x9e37b97f8a5a7c19ULL ^ seed);
115 rng->s[3] = lmmp_seed_generator(0x8a07e6c7f6b9c92eULL ^ seed);
116
117 // assert that the initial state is non-zero
118 if (rng->s[0] == 0 && rng->s[1] == 0 && rng->s[2] == 0 && rng->s[3] == 0) {
119 rng->s[0] = 0xa12ef3383a3d2eefULL + seed;
120 rng->s[1] = 0xcdfabe82ecd412ceULL + seed;
121 rng->s[2] = 0x90b5ec55c9235815ULL + seed;
122 rng->s[3] = 0xcfb28093ca79a3a7ULL + seed;
123 }
124 // warm up
128}
129
130#define PCG64_LE_MULTIPLIER 6364136223846793005ULL
131#define PCG64_LE_INCREMENT 1442695040888963407ULL
132
133typedef struct {
135 mp_limb_t* restrict state;
137
139 lmmp_param_assert(rng != NULL);
140 lmmp_param_assert(rng->k > 0);
141 lmmp_param_assert(rng->state != NULL);
142
143#define PRIME64_0 0x9E3779B185EBCA87ULL
144#define PRIME64_1 0xC2B2AE3D27D4EB4FULL
145#define PRIME64_2 0x165667B19E3779F9ULL
146#define PRIME64_3 0x85EBCA77C2B2AE63ULL
147#define PRIME64_4 0x27D4EB2F165667C5ULL
148
149 mp_limb_t s0, s1, s2, s3;
150
151 for (; i + 3 < rng->k; i += 4) {
152 s0 = rotl(seed + i + 0, 41);
153 s1 = rotl(seed + i + 1, 29);
154 s2 = rotl(seed + i + 2, 23);
155 s3 = rotl(seed + i + 3, 7);
156 s0 *= PRIME64_0;
157 s1 *= PRIME64_1;
158 s2 *= PRIME64_2;
159 s3 *= PRIME64_3;
160 rng->state[i + 0] = lmmp_seed_generator(s0 ^ rotl(s0, 17));
161 rng->state[i + 1] = lmmp_seed_generator(s1 ^ rotl(s1, 21));
162 rng->state[i + 2] = lmmp_seed_generator(s2 ^ rotl(s2, 13));
163 rng->state[i + 3] = lmmp_seed_generator(s3 ^ rotl(s3, 33));
164 }
165 for (; i < rng->k; i++) {
166 s0 = rotl(seed + i, 31);
167 s0 *= PRIME64_4;
168 rng->state[i] = lmmp_seed_generator(s0 ^ rotl(s0, 27));
169 }
170
171#undef PRIME64_0
172#undef PRIME64_1
173#undef PRIME64_2
174#undef PRIME64_3
175#undef PRIME64_4
176}
177
179 mp_limb_t old_state = *state;
180 *state = old_state * PCG64_LE_MULTIPLIER + PCG64_LE_INCREMENT;
181
182 // RXS-M-XS
183 mp_limb_t x = old_state;
184 int count = x >> 59;
185 x ^= x >> (5 + count);
186 x *= 12605985483714917081ULL;
187 x ^= x >> 43;
188
189 return x;
190}
191
193 lmmp_param_assert(dst != NULL);
194 lmmp_param_assert(rng != NULL);
195 lmmp_param_assert(n <= rng->k);
196 mp_size_t i;
197 mp_limb_t mixn = lmmp_seed_generator(n * 0xb9ce52b55c72d585ULL);
198 for (i = 0; i + 3 < n; i += 4) {
199 dst[i + 0] = pcg64_le_action(&rng->state[i + 0]) ^ mixn;
200 dst[i + 1] = pcg64_le_action(&rng->state[i + 1]) ^ mixn;
201 dst[i + 2] = pcg64_le_action(&rng->state[i + 2]) ^ mixn;
202 dst[i + 3] = pcg64_le_action(&rng->state[i + 3]) ^ mixn;
203 }
204 for (; i < n; i++) {
205 dst[i] = pcg64_le_action(&rng->state[i]) ^ mixn;
206 }
207 for (; i < rng->k; i++) {
208 mp_limb_t old_state = rng->state[i];
209 rng->state[i] = old_state * PCG64_LE_MULTIPLIER + PCG64_LE_INCREMENT;
210 }
211}
212
213#undef INLINE_
214
215#endif // __LAMMP_RAND_STATE_H__
#define k
mp_limb_t * mp_ptr
Definition lmmp.h:215
uint8_t mp_byte_t
Definition lmmp.h:210
uint64_t mp_size_t
Definition lmmp.h:212
uint64_t mp_limb_t
Definition lmmp.h:211
#define lmmp_param_assert(x)
Definition lmmp.h:398
#define _u128add(r, x, y)
Definition longlong.h:260
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
Definition longlong.h:31
#define s1
#define s3
#define s2
static void pcg64_le_seq_init(pcg64_le_seq_t *rng, mp_size_t i, mp_limb_t seed)
Definition rand_state.h:138
mp_limb_t *restrict state
Definition rand_state.h:135
static mp_limb_t lmmp_xoshiro256pp_random(xoshiro256pp_state *rng)
Definition rand_state.h:94
mp_limb_t state[2]
Definition rand_state.h:26
#define PRIME64_0
#define PRIME64_4
static void pcg64_128_action(mp_limb_t state[2], const mp_limb_t inc[2])
Definition rand_state.h:53
static void lmmp_xoshiro256pp_srandom(xoshiro256pp_state *rng, mp_limb_t seed)
Definition rand_state.h:109
mp_size_t k
Definition rand_state.h:134
static mp_limb_t lmmp_seed_generator(mp_limb_t seed)
种子生成器
Definition rand_state.h:46
mp_limb_t inc[2]
Definition rand_state.h:27
#define PCG64_LE_INCREMENT
Definition rand_state.h:131
#define PCG64_LE_MULTIPLIER
Definition rand_state.h:130
static mp_limb_t pcg64_le_action(mp_limb_t *restrict state)
Definition rand_state.h:178
#define PRIME64_1
#define INLINE_
Definition rand_state.h:38
static void lmmp_pcg64_128_srandom(pcg64_128_state *rng, mp_limb_t seed)
Definition rand_state.h:62
#define PCG128_DEFAULT_MULTIPLIER_HI
Definition rand_state.h:34
static mp_limb_t rotl(const mp_limb_t x, int k)
Definition rand_state.h:89
static mp_limb_t lmmp_pcg64_128_random(pcg64_128_state *rng)
Definition rand_state.h:77
static void pcg64_le_seq_next(mp_ptr restrict dst, mp_size_t n, pcg64_le_seq_t *rng)
Definition rand_state.h:192
mp_limb_t s[4]
Definition rand_state.h:31
#define PRIME64_3
#define PCG128_DEFAULT_MULTIPLIER_LO
Definition rand_state.h:35
#define PRIME64_2