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