LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
mprand.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_MPRAND_H
17#define LAMMP_MPRAND_H
18
19/*
20 本头文件提供的随机数发生器均为非密码学安全的伪随机数生成器,仅用于生成随机数序列。
21 输入种子类型为int时,意味着无需输入高熵的随机数,我们会通过一些额外的信息(生成序列的长度)
22 通过一些简单的算法来生成高熵的新种子(依然可以保证可重用和可复现性)。对于种子类型为
23 其他类型,我们会直接使用输入的种子,我们仍然会在发生器中进行一些处理,以保证最低限度的随机性。
24
25 LAMMP 主要实现了两个随机数引擎:PCG-XSL-RR-128/64 和 xoshiro256++。
26 其中,后者通常为默认的lammp的随机数引擎,生成速度较前者快,大约有1.5倍性能差距。
27 可以参考以下文章了解PCG:<https://www.pcg-random.org/paper.html>
28
29 PCG网站<https://www.pcg-random.org>中也有PCG和xoshiro256++及其他随机生成器的比较。
30
31 PCG-XSL-RR-128/64 生成的随机数序列通常拥有比xoshiro256++更好的统计性能,当然两者的统计性能
32 在大部分场景下都足够的好。生成速度上,在64位平台且吞吐量较好的情况下,各个随机数发生器平均生成
33 单个limb的耗时大致如下:(在生成较短bit长度的随机数时,所有的发生器平均耗时都会提高)
34
35 随机生成器 平均耗时(ns)
36 mt19937 3.9
37 PCG-XSL-RR-128/64 1.3
38 xoshiro256++ 0.8
39 strong_rng 1.4/2.9
40
41 (备注:strong_rng第一个耗时未考虑随机状态初始化的时间,第二个耗时是在初始化状态后,生成单个limb的耗时)
42
43 LAMMP 实现的强随机数生成器,通常用于多次大量生成较长的随机大整数序列,比如用于多次生成
44 1000个limb长度的随机大整数。其随机状态为一个长度为 k 的limb数组,初始状态由种子决定,每个limb代表一个64bit状态,
45 初始状态会由种子和limb的位置通过复杂的hash算法确定,因此初始状态几乎完全不同,用以保证同一个大整数中的各个limb之
46 间几乎没有相关性。
47
48 在生成单个随机大整数时,强随机生成器的总生成速度会显著慢于PCG-XSL-RR-128/64和xoshiro256++,与cpp标准库的
49 梅森旋转法大致相当。这是由于初始化随机状态的巨大开销导致的。在多次生成固定长度的随机大整数序列时,强随机生成
50 器的生成速度则比pcg-xsl-rr-128/64略慢,但仍然快于梅森旋转算法(Mersenne Twister)。
51 */
52
53#include "lmmp.h"
54
55#ifdef __cplusplus
56extern "C" {
57#endif
58
59/**
60 * @brief 初始化全局随机数生成器
61 * @param seed 种子
62 * @param seed_type 随机数发生器类型(0:pcg64_128,1:xoshiro256++)
63 * @warning seed_type 必须在0到1之间,如果不是,则使用 seed_type%2 作为seed_type,
64 * 如果全局种子已经初始化,则会更新全局种子,或更新发生器类型
65 * @note 由于使用int类型作为种子,我们将会维护一个全局种子随机序列,丰富种子的随机性。
66 */
67LAMMP_API void lmmp_global_rng_init_(int seed, int seed_type);
68
69/**
70 * @brief 生成随机大整数(0 - B^n-1 均匀分布)
71 * @param dst 随机数存储位置
72 * @param n dst的 limb 长度
73 * @param seed 种子(建议使用有效位数较多的随机数,以保证随机数质量)
74 * @param seed_type 随机数发生器类型(0:pcg64_128,1:xoshiro256++)
75 * @warning seed_type 必须在0到1之间,如果不是,则使用 seed_type%2 作为seed_type
76 * @return 随机数的 limb 长度(这是由于可能存在生成随机数为0的情况(虽然几乎不可能),
77 * 所以返回值可能小于n,但不会大于n)
78 */
80
81/**
82 * @brief 生成随机大整数(0 - B^n-1 均匀分布)
83 * @param dst 随机数存储位置
84 * @param n dst的 limb 长度
85 * @warning 如果dst==NULL或n==0,则返回0,无其他操作。种子由 lmmp_global_rng_init() 设置,发生器类型由
86 * lmmp_global_rng_init() 设置,如果没有进行全局初始化,则使用默认种子(默认等价设置全局种子为0,
87 * 并不代表全局种子为0)和默认发生器类型(默认为xoshiro256++),即未设置全局种子,行为等价于
88 * 执行了 lmmp_global_rng_init_(0, 1)
89 * @note 每调用一次此函数,种子将会进行一次更新,以确保多次调用时的种子不同,但是只要每次调用的方式
90 * 和顺序相同,在同一个进程中,每次生成的随机数序列相同。
91 * @return 随机数的 limb 长度(由于可能存在生成随机数为0的情况,所以返回值可能小于n,但不会大于n)
92 */
94
95/**
96 * @brief 强随机数生成器结构体
97 * @note 内部状态为一个长度为 k 的limb数组,初始状态由种子决定,每生成一次,内部状态将会更新,
98 * 内部状态的每个维度都是一个64位无符号整数,且可以认为是独立的。故通常情况下,此生成器得到的
99 * 随机数拥有极好的k-维均匀性。对于每个独立的limb,为了提高生成速度,我们使用pcg64-le随机数发生器
100 * 虽然各个limb间算法相同,但初始化状态几乎完全不同。
101 */
103
104/**
105 * @brief 创建k维度强随机数生成器
106 * @param k 随机数长度(单位:limb)
107 * @param seed 种子
108 * @warning k>0
109 * @note 请注意,此操作是一个开销很大的操作,且会分配内存,在仅生成一次的情况下,甚至初始化时间会慢于生成
110 * 一个随机数的时间。
111 * @return 强随机数生成器指针
112 */
114
115/**
116 * @brief 将rng内部状态拓展至k维度
117 * @param rng 强随机数生成器指针
118 * @param k 随机数长度(单位:limb)
119 * @warning rng!=NULL, k>0
120 * @note 若k<=rng->stream.k,则不进行任何操作。否则,将rng内部状态拓展至k维度。
121 */
123
124/**
125 * @brief 销毁强随机数生成器
126 * @param rng 强随机数生成器指针
127 */
129
130/**
131 * @brief 生成n维度强随机数(0 - B^n-1 均匀分布)
132 * @param dst 随机数存储位置(长度为k个limb)
133 * @param n dst的 limb 长度(n<=k)
134 * @param rng 强随机数生成器指针,每生成一次,内部状态将会更新
135 * @warning rng!=NULL, dst!=NULL, 0<n<=k,
136 * @note rng为强随机数生成器指针,每调用一次此函数,内部状态将会更新,以进行重复生成长度相同的随机大整数序列
137 * 此方法生成的随机数序列具有极好的k-维均匀性,单个随机大整数间的各个limb都是几乎完全独立的序列。
138 * @return 随机数的 limb 长度(由于可能存在生成随机数为0的情况,所以返回值可能小于n,但不会大于n)
139 */
141
142#ifdef __cplusplus
143}
144#endif
145
146#endif // LAMMP_MPRAND_H
#define k
mp_limb_t * mp_ptr
Definition lmmp.h:80
uint64_t mp_size_t
Definition lmmp.h:77
uint64_t mp_limb_t
Definition lmmp.h:76
#define LAMMP_API
Definition lmmp.h:61
mp_size_t lmmp_seed_random_(mp_ptr dst, mp_size_t n, mp_limb_t seed, int seed_type)
生成随机大整数(0 - B^n-1 均匀分布)
void lmmp_global_rng_init_(int seed, int seed_type)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition mprand.c:29
void lmmp_strong_rng_free_(lmmp_strong_rng_t *rng)
销毁强随机数生成器
Definition mprand.c:108
mp_size_t lmmp_strong_random_(mp_ptr dst, mp_size_t n, lmmp_strong_rng_t *rng)
生成n维度强随机数(0 - B^n-1 均匀分布)
lmmp_strong_rng_t * lmmp_strong_rng_init_(mp_size_t k, int seed)
创建k维度强随机数生成器
Definition mprand.c:83
void lmmp_strong_rng_extern_(lmmp_strong_rng_t *rng, mp_size_t k)
将rng内部状态拓展至k维度
Definition mprand.c:96
mp_size_t lmmp_random_(mp_ptr dst, mp_size_t n)
生成随机大整数(0 - B^n-1 均匀分布)
#define n