NumPy 源码解析(三十五)
.\numpy\numpy\polynomial\__init__.py
"""
A sub-package for efficiently dealing with polynomials.
Within the documentation for this sub-package, a "finite power series,"
i.e., a polynomial (also referred to simply as a "series") is represented
by a 1-D numpy array of the polynomial's coefficients, ordered from lowest
order term to highest. For example, array([1,2,3]) represents
``P_0 + 2*P_1 + 3*P_2``, where P_n is the n-th order basis polynomial
applicable to the specific module in question, e.g., `polynomial` (which
"wraps" the "standard" basis) or `chebyshev`. For optimal performance,
all operations on polynomials, including evaluation at an argument, are
implemented as operations on the coefficients. Additional (module-specific)
information can be found in the docstring for the module of interest.
This package provides *convenience classes* for each of six different kinds
of polynomials:
======================== ================
**Name** **Provides**
======================== ================
`~polynomial.Polynomial` Power series
`~chebyshev.Chebyshev` Chebyshev series
`~legendre.Legendre` Legendre series
`~laguerre.Laguerre` Laguerre series
`~hermite.Hermite` Hermite series
`~hermite_e.HermiteE` HermiteE series
======================== ================
These *convenience classes* provide a consistent interface for creating,
manipulating, and fitting data with polynomials of different bases.
The convenience classes are the preferred interface for the `~numpy.polynomial`
package, and are available from the ``numpy.polynomial`` namespace.
This eliminates the need to navigate to the corresponding submodules, e.g.
``np.polynomial.Polynomial`` or ``np.polynomial.Chebyshev`` instead of
``np.polynomial.polynomial.Polynomial`` or
``np.polynomial.chebyshev.Chebyshev``, respectively.
The classes provide a more consistent and concise interface than the
type-specific functions defined in the submodules for each type of polynomial.
For example, to fit a Chebyshev polynomial with degree ``1`` to data given
by arrays ``xdata`` and ``ydata``, the
`~chebyshev.Chebyshev.fit` class method::
>>> from numpy.polynomial import Chebyshev
>>> xdata = [1, 2, 3, 4]
>>> ydata = [1, 4, 9, 16]
>>> c = Chebyshev.fit(xdata, ydata, deg=1)
is preferred over the `chebyshev.chebfit` function from the
``np.polynomial.chebyshev`` module::
>>> from numpy.polynomial.chebyshev import chebfit
>>> c = chebfit(xdata, ydata, deg=1)
See :doc:`routines.polynomials.classes` for more details.
Convenience Classes
===================
The following lists the various constants and methods common to all of
the classes representing the various kinds of polynomials. In the following,
the term ``Poly`` represents any one of the convenience classes (e.g.
`~polynomial.Polynomial`, `~chebyshev.Chebyshev`, `~hermite.Hermite`, etc.)
while the lowercase ``p`` represents an **instance** of a polynomial class.
Constants
---------
"""
# 设置默认的多项式字符串表示格式
def set_default_printstyle(style):
"""
Set the default format for the string representation of polynomials.
Values for ``style`` must be valid inputs to ``__format__``, i.e. 'ascii'
or 'unicode'.
Parameters
----------
style : str
Format string for default printing style. Must be either 'ascii' or
'unicode'.
Notes
-----
The default format depends on the platform: 'unicode' is used on
Unix-based systems and 'ascii' on Windows. This determination is based on
default font support for the unicode superscript and subscript ranges.
Examples
--------
>>> p = np.polynomial.Polynomial([1, 2, 3])
>>> c = np.polynomial.Chebyshev([1, 2, 3])
>>> np.polynomial.set_default_printstyle('unicode')
>>> print(p)
1.0 + 2.0·x + 3.0·x²
"""
pass
# 默认域
Poly.domain
# 默认窗口
Poly.window
# 用于表示基础的字符串
Poly.basis_name
# 允许的最大幂值,使得 p**n 是被允许的
Poly.maxpower
# 打印时使用的字符串
Poly.nickname
# 创建
# 返回给定阶数的基础多项式
Poly.basis(degree)
# 创建
# 返回多项式 p,其中 p(x) = x 对所有 x 成立
Poly.identity()
# 创建
# 返回与数据 x、y 最小二乘拟合的阶数为 deg 的多项式 p
Poly.fit(x, y, deg)
# 创建
# 返回具有指定根的多项式 p
Poly.fromroots(roots)
# 创建
# 复制多项式 p
p.copy()
# 转换
# 将 p 转换为指定类别 Poly 的实例
p.cast(Poly)
# 转换
# 将 p 转换为指定类别 Poly 的实例或在 domain 和 window 之间进行映射
p.convert(Poly)
# 微积分
# 对 p 求导数
p.deriv()
# 微积分
# 对 p 积分
p.integ()
# 验证
# 检查多项式 p1 和 p2 的系数是否匹配
Poly.has_samecoef(p1, p2)
# 验证
# 检查多项式 p1 和 p2 的域是否匹配
Poly.has_samedomain(p1, p2)
# 验证
# 检查多项式 p1 和 p2 的类型是否匹配
Poly.has_sametype(p1, p2)
# 验证
# 检查多项式 p1 和 p2 的窗口是否匹配
Poly.has_samewindow(p1, p2)
# 杂项
# 在默认域内返回均匀间隔点上的 x, p(x)
p.linspace()
# 杂项
# 返回在 domain 和 window 之间的线性映射参数
p.mapparms()
# 杂项
# 返回多项式 p 的根
p.roots()
# 杂项
# 去除多项式 p 的尾系数
p.trim()
# 杂项
# 截断多项式 p 到给定阶数
p.cutdeg(degree)
# 杂项
# 截断多项式 p 到给定大小
p.truncate(size)
>>> print(c)
1.0 + 2.0·T₁(x) + 3.0·T₂(x)
>>> np.polynomial.set_default_printstyle('ascii')
>>> print(p)
1.0 + 2.0 x + 3.0 x**2
>>> print(c)
1.0 + 2.0 T_1(x) + 3.0 T_2(x)
>>> # Formatting supersedes all class/package-level defaults
>>> print(f"{p:unicode}")
1.0 + 2.0·x + 3.0·x²
"""
if style not in ('unicode', 'ascii'):
raise ValueError(
f"Unsupported format string '{style}'. Valid options are 'ascii' "
f"and 'unicode'"
)
_use_unicode = True
if style == 'ascii':
_use_unicode = False
from ._polybase import ABCPolyBase
ABCPolyBase._use_unicode = _use_unicode
注释:
# 如果样式不是 'unicode' 或 'ascii',则抛出值错误异常,提示有效选项为 'ascii' 和 'unicode'
if style not in ('unicode', 'ascii'):
raise ValueError(
f"Unsupported format string '{style}'. Valid options are 'ascii' "
f"and 'unicode'"
)
# 默认使用 Unicode 格式打印多项式
_use_unicode = True
# 如果选择了 'ascii' 格式,则设置为不使用 Unicode
if style == 'ascii':
_use_unicode = False
# 导入多项式基类,并设置其打印格式为当前选择的格式
from ._polybase import ABCPolyBase
ABCPolyBase._use_unicode = _use_unicode
# 从numpy._pytesttester模块中导入PytestTester类
from numpy._pytesttester import PytestTester
# 创建一个PytestTester对象,并将当前模块的名称作为参数传递
test = PytestTester(__name__)
# 删除当前作用域中的PytestTester类的引用,通常用于清理不再需要的变量或类
del PytestTester
.\numpy\numpy\polynomial\__init__.pyi
# 导入 numpy._pytesttester 模块中的 PytestTester 类
from numpy._pytesttester import PytestTester
# 从 numpy.polynomial 模块中导入以下多项式对象
# chebyshev 对应 numpy.polynomial.chebyshev 模块的别名 chebyshev
# hermite 对应 numpy.polynomial.hermite 模块的别名 hermite
# hermite_e 对应 numpy.polynomial.hermite_e 模块的别名 hermite_e
# laguerre 对应 numpy.polynomial.laguerre 模块的别名 laguerre
# legendre 对应 numpy.polynomial.legendre 模块的别名 legendre
# polynomial 对应 numpy.polynomial.polynomial 模块的别名 polynomial
from numpy.polynomial import (
chebyshev as chebyshev,
hermite as hermite,
hermite_e as hermite_e,
laguerre as laguerre,
legendre as legendre,
polynomial as polynomial,
)
# 从 numpy.polynomial.chebyshev 模块导入 Chebyshev 类,并将其命名为 Chebyshev
from numpy.polynomial.chebyshev import Chebyshev as Chebyshev
# 从 numpy.polynomial.hermite 模块导入 Hermite 类,并将其命名为 Hermite
from numpy.polynomial.hermite import Hermite as Hermite
# 从 numpy.polynomial.hermite_e 模块导入 HermiteE 类,并将其命名为 HermiteE
from numpy.polynomial.hermite_e import HermiteE as HermiteE
# 从 numpy.polynomial.laguerre 模块导入 Laguerre 类,并将其命名为 Laguerre
from numpy.polynomial.laguerre import Laguerre as Laguerre
# 从 numpy.polynomial.legendre 模块导入 Legendre 类,并将其命名为 Legendre
from numpy.polynomial.legendre import Legendre as Legendre
# 从 numpy.polynomial.polynomial 模块导入 Polynomial 类,并将其命名为 Polynomial
from numpy.polynomial.polynomial import Polynomial as Polynomial
# 定义 __all__ 列表,包含可以从当前模块导入的公共名称
__all__: list[str]
# 创建 PytestTester 类的实例 test
test: PytestTester
# 定义一个名为 set_default_printstyle 的函数,接受一个参数 style,并没有具体实现内容
def set_default_printstyle(style): ...
.\numpy\numpy\random\bit_generator.pxd
# 导入必要的Cython模块和类型定义
cimport numpy as np
from libc.stdint cimport uint32_t, uint64_t
# 从numpy/random/bitgen.h中导入bitgen结构体的定义
cdef extern from "numpy/random/bitgen.h":
struct bitgen:
void *state
uint64_t (*next_uint64)(void *st) nogil
uint32_t (*next_uint32)(void *st) nogil
double (*next_double)(void *st) nogil
uint64_t (*next_raw)(void *st) nogil
ctypedef bitgen bitgen_t
# 定义一个Cython类BitGenerator,实现了随机数生成器的接口
cdef class BitGenerator():
cdef readonly object _seed_seq # 私有成员变量,用于种子序列
cdef readonly object lock # 锁对象,用于多线程同步
cdef bitgen_t _bitgen # bitgen结构体对象,实际的随机数生成器
cdef readonly object _ctypes # ctypes对象,用于C语言类型的转换
cdef readonly object _cffi # cffi对象,用于C语言函数接口
cdef readonly object capsule # Python中的胶囊对象
# 定义一个Cython类SeedSequence,用于生成种子序列
cdef class SeedSequence():
cdef readonly object entropy # 私有成员变量,熵源对象
cdef readonly tuple spawn_key # 只读元组,用于生成子序列的键
cdef readonly Py_ssize_t pool_size # 只读整数,池大小
cdef readonly object pool # 只读对象,池对象
cdef readonly uint32_t n_children_spawned # 只读无符号32位整数,生成的子序列数
# 用于混合熵和熵数组的方法定义
cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
np.ndarray[np.npy_uint32, ndim=1] entropy_array)
# 获取组装的熵的方法定义
cdef get_assembled_entropy(self)
# 定义一个简单的Cython类SeedlessSequence,表示没有种子的序列
cdef class SeedlessSequence():
pass
.\numpy\numpy\random\bit_generator.pyi
import abc # 导入抽象基类模块
from threading import Lock # 导入线程锁对象
from collections.abc import Callable, Mapping, Sequence # 导入抽象基类的Callable、Mapping、Sequence
from typing import ( # 导入类型提示相关模块
Any,
NamedTuple,
TypedDict,
TypeVar,
overload,
Literal,
)
from numpy import dtype, uint32, uint64 # 导入numpy的dtype、uint32和uint64类型
from numpy._typing import ( # 导入numpy的类型提示模块
NDArray,
_ArrayLikeInt_co,
_ShapeLike,
_SupportsDType,
_UInt32Codes,
_UInt64Codes,
)
_T = TypeVar("_T") # 定义泛型变量_T
_DTypeLikeUint32 = ( # 定义_DTypeLikeUint32类型,支持uint32类型
dtype[uint32]
| _SupportsDType[dtype[uint32]]
| type[uint32]
| _UInt32Codes
)
_DTypeLikeUint64 = ( # 定义_DTypeLikeUint64类型,支持uint64类型
dtype[uint64]
| _SupportsDType[dtype[uint64]]
| type[uint64]
| _UInt64Codes
)
class _SeedSeqState(TypedDict): # 定义名为_SeedSeqState的字典类型
entropy: None | int | Sequence[int] # 键为entropy,值可以为None、int或int序列
spawn_key: tuple[int, ...] # 键为spawn_key,值为int类型的元组
pool_size: int # 键为pool_size,值为int类型
n_children_spawned: int # 键为n_children_spawned,值为int类型
class _Interface(NamedTuple): # 定义名为_Interface的命名元组
state_address: Any # 元组字段state_address的类型为Any
state: Any # 元组字段state的类型为Any
next_uint64: Any # 元组字段next_uint64的类型为Any
next_uint32: Any # 元组字段next_uint32的类型为Any
next_double: Any # 元组字段next_double的类型为Any
bit_generator: Any # 元组字段bit_generator的类型为Any
class ISeedSequence(abc.ABC): # 定义名为ISeedSequence的抽象基类
@abc.abstractmethod
def generate_state( # 抽象方法generate_state,生成状态
self, n_words: int, dtype: _DTypeLikeUint32 | _DTypeLikeUint64 = ... # 参数n_words为int类型,dtype为_DTypeLikeUint32或_DTypeLikeUint64类型
) -> NDArray[uint32 | uint64]: ... # 返回类型为NDArray[uint32 | uint64]
class ISpawnableSeedSequence(ISeedSequence): # 定义名为ISpawnableSeedSequence的抽象基类,继承自ISeedSequence
@abc.abstractmethod
def spawn(self: _T, n_children: int) -> list[_T]: ... # 抽象方法spawn,生成_T类型的列表,参数n_children为int类型
class SeedlessSeedSequence(ISpawnableSeedSequence): # 定义名为SeedlessSeedSequence的类,继承自ISpawnableSeedSequence
def generate_state( # 实现generate_state方法,生成状态
self, n_words: int, dtype: _DTypeLikeUint32 | _DTypeLikeUint64 = ... # 参数n_words为int类型,dtype为_DTypeLikeUint32或_DTypeLikeUint64类型
) -> NDArray[uint32 | uint64]: ... # 返回类型为NDArray[uint32 | uint64]
def spawn(self: _T, n_children: int) -> list[_T]: ... # 实现spawn方法,生成_T类型的列表,参数n_children为int类型
class SeedSequence(ISpawnableSeedSequence): # 定义名为SeedSequence的类,继承自ISpawnableSeedSequence
entropy: None | int | Sequence[int] # 属性entropy,可以为None、int或int序列
spawn_key: tuple[int, ...] # 属性spawn_key,为int类型的元组
pool_size: int # 属性pool_size,为int类型
n_children_spawned: int # 属性n_children_spawned,为int类型
pool: NDArray[uint32] # 属性pool,类型为NDArray[uint32]
def __init__( # 构造方法__init__
self,
entropy: None | int | Sequence[int] | _ArrayLikeInt_co = ..., # 参数entropy,可以为None、int、int序列或_ArrayLikeInt_co类型
*,
spawn_key: Sequence[int] = ..., # 关键字参数spawn_key,类型为int类型的序列
pool_size: int = ..., # 关键字参数pool_size,类型为int
n_children_spawned: int = ..., # 关键字参数n_children_spawned,类型为int
) -> None: ... # 返回类型为None
def __repr__(self) -> str: ... # 定义__repr__方法,返回类型为str
@property
def state( # 属性state,返回类型为_SeedSeqState
self,
) -> _SeedSeqState: ...
def generate_state( # 实现generate_state方法,生成状态
self, n_words: int, dtype: _DTypeLikeUint32 | _DTypeLikeUint64 = ... # 参数n_words为int类型,dtype为_DTypeLikeUint32或_DTypeLikeUint64类型
) -> NDArray[uint32 | uint64]: ...
def spawn(self, n_children: int) -> list[SeedSequence]: ... # 实现spawn方法,生成SeedSequence类型的列表,参数n_children为int类型
class BitGenerator(abc.ABC): # 定义名为BitGenerator的抽象基类
lock: Lock # 属性lock,类型为Lock对象
def __init__(self, seed: None | _ArrayLikeInt_co | SeedSequence = ...) -> None: ... # 构造方法__init__
def __getstate__(self) -> tuple[dict[str, Any], ISeedSequence]: ... # 定义__getstate__方法,返回类型为元组
def __setstate__( # 定义__setstate__方法
self, state_seed_seq: dict[str, Any] | tuple[dict[str, Any], ISeedSequence] # 参数state_seed_seq,类型为dict[str, Any]或元组
) -> None: ...
def __reduce__( # 定义__reduce__方法
self,
) -> tuple[ # 返回类型为元组
Callable[[str], BitGenerator], # 第一个元素为函数类型,接受str参数,返回BitGenerator对象
tuple[str], # 第二个元素为元组类型,包含一个str类型的元素
tuple[dict[str, Any], ISeedSequence] # 第三个元素为元组类型,包含一个dict[str, Any]和一个ISeedSequence类型的元素
]: ...
@abc.abstractmethod
@property
def state(self) -> Mapping[str, Any]: ... # 抽象属性state,返回类型为Mapping[str, Any]
@state.setter
def state(self, value: Mapping[str, Any]) -> None: ... # state的setter方法,参数value为Mapping[str, Any]类型,返回类型为None
@property
def seed_seq(self) -> ISeedSequence: ... # 属性seed_seq,返回类型为ISeedSequence
# 定义一个方法 spawn,用于生成指定数量的子生成器
def spawn(self, n_children: int) -> list[BitGenerator]: ...
# 重载定义 random_raw 方法,返回类型为 int,用于特定情况下的随机数生成
@overload
def random_raw(self, size: None = ..., output: Literal[True] = ...) -> int: ...
# 重载定义 random_raw 方法,返回类型为 NDArray[uint64],用于特定情况下的随机数生成
@overload
def random_raw(self, size: _ShapeLike = ..., output: Literal[True] = ...) -> NDArray[uint64]: ...
# 重载定义 random_raw 方法,返回类型为 None,用于特定情况下的随机数生成
@overload
def random_raw(self, size: None | _ShapeLike = ..., output: Literal[False] = ...) -> None: ...
# 定义一个 _benchmark 方法,用于执行性能基准测试,接受计数器和方法名作为参数
def _benchmark(self, cnt: int, method: str = ...) -> None: ...
# 定义一个属性方法 ctypes,返回类型为 _Interface,用于访问 ctypes 接口
@property
def ctypes(self) -> _Interface: ...
# 定义一个属性方法 cffi,返回类型为 _Interface,用于访问 cffi 接口
@property
def cffi(self) -> _Interface: ...
.\numpy\numpy\random\bit_generator.pyx
#cython: binding=True
"""
BitGenerator base class and SeedSequence used to seed the BitGenerators.
SeedSequence is derived from Melissa E. O'Neill's C++11 `std::seed_seq`
implementation, as it has a lot of nice properties that we want.
https://gist.github.com/imneme/540829265469e673d045
https://www.pcg-random.org/posts/developing-a-seed_seq-alternative.html
The MIT License (MIT)
Copyright (c) 2015 Melissa E. O'Neill
Copyright (c) 2019 NumPy Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
import abc
import sys
from itertools import cycle
import re
from secrets import randbits
from threading import Lock
from cpython.pycapsule cimport PyCapsule_New
import numpy as np
cimport numpy as np
from ._common cimport (random_raw, benchmark, prepare_ctypes, prepare_cffi)
__all__ = ['SeedSequence', 'BitGenerator']
# Initialize NumPy C API
np.import_array()
# Regular expression to match decimal numbers
DECIMAL_RE = re.compile(r'[0-9]+')
# Constants used for the SeedSequence class
cdef uint32_t DEFAULT_POOL_SIZE = 4 # Appears also in docstring for pool_size
cdef uint32_t INIT_A = 0x43b0d7e5
cdef uint32_t MULT_A = 0x931e8875
cdef uint32_t INIT_B = 0x8b51f9dd
cdef uint32_t MULT_B = 0x58f38ded
cdef uint32_t MIX_MULT_L = 0xca01f9dd
cdef uint32_t MIX_MULT_R = 0x4973f715
cdef uint32_t XSHIFT = np.dtype(np.uint32).itemsize * 8 // 2
cdef uint32_t MASK32 = 0xFFFFFFFF
# Function to convert a Python integer to a uint32 NumPy array
def _int_to_uint32_array(n):
arr = []
if n < 0:
raise ValueError("expected non-negative integer")
if n == 0:
arr.append(np.uint32(n))
# Convert the integer `n` into an array of uint32 values
n = int(n)
while n > 0:
arr.append(np.uint32(n & MASK32))
n //= 2**32
return np.array(arr, dtype=np.uint32)
# Function to coerce an input into a uint32 NumPy array
def _coerce_to_uint32_array(x):
""" Coerce an input to a uint32 array.
If `x` is already a uint32 array, return it directly.
If `x` is a non-negative integer, break it into uint32 words, starting
from the lowest bits.
If `x` is a string starting with "0x", interpret it as a hexadecimal integer.
"""
如果输入是一个 numpy 数组且其类型是 uint32,则直接返回其拷贝。
如果输入是一个字符串:
- 如果以 '0x' 开头,则将其视为十六进制数并转换为整数。
- 否则,如果匹配十进制数字的正则表达式,则将其转换为整数。
- 否则,引发数值错误异常,提示字符串无法识别。
如果输入是一个整数或者 numpy 的整数类型:
- 调用 _int_to_uint32_array 函数将其转换为 uint32 类型的数组并返回。
如果输入是浮点数或者 numpy 的非精确类型:
- 抛出类型错误异常,提示种子必须是整数。
否则:
- 如果输入为空序列,则返回一个空的 uint32 类型数组。
- 否则,对每个元素递归调用 _coerce_to_uint32_array 函数,并将结果拼接成一个大数组返回。
cdef uint32_t hashmix(uint32_t value, uint32_t * hash_const):
# 对 value 进行哈希混合运算,使用 hash_const 数组的第一个元素进行异或操作
value ^= hash_const[0]
# 更新 hash_const 的第一个元素为当前值乘以常数 MULT_A
hash_const[0] *= MULT_A
# 将 value 乘以更新后的 hash_const 的第一个元素
value *= hash_const[0]
# 对 value 进行位移异或操作
value ^= value >> XSHIFT
return value
cdef uint32_t mix(uint32_t x, uint32_t y):
# 计算混合结果,使用给定的常数 MIX_MULT_L 和 MIX_MULT_R
cdef uint32_t result = (MIX_MULT_L * x - MIX_MULT_R * y)
# 对混合结果进行位移异或操作
result ^= result >> XSHIFT
return result
class ISeedSequence(abc.ABC):
"""
Abstract base class for seed sequences.
``BitGenerator`` implementations should treat any object that adheres to
this interface as a seed sequence.
See Also
--------
SeedSequence, SeedlessSeedSequence
"""
@abc.abstractmethod
def generate_state(self, n_words, dtype=np.uint32):
"""
generate_state(n_words, dtype=np.uint32)
Return the requested number of words for PRNG seeding.
A BitGenerator should call this method in its constructor with
an appropriate `n_words` parameter to properly seed itself.
Parameters
----------
n_words : int
dtype : np.uint32 or np.uint64, optional
The size of each word. This should only be either `uint32` or
`uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
requesting `uint64` will draw twice as many bits as `uint32` for
the same `n_words`. This is a convenience for `BitGenerator`\ s that
express their states as `uint64` arrays.
Returns
-------
state : uint32 or uint64 array, shape=(n_words,)
"""
pass
class ISpawnableSeedSequence(ISeedSequence):
"""
Abstract base class for seed sequences that can spawn.
"""
@abc.abstractmethod
def spawn(self, n_children):
"""
spawn(n_children)
Spawn a number of child `SeedSequence` s by extending the
`spawn_key`.
See :ref:`seedsequence-spawn` for additional notes on spawning
children.
Parameters
----------
n_children : int
Returns
-------
seqs : list of `SeedSequence` s
"""
pass
cdef class SeedlessSeedSequence():
"""
A seed sequence for BitGenerators with no need for seed state.
See Also
--------
SeedSequence, ISeedSequence
"""
def generate_state(self, n_words, dtype=np.uint32):
raise NotImplementedError('seedless SeedSequences cannot generate state')
def spawn(self, n_children):
return [self] * n_children
# We cannot directly subclass a `cdef class` type from an `ABC` in Cython, so
# we must register it after the fact.
ISpawnableSeedSequence.register(SeedlessSeedSequence)
cdef class SeedSequence():
"""
SeedSequence(entropy=None, *, spawn_key=(), pool_size=4)
SeedSequence mixes sources of entropy in a reproducible way to set the
initial state for independent and very probably non-overlapping
BitGenerators.
"""
# `SeedSequence`类的文档字符串,说明了如何使用和实例化该类的信息
Once the SeedSequence is instantiated, you can call the `generate_state`
method to get an appropriately sized seed. Calling `spawn(n) <spawn>` will
create ``n`` SeedSequences that can be used to seed independent
BitGenerators, i.e. for different threads.
# 参数部分的说明文档
Parameters
----------
entropy : {None, int, sequence[int]}, optional
The entropy for creating a `SeedSequence`.
All integer values must be non-negative.
spawn_key : {(), sequence[int]}, optional
An additional source of entropy based on the position of this
`SeedSequence` in the tree of such objects created with the
`SeedSequence.spawn` method. Typically, only `SeedSequence.spawn` will
set this, and users will not.
pool_size : {int}, optional
Size of the pooled entropy to store. Default is 4 to give a 128-bit
entropy pool. 8 (for 256 bits) is another reasonable choice if working
with larger PRNGs, but there is very little to be gained by selecting
another value.
n_children_spawned : {int}, optional
The number of children already spawned. Only pass this if
reconstructing a `SeedSequence` from a serialized form.
# 注意事项部分,提供了最佳实践和使用建议
Notes
-----
Best practice for achieving reproducible bit streams is to use
the default ``None`` for the initial entropy, and then use
`SeedSequence.entropy` to log/pickle the `entropy` for reproducibility:
# 示例说明如何使用`SeedSequence`类来生成可重现的随机数种子
>>> sq1 = np.random.SeedSequence()
>>> sq1.entropy
243799254704924441050048792905230269161 # random
>>> sq2 = np.random.SeedSequence(sq1.entropy)
>>> np.all(sq1.generate_state(10) == sq2.generate_state(10))
True
"""
# `SeedSequence`类的初始化方法,接受多个可选参数,并进行相应的初始化操作
def __init__(self, entropy=None, *, spawn_key=(),
pool_size=DEFAULT_POOL_SIZE, n_children_spawned=0):
# 检查并设置熵池的大小,若小于默认值则引发错误
if pool_size < DEFAULT_POOL_SIZE:
raise ValueError("The size of the entropy pool should be at least "
f"{DEFAULT_POOL_SIZE}")
# 如果未提供熵的值,则生成一个默认大小的随机比特串作为熵的值
if entropy is None:
entropy = randbits(pool_size * 32)
# 如果提供的熵的类型不是整数或整数序列,则引发类型错误
elif not isinstance(entropy, (int, np.integer, list, tuple, range,
np.ndarray)):
raise TypeError('SeedSequence expects int or sequence of ints for '
'entropy not {}'.format(entropy))
# 设置对象的属性,包括熵值、生成键、熵池大小和已生成子代的数量
self.entropy = entropy
self.spawn_key = tuple(spawn_key)
self.pool_size = pool_size
self.n_children_spawned = n_children_spawned
# 初始化一个全为零的熵池,数据类型为32位无符号整数
self.pool = np.zeros(pool_size, dtype=np.uint32)
# 调用方法,将初始化时设置的熵值混入到熵池中
self.mix_entropy(self.pool, self.get_assembled_entropy())
def __repr__(self):
# 定义一个字符串列表,用于存放对象表示的各行内容
lines = [
f'{type(self).__name__}(', # 打印对象类型名称
f' entropy={self.entropy!r},', # 打印entropy属性值
]
# 如果spawn_key属性非空,则添加其字符串表示到lines列表中
if self.spawn_key:
lines.append(f' spawn_key={self.spawn_key!r},')
# 如果pool_size属性不等于默认值DEFAULT_POOL_SIZE,则添加其字符串表示到lines列表中
if self.pool_size != DEFAULT_POOL_SIZE:
lines.append(f' pool_size={self.pool_size!r},')
# 如果n_children_spawned属性不等于0,则添加其字符串表示到lines列表中
if self.n_children_spawned != 0:
lines.append(f' n_children_spawned={self.n_children_spawned!r},')
# 添加表示对象构造函数结尾的字符串到lines列表中
lines.append(')')
# 将lines列表中的所有字符串拼接成一个完整的表示对象的文本
text = '\n'.join(lines)
# 返回构造好的对象表示文本
return text
@property
def state(self):
# 返回一个字典,包含对象的指定属性及其对应的值
return {k:getattr(self, k) for k in
['entropy', 'spawn_key', 'pool_size',
'n_children_spawned']
if getattr(self, k) is not None}
cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
np.ndarray[np.npy_uint32, ndim=1] entropy_array):
""" Mix in the given entropy to mixer.
Parameters
----------
mixer : 1D uint32 array, modified in-place
要混合的uint32类型的一维数组,将会就地修改
entropy_array : 1D uint32 array
uint32类型的一维数组,包含要混合的熵数据
"""
cdef uint32_t hash_const[1]
hash_const[0] = INIT_A
# 将熵数据混合到mixer数组中,直到达到池大小
for i in range(len(mixer)):
if i < len(entropy_array):
mixer[i] = hashmix(entropy_array[i], hash_const)
else:
# 如果我们的池大小大于熵数据的长度,继续运行哈希函数
mixer[i] = hashmix(0, hash_const)
# 将所有位混合在一起,以便后面的位可以影响前面的位
for i_src in range(len(mixer)):
for i_dst in range(len(mixer)):
if i_src != i_dst:
mixer[i_dst] = mix(mixer[i_dst],
hashmix(mixer[i_src], hash_const))
# 添加剩余的熵数据,将每个新的熵词与每个池词混合
for i_src in range(len(mixer), len(entropy_array)):
for i_dst in range(len(mixer)):
mixer[i_dst] = mix(mixer[i_dst],
hashmix(entropy_array[i_src], hash_const))
# 定义一个方法,用于获取汇总的熵源并将它们转换成统一的 uint32 数组
def get_assembled_entropy(self):
""" Convert and assemble all entropy sources into a uniform uint32
array.
Returns
-------
entropy_array : 1D uint32 array
"""
# 确保至少有一些运行熵(run-entropy),其他是可选的
assert self.entropy is not None
# 将运行熵(run-entropy)转换为 uint32 数组
run_entropy = _coerce_to_uint32_array(self.entropy)
# 将生成密钥(spawn key)转换为 uint32 数组
spawn_entropy = _coerce_to_uint32_array(self.spawn_key)
# 如果生成密钥(spawn key)的长度大于0,并且运行熵(run-entropy)长度小于池大小(pool_size)
if len(spawn_entropy) > 0 and len(run_entropy) < self.pool_size:
# 显式使用0填充熵直到达到池大小,以避免与生成密钥(spawn key)冲突
# 我们在1.19.0中更改了这一点以修复 gh-16539。为了保持与未生成的 SeedSequence
# 具有小熵输入的流兼容性,仅在指定 spawn_key 时才执行此操作。
diff = self.pool_size - len(run_entropy)
run_entropy = np.concatenate(
[run_entropy, np.zeros(diff, dtype=np.uint32)])
# 将运行熵(run-entropy)和生成密钥(spawn key)数组拼接起来
entropy_array = np.concatenate([run_entropy, spawn_entropy])
# 返回汇总后的熵数组
return entropy_array
@np.errstate(over='ignore')
def generate_state(self, n_words, dtype=np.uint32):
"""
generate_state(n_words, dtype=np.uint32)
Return the requested number of words for PRNG seeding.
A BitGenerator should call this method in its constructor with
an appropriate `n_words` parameter to properly seed itself.
Parameters
----------
n_words : int
Number of words (32-bit or 64-bit) to generate for seeding.
dtype : np.uint32 or np.uint64, optional
The size of each word. This should only be either `uint32` or
`uint64`. Strings (`'uint32'`, `'uint64'`) are acceptable.
Returns
-------
state : uint32 or uint64 array, shape=(n_words,)
Array of generated seed values in uint32 or uint64 format.
"""
# Initialize the constant hash value for seeding
cdef uint32_t hash_const = INIT_B
# Variable to hold each data value during processing
cdef uint32_t data_val
# Determine the output data type
out_dtype = np.dtype(dtype)
if out_dtype == np.dtype(np.uint32):
# No action needed for uint32
pass
elif out_dtype == np.dtype(np.uint64):
# Double the number of words for uint64
n_words *= 2
else:
# Raise an error for unsupported types
raise ValueError("only support uint32 or uint64")
# Initialize an array to store the generated state
state = np.zeros(n_words, dtype=np.uint32)
# Create a cycling iterator over the entropy pool
src_cycle = cycle(self.pool)
# Generate the seed values
for i_dst in range(n_words):
data_val = next(src_cycle)
data_val ^= hash_const
hash_const *= MULT_B
data_val *= hash_const
data_val ^= data_val >> XSHIFT
state[i_dst] = data_val
# If output type is uint64, ensure endianness consistency
if out_dtype == np.dtype(np.uint64):
# View as little-endian and then convert to native endianness
state = state.astype('<u4').view('<u8').astype(np.uint64)
# Return the generated state array
return state
def spawn(self, n_children):
"""
spawn(n_children)
Spawn a number of child `SeedSequence`s by extending the
`spawn_key`.
Parameters
----------
n_children : int
Number of child SeedSequences to spawn.
Returns
-------
seqs : list of `SeedSequence`s
List containing the spawned SeedSequence objects.
See Also
--------
random.Generator.spawn, random.BitGenerator.spawn :
Equivalent method on the generator and bit generator.
"""
# Variable to hold the index during iteration
cdef uint32_t i
# List to store spawned SeedSequence objects
seqs = []
# Iterate over the range of children to spawn
for i in range(self.n_children_spawned,
self.n_children_spawned + n_children):
# Append a new SeedSequence object to the list
seqs.append(type(self)(
self.entropy,
spawn_key=self.spawn_key + (i,),
pool_size=self.pool_size,
))
# Update the count of spawned children
self.n_children_spawned += n_children
# Return the list of spawned SeedSequence objects
return seqs
# 注册 SeedSequence 到 ISpawnableSeedSequence 接口
ISpawnableSeedSequence.register(SeedSequence)
# 定义 BitGenerator 类
cdef class BitGenerator():
"""
BitGenerator(seed=None)
Base Class for generic BitGenerators, which provide a stream
of random bits based on different algorithms. Must be overridden.
Parameters
----------
seed : {None, int, array_like[ints], SeedSequence}, optional
A seed to initialize the `BitGenerator`. If None, then fresh,
unpredictable entropy will be pulled from the OS. If an ``int`` or
``array_like[ints]`` is passed, then it will be passed to
`~numpy.random.SeedSequence` to derive the initial `BitGenerator` state.
One may also pass in a `SeedSequence` instance.
All integer values must be non-negative.
Attributes
----------
lock : threading.Lock
Lock instance that is shared so that the same BitGenerator can
be used in multiple Generators without corrupting the state. Code that
generates values from a bit generator should hold the bit generator's
lock.
See Also
--------
SeedSequence
"""
def __init__(self, seed=None):
# 初始化一个线程锁
self.lock = Lock()
# 初始化 _bitgen 状态为 void 指针的 0 值
self._bitgen.state = <void *>0
# 如果实例化的类是 BitGenerator 自身,则抛出未实现错误
if type(self) is BitGenerator:
raise NotImplementedError('BitGenerator is a base class and cannot be instantized')
# 初始化 _ctypes 和 _cffi 为 None
self._ctypes = None
self._cffi = None
# 定义常量字符串 name 为 "BitGenerator"
cdef const char *name = "BitGenerator"
# 创建一个 Python Capsule 对象,封装 self._bitgen 的 void 指针
self.capsule = PyCapsule_New(<void *>&self._bitgen, name, NULL)
# 如果 seed 不是 ISeedSequence 的实例,则将其转换为 SeedSequence 实例
if not isinstance(seed, ISeedSequence):
seed = SeedSequence(seed)
# 设置 _seed_seq 为传入的 seed
self._seed_seq = seed
# Pickling support:
def __getstate__(self):
# 返回对象的状态和 _seed_seq
return self.state, self._seed_seq
def __setstate__(self, state_seed_seq):
# 如果状态是字典,则为兼容性路径,之前的版本只保存了底层位生成器的状态
if isinstance(state_seed_seq, dict):
self.state = state_seed_seq
else:
# 否则设置 _seed_seq 和 state
self._seed_seq = state_seed_seq[1]
self.state = state_seed_seq[0]
def __reduce__(self):
from ._pickle import __bit_generator_ctor
# 返回对象的 pickle 反序列化信息
return (
__bit_generator_ctor,
(type(self), ),
(self.state, self._seed_seq)
)
@property
def state(self):
"""
Get or set the PRNG state
The base BitGenerator.state must be overridden by a subclass
Returns
-------
state : dict
Dictionary containing the information required to describe the
state of the PRNG
"""
# 抛出未实现错误,子类必须重写此方法
raise NotImplementedError('Not implemented in base BitGenerator')
@state.setter
def state(self, value):
# 抛出未实现错误,子类必须重写此方法
raise NotImplementedError('Not implemented in base BitGenerator')
@property
def seed_seq(self):
"""
Get the seed sequence used to initialize the bit generator.
.. versionadded:: 1.25.0
Returns
-------
seed_seq : ISeedSequence
The SeedSequence object used to initialize the BitGenerator.
This is normally a `np.random.SeedSequence` instance.
"""
# 返回当前对象的 _seed_seq 属性,用于初始化位生成器的种子序列
return self._seed_seq
def spawn(self, int n_children):
"""
spawn(n_children)
Create new independent child bit generators.
See :ref:`seedsequence-spawn` for additional notes on spawning
children. Some bit generators also implement ``jumped``
as a different approach for creating independent streams.
.. versionadded:: 1.25.0
Parameters
----------
n_children : int
Number of child bit generators to create.
Returns
-------
child_bit_generators : list of BitGenerators
List containing newly created child BitGenerator instances.
Raises
------
TypeError
When the underlying SeedSequence does not implement spawning.
See Also
--------
random.Generator.spawn, random.SeedSequence.spawn :
Equivalent method on the generator and seed sequence.
"""
# 检查 _seed_seq 属性是否实现了 ISpawnableSeedSequence 接口,如果没有则抛出 TypeError 异常
if not isinstance(self._seed_seq, ISpawnableSeedSequence):
raise TypeError(
"The underlying SeedSequence does not implement spawning.")
# 使用 _seed_seq 的 spawn 方法创建指定数量的子位生成器,并返回这些生成器组成的列表
return [type(self)(seed=s) for s in self._seed_seq.spawn(n_children)]
def random_raw(self, size=None, output=True):
"""
random_raw(self, size=None)
Return randoms as generated by the underlying BitGenerator
Parameters
----------
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
output : bool, optional
Output values. Used for performance testing since the generated
values are not returned.
Returns
-------
out : uint or ndarray
Drawn samples.
Notes
-----
This method directly exposes the raw underlying pseudo-random
number generator. All values are returned as unsigned 64-bit
values irrespective of the number of bits produced by the PRNG.
See the class docstring for the number of bits returned.
"""
# 调用 random_raw 函数,使用 _bitgen 和 self.lock 作为参数,生成指定大小的随机数或数组,并返回结果
return random_raw(&self._bitgen, self.lock, size, output)
def _benchmark(self, Py_ssize_t cnt, method='uint64'):
"""Used in tests"""
# 调用 _benchmark 函数,使用 _bitgen、self.lock 和 cnt 作为参数,并返回基准测试结果
return benchmark(&self._bitgen, self.lock, cnt, method)
@property
# 定义一个方法 ctypes,用于获取 ctypes 接口
def ctypes(self):
"""
ctypes interface
Returns
-------
interface : namedtuple
Named tuple containing ctypes wrapper
* state_address - Memory address of the state struct
* state - pointer to the state struct
* next_uint64 - function pointer to produce 64 bit integers
* next_uint32 - function pointer to produce 32 bit integers
* next_double - function pointer to produce doubles
* bitgen - pointer to the bit generator struct
"""
# 如果 self._ctypes 属性为 None,则调用 prepare_ctypes 函数初始化它
if self._ctypes is None:
self._ctypes = prepare_ctypes(&self._bitgen)
# 返回 self._ctypes 属性,即包含 ctypes 接口的命名元组
return self._ctypes
@property
# 定义一个属性 cffi,用于获取 CFFI 接口
def cffi(self):
"""
CFFI interface
Returns
-------
interface : namedtuple
Named tuple containing CFFI wrapper
* state_address - Memory address of the state struct
* state - pointer to the state struct
* next_uint64 - function pointer to produce 64 bit integers
* next_uint32 - function pointer to produce 32 bit integers
* next_double - function pointer to produce doubles
* bitgen - pointer to the bit generator struct
"""
# 如果 self._cffi 属性为 None,则调用 prepare_cffi 函数初始化它
if self._cffi is None:
self._cffi = prepare_cffi(&self._bitgen)
# 返回 self._cffi 属性,即包含 CFFI 接口的命名元组
return self._cffi
.\numpy\numpy\random\c_distributions.pxd
# 导入必要的模块和类型定义
# 设置 Cython 编译选项:禁用循环包装、空指针检查、边界检查,启用 C 除法,语言级别为 Python 3
#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3
# 从 numpy 中导入指定类型 npy_intp
from numpy cimport npy_intp
# 从 C 标准库中导入指定类型和结构体
from libc.stdint cimport (uint64_t, int32_t, int64_t)
# 从 numpy.random 模块中导入 bitgen_t 类型
from numpy.random cimport bitgen_t
# 从 numpy/random/distributions.h 头文件中引入以下函数和结构体的定义
# 定义二项分布结构体 s_binomial_t,包含多个字段
cdef extern from "numpy/random/distributions.h":
struct s_binomial_t:
int has_binomial
double psave
int64_t nsave
double r
double q
double fm
int64_t m
double p1
double xm
double xl
double xr
double c
double laml
double lamr
double p2
double p3
double p4
# 为 s_binomial_t 结构体定义别名 binomial_t
ctypedef s_binomial_t binomial_t
# 下面列出了一系列用于生成随机数的函数声明,这些函数使用 bitgen_t 类型的参数,并在无 GIL 的环境下执行
# 生成标准均匀分布的随机浮点数,双精度版本
float random_standard_uniform_f(bitgen_t *bitgen_state) nogil
# 生成标准均匀分布的随机双精度数,无 GIL
double random_standard_uniform(bitgen_t *bitgen_state) nogil
# 生成标准均匀分布的随机浮点数数组,无 GIL
void random_standard_uniform_fill(bitgen_t* bitgen_state, npy_intp cnt, double *out) nogil
# 生成标准均匀分布的随机单精度数数组,无 GIL
void random_standard_uniform_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) nogil
# 生成标准指数分布的随机双精度数,无 GIL
double random_standard_exponential(bitgen_t *bitgen_state) nogil
# 生成标准指数分布的随机单精度数,无 GIL
float random_standard_exponential_f(bitgen_t *bitgen_state) nogil
# 生成标准指数分布的随机双精度数数组,无 GIL
void random_standard_exponential_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
# 生成标准指数分布的随机单精度数数组,无 GIL
void random_standard_exponential_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) nogil
# 生成标准指数分布的逆函数的随机双精度数数组,无 GIL
void random_standard_exponential_inv_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
# 生成标准指数分布的逆函数的随机单精度数数组,无 GIL
void random_standard_exponential_inv_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) nogil
# 生成标准正态分布的随机双精度数,无 GIL
double random_standard_normal(bitgen_t* bitgen_state) nogil
# 生成标准正态分布的随机单精度数,无 GIL
float random_standard_normal_f(bitgen_t *bitgen_state) nogil
# 生成标准正态分布的随机双精度数数组,无 GIL
void random_standard_normal_fill(bitgen_t *bitgen_state, npy_intp count, double *out) nogil
# 生成标准正态分布的随机单精度数数组,无 GIL
void random_standard_normal_fill_f(bitgen_t *bitgen_state, npy_intp count, float *out) nogil
# 生成标准 Gamma 分布的随机双精度数,无 GIL
double random_standard_gamma(bitgen_t *bitgen_state, double shape) nogil
# 生成标准 Gamma 分布的随机单精度数,无 GIL
float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
# 下面是重复声明,已经在前面出现过的函数,这里再次声明,保持完整性
float random_standard_uniform_f(bitgen_t *bitgen_state) nogil
void random_standard_uniform_fill_f(bitgen_t* bitgen_state, npy_intp cnt, float *out) nogil
float random_standard_normal_f(bitgen_t* bitgen_state) nogil
float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
# 生成正整数范围内的随机 int64_t 数,无 GIL
int64_t random_positive_int64(bitgen_t *bitgen_state) nogil
# 生成正整数范围内的随机 int32_t 数,无 GIL
int32_t random_positive_int32(bitgen_t *bitgen_state) nogil
# 生成正整数范围内的随机 int64_t 数,无 GIL
int64_t random_positive_int(bitgen_t *bitgen_state) nogil
# 生成随机的 uint64_t 数,无 GIL
uint64_t random_uint(bitgen_t *bitgen_state) nogil
# 生成正态分布的随机双精度数,指定均值和标准差,无 GIL
double random_normal(bitgen_t *bitgen_state, double loc, double scale) nogil
# 生成 Gamma 分布的随机双精度数,指定形状和尺度参数,无 GIL
double random_gamma(bitgen_t *bitgen_state, double shape, double scale) nogil
# 生成 Gamma 分布的随机单精度数,指定形状和尺度参数,无 GIL
float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale) nogil
# 生成指数分布的随机双精度数,指定尺度参数,无 GIL
double random_exponential(bitgen_t *bitgen_state, double scale) nogil
# 生成均匀分布的随机双精度数,指定下限和范围,无 GIL
double random_uniform(bitgen_t *bitgen_state, double lower, double range) nogil
// 生成符合 Beta 分布的随机数
double random_beta(bitgen_t *bitgen_state, double a, double b) nogil
// 生成符合自由度为 df 的卡方分布的随机数
double random_chisquare(bitgen_t *bitgen_state, double df) nogil
// 生成符合自由度为 dfnum 和 dfden 的 F 分布的随机数
double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) nogil
// 生成符合标准 Cauchy 分布的随机数
double random_standard_cauchy(bitgen_t *bitgen_state) nogil
// 生成符合参数 a 的 Pareto 分布的随机数
double random_pareto(bitgen_t *bitgen_state, double a) nogil
// 生成符合参数 a 的 Weibull 分布的随机数
double random_weibull(bitgen_t *bitgen_state, double a) nogil
// 生成符合参数 a 的 Power 分布的随机数
double random_power(bitgen_t *bitgen_state, double a) nogil
// 生成符合参数 loc 和 scale 的 Laplace (Double Exponential) 分布的随机数
double random_laplace(bitgen_t *bitgen_state, double loc, double scale) nogil
// 生成符合参数 loc 和 scale 的 Gumbel (Extreme Value Type I) 分布的随机数
double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) nogil
// 生成符合参数 loc 和 scale 的 Logistic 分布的随机数
double random_logistic(bitgen_t *bitgen_state, double loc, double scale) nogil
// 生成符合参数 mean 和 sigma 的对数正态分布的随机数
double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) nogil
// 生成符合参数 mode 的 Rayleigh 分布的随机数
double random_rayleigh(bitgen_t *bitgen_state, double mode) nogil
// 生成符合自由度为 df 的标准 t 分布的随机数
double random_standard_t(bitgen_t *bitgen_state, double df) nogil
// 生成符合非中心卡方分布的随机数,参数为自由度 df 和非中心参数 nonc
double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc) nogil
// 生成符合非中心 F 分布的随机数,参数为自由度 dfnum、dfden 和非中心参数 nonc
double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden, double nonc) nogil
// 生成符合参数 mean 和 scale 的 Wald (Inverse Gaussian) 分布的随机数
double random_wald(bitgen_t *bitgen_state, double mean, double scale) nogil
// 生成符合参数 mu 和 kappa 的 von Mises 分布的随机数
double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) nogil
// 生成符合参数 left、mode 和 right 的三角分布的随机数
double random_triangular(bitgen_t *bitgen_state, double left, double mode, double right) nogil
// 生成符合参数 lam 的泊松分布的随机整数
int64_t random_poisson(bitgen_t *bitgen_state, double lam) nogil
// 生成符合参数 n 和 p 的负二项分布的随机整数
int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p) nogil
// 生成符合参数 p 和 n 的二项分布的随机整数
int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) nogil
// 生成符合参数 p 的对数级数分布的随机整数
int64_t random_logseries(bitgen_t *bitgen_state, double p) nogil
// 使用搜索法生成符合参数 p 的几何分布的随机整数
int64_t random_geometric_search(bitgen_t *bitgen_state, double p) nogil
// 使用反演法生成符合参数 p 的几何分布的随机整数
int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) nogil
// 生成符合参数 p 的几何分布的随机整数
int64_t random_geometric(bitgen_t *bitgen_state, double p) nogil
// 生成符合参数 a 的 Zipf 分布的随机整数
int64_t random_zipf(bitgen_t *bitgen_state, double a) nogil
// 生成符合参数 good、bad 和 sample 的超几何分布的随机整数
int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad, int64_t sample) nogil
// 生成在闭区间 [0, max] 内的随机整数
uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) nogil
// 生成在闭区间 [off, off + rng] 内的随机 uint64 数字
uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off, uint64_t rng, uint64_t mask, bint use_masked) nogil
// 生成符合多项式分布的随机数,参数为 n(试验次数)、mnix(结果数组)、pix(概率数组)、d(数组长度)、binomial(二项分布辅助对象)
void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix, double *pix, npy_intp d, binomial_t *binomial) nogil
# 计算多元超几何分布的随机数计数
int random_multivariate_hypergeometric_count(bitgen_t *bitgen_state,
int64_t total,
size_t num_colors, int64_t *colors,
int64_t nsample,
size_t num_variates, int64_t *variates) nogil
{
# 用于存储每个变量的超几何分布计数结果
int result;
# 使用快速判断方法,初始化bitgen_state
setup_bitgen_for_normal_distribution(bitgen_state);
for (size_t i = 0; i < num_variates; ++i) {
# 采用较大的数,use max_value from the colors[i]
to_max_value[i] += total;
}
'
.\numpy\numpy\random\include\aligned_malloc.h
#ifndef _RANDOMDGEN__ALIGNED_MALLOC_H_
#define _RANDOMDGEN__ALIGNED_MALLOC_H_
#include <Python.h>
#include "numpy/npy_common.h"
#define NPY_MEMALIGN 16 /* 内存对齐要求,为 SSE2 设置为16,AVX 设置为32,Xeon Phi 设置为64 */
// 重新分配对齐内存的函数,支持按需分配
static inline void *PyArray_realloc_aligned(void *p, size_t n)
{
void *p1, **p2, *base;
size_t old_offs, offs = NPY_MEMALIGN - 1 + sizeof(void *);
// 如果指针 p 不为空,进行重新分配操作
if (NPY_UNLIKELY(p != NULL))
{
// 获取原始分配的基地址
base = *(((void **)p) - 1);
// 尝试重新分配内存,以满足新的大小要求
if (NPY_UNLIKELY((p1 = PyMem_Realloc(base, n + offs)) == NULL))
return NULL;
// 如果重新分配后的地址和原地址相同,则直接返回原指针 p
if (NPY_LIKELY(p1 == base))
return p;
// 计算新的对齐地址并进行数据的移动
p2 = (void **)(((Py_uintptr_t)(p1) + offs) & ~(NPY_MEMALIGN - 1));
old_offs = (size_t)((Py_uintptr_t)p - (Py_uintptr_t)base);
memmove((void *)p2, ((char *)p1) + old_offs, n);
}
else
{
// 如果 p 为空,直接分配新的对齐内存
if (NPY_UNLIKELY((p1 = PyMem_Malloc(n + offs)) == NULL))
return NULL;
// 计算新的对齐地址
p2 = (void **)(((Py_uintptr_t)(p1) + offs) & ~(NPY_MEMALIGN - 1));
}
// 记录分配的基地址,并返回对齐后的指针
*(p2 - 1) = p1;
return (void *)p2;
}
// 分配对齐内存的函数,直接调用 PyArray_realloc_aligned,并传入空指针 p
static inline void *PyArray_malloc_aligned(size_t n)
{
return PyArray_realloc_aligned(NULL, n);
}
// 分配并清零对齐内存的函数,调用 PyArray_realloc_aligned,并在分配后使用 memset 清零
static inline void *PyArray_calloc_aligned(size_t n, size_t s)
{
void *p;
// 分配 n*s 大小的对齐内存
if (NPY_UNLIKELY((p = PyArray_realloc_aligned(NULL, n * s)) == NULL))
return NULL;
// 清零分配的内存
memset(p, 0, n * s);
return p;
}
// 释放对齐内存的函数,通过基地址释放内存
static inline void PyArray_free_aligned(void *p)
{
void *base = *(((void **)p) - 1);
PyMem_Free(base);
}
#endif
.\numpy\numpy\random\include\legacy-distributions.h
#ifndef _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_
#define _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_
// 包含 numpy 随机数分布头文件
#include "numpy/random/distributions.h"
// 定义增强型比特生成器结构体
typedef struct aug_bitgen {
bitgen_t *bit_generator; // 指向比特生成器的指针
int has_gauss; // 是否已生成高斯数标志
double gauss; // 存储上一个生成的高斯数值
} aug_bitgen_t;
// 下面是各种随机数分布的函数声明
// 产生服从正态分布的随机数
extern double legacy_gauss(aug_bitgen_t *aug_state);
// 产生标准指数分布的随机数
extern double legacy_standard_exponential(aug_bitgen_t *aug_state);
// 产生帕累托分布的随机数
extern double legacy_pareto(aug_bitgen_t *aug_state, double a);
// 产生威布尔分布的随机数
extern double legacy_weibull(aug_bitgen_t *aug_state, double a);
// 产生幂律分布的随机数
extern double legacy_power(aug_bitgen_t *aug_state, double a);
// 产生伽马分布的随机数
extern double legacy_gamma(aug_bitgen_t *aug_state, double shape, double scale);
// 产生卡方分布的随机数
extern double legacy_chisquare(aug_bitgen_t *aug_state, double df);
// 产生雷利分布的随机数
extern double legacy_rayleigh(bitgen_t *bitgen_state, double mode);
// 产生非中心卡方分布的随机数
extern double legacy_noncentral_chisquare(aug_bitgen_t *aug_state, double df,
double nonc);
// 产生非中心 F 分布的随机数
extern double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum,
double dfden, double nonc);
// 产生瓦尔德分布的随机数
extern double legacy_wald(aug_bitgen_t *aug_state, double mean, double scale);
// 产生对数正态分布的随机数
extern double legacy_lognormal(aug_bitgen_t *aug_state, double mean,
double sigma);
// 产生标准 t 分布的随机数
extern double legacy_standard_t(aug_bitgen_t *aug_state, double df);
// 产生标准柯西分布的随机数
extern double legacy_standard_cauchy(aug_bitgen_t *state);
// 产生贝塔分布的随机数
extern double legacy_beta(aug_bitgen_t *aug_state, double a, double b);
// 产生 F 分布的随机数
extern double legacy_f(aug_bitgen_t *aug_state, double dfnum, double dfden);
// 产生正态分布的随机数
extern double legacy_normal(aug_bitgen_t *aug_state, double loc, double scale);
// 产生标准伽马分布的随机数
extern double legacy_standard_gamma(aug_bitgen_t *aug_state, double shape);
// 产生指数分布的随机数
extern double legacy_exponential(aug_bitgen_t *aug_state, double scale);
// 产生冯·米塞斯分布的随机数
extern double legacy_vonmises(bitgen_t *bitgen_state, double mu, double kappa);
// 产生二项分布的随机数
extern int64_t legacy_random_binomial(bitgen_t *bitgen_state, double p,
int64_t n, binomial_t *binomial);
// 产生负二项分布的随机数
extern int64_t legacy_negative_binomial(aug_bitgen_t *aug_state, double n,
double p);
// 产生超几何分布的随机数
extern int64_t legacy_random_hypergeometric(bitgen_t *bitgen_state,
int64_t good, int64_t bad,
int64_t sample);
// 产生对数级数分布的随机数
extern int64_t legacy_logseries(bitgen_t *bitgen_state, double p);
// 产生泊松分布的随机数
extern int64_t legacy_random_poisson(bitgen_t *bitgen_state, double lam);
// 产生 Zipf 分布的随机数
extern int64_t legacy_random_zipf(bitgen_t *bitgen_state, double a);
// 产生几何分布的随机数
extern int64_t legacy_random_geometric(bitgen_t *bitgen_state, double p);
// 多项式分布的随机数生成函数声明
void legacy_random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n,
RAND_INT_TYPE *mnix, double *pix, npy_intp d,
binomial_t *binomial);
#endif // _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_
This software is dual-licensed under the The University of Illinois/NCSA Open Source License (NCSA) and The 3-Clause BSD License
NCSA Open Source License
Copyright (c) 2019 Kevin Sheppard. All rights reserved.
Developed by: Kevin Sheppard (kevin.sheppard@economics.ox.ac.uk, kevin.k.sheppard@gmail.com) www.kevinsheppard.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution.
Neither the names of Kevin Sheppard, nor the names of any contributors may be used to endorse or promote products derived from this Software without specific prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
3-Clause BSD License
Copyright (c) 2019 Kevin Sheppard. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Components
Many parts of this module have been derived from original sources, often the algorithm's designer. Component licenses are located with the component code.
.\numpy\numpy\random\mtrand.pyi
# 导入内置模块 builtins,提供内置函数和异常
import builtins
# 从 collections.abc 模块导入 Callable 抽象基类,用于支持函数调用的类型提示
from collections.abc import Callable
# 从 typing 模块导入 Any、overload、Literal 类型提示
from typing import Any, overload, Literal
# 导入 NumPy 库,并从中导入所需的数据类型和函数
import numpy as np
from numpy import (
dtype, # 导入 dtype 类型,用于定义数组的数据类型
float32, # 32 位浮点数数据类型
float64, # 64 位浮点数数据类型
int8, # 8 位整数数据类型
int16, # 16 位整数数据类型
int32, # 32 位整数数据类型
int64, # 64 位整数数据类型
int_, # int 的别名,用于通用整数类型
long, # Python 2 中的长整数类型,在 Python 3 中为 int 的别名
uint8, # 无符号 8 位整数数据类型
uint16, # 无符号 16 位整数数据类型
uint32, # 无符号 32 位整数数据类型
uint64, # 无符号 64 位整数数据类型
uint, # 无符号整数类型
ulong, # 无符号长整数类型
)
# 从 numpy.random.bit_generator 模块导入 BitGenerator 类,用于生成随机数的位生成器
from numpy.random.bit_generator import BitGenerator
# 从 numpy._typing 模块导入各种类型提示,用于定义数组及其元素的类型
from numpy._typing import (
ArrayLike, # 数组或类数组类型提示
NDArray, # NumPy 数组类型提示
_ArrayLikeFloat_co, # 兼容浮点数的数组或类数组类型提示
_ArrayLikeInt_co, # 兼容整数的数组或类数组类型提示
_DoubleCodes, # 双精度浮点数代码提示
_DTypeLikeBool, # 布尔类型数据类型提示
_DTypeLikeInt, # 整数类型数据类型提示
_DTypeLikeUInt, # 无符号整数类型数据类型提示
_Float32Codes, # 单精度浮点数代码提示
_Float64Codes, # 双精度浮点数代码提示
_Int8Codes, # 8 位整数代码提示
_Int16Codes, # 16 位整数代码提示
_Int32Codes, # 32 位整数代码提示
_Int64Codes, # 64 位整数代码提示
_IntCodes, # 整数代码提示
_LongCodes, # 长整数代码提示
_ShapeLike, # 数组形状的类型提示
_SingleCodes, # 单精度浮点数代码提示
_SupportsDType, # 支持数据类型的通用类型提示
_UInt8Codes, # 无符号 8 位整数代码提示
_UInt16Codes, # 无符号 16 位整数代码提示
_UInt32Codes, # 无符号 32 位整数代码提示
_UInt64Codes, # 无符号 64 位整数代码提示
_UIntCodes, # 无符号整数代码提示
_ULongCodes, # 无符号长整数代码提示
)
# 定义 _DTypeLikeFloat32 类型别名,包括 float32 数据类型及其支持的相关代码提示
_DTypeLikeFloat32 = (
dtype[float32]
| _SupportsDType[dtype[float32]]
| type[float32]
| _Float32Codes
| _SingleCodes
)
# 定义 _DTypeLikeFloat64 类型别名,包括 float64 数据类型及其支持的相关代码提示
_DTypeLikeFloat64 = (
dtype[float64]
| _SupportsDType[dtype[float64]]
| type[float]
| type[float64]
| _Float64Codes
| _DoubleCodes
)
# 定义 RandomState 类,用于生成随机数的状态管理器
class RandomState:
_bit_generator: BitGenerator # 随机数位生成器
# 初始化方法,接受种子参数,初始化随机数生成器状态
def __init__(self, seed: None | _ArrayLikeInt_co | BitGenerator = ...) -> None: ...
# 返回对象的字符串表示形式
def __repr__(self) -> str: ...
# 返回对象的字符串表示形式
def __str__(self) -> str: ...
# 返回对象的序列化状态,以字典形式
def __getstate__(self) -> dict[str, Any]: ...
# 设置对象的序列化状态
def __setstate__(self, state: dict[str, Any]) -> None: ...
# 返回用于重建对象的可调用函数和参数
def __reduce__(self) -> tuple[Callable[[BitGenerator], RandomState], tuple[BitGenerator], dict[str, Any]]: ...
# 设置随机数生成器的种子
def seed(self, seed: None | _ArrayLikeFloat_co = ...) -> None: ...
# 获取当前随机数生成器的状态,支持不同的返回格式
@overload
def get_state(self, legacy: Literal[False] = ...) -> dict[str, Any]: ...
# 获取当前随机数生成器的状态,支持不同的返回格式
@overload
def get_state(
self, legacy: Literal[True] = ...
) -> dict[str, Any] | tuple[str, NDArray[uint32], int, int, float]: ...
# 设置随机数生成器的状态
def set_state(
self, state: dict[str, Any] | tuple[str, NDArray[uint32], int, int, float]
) -> None: ...
# 生成指定形状的随机样本,支持不同的返回类型
@overload
def random_sample(self, size: None = ...) -> float: ... # type: ignore[misc]
# 生成指定形状的随机样本,支持不同的返回类型
@overload
def random_sample(self, size: _ShapeLike) -> NDArray[float64]: ...
# 生成指定形状的随机数,支持不同的返回类型
@overload
def random(self, size: None = ...) -> float: ... # type: ignore[misc]
# 生成指定形状的随机数,支持不同的返回类型
@overload
def random(self, size: _ShapeLike) -> NDArray[float64]: ...
# 生成 Beta 分布的随机样本,支持不同的返回类型
@overload
def beta(self, a: float, b: float, size: None = ...) -> float: ... # type: ignore[misc]
# 生成 Beta 分布的随机样本,支持不同的返回类型
@overload
def beta(
self, a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 生成指数分布的随机样本,支持不同的返回类型
@overload
def exponential(self, scale: float = ..., size: None = ...) -> float: ... # type: ignore[misc]
# 生成指数分布的随机样本,支持不同的返回类型
@overload
def exponential(
self, scale: _ArrayLikeFloat_co = ..., size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 生成标准指数分布的随机样本,支持不同的返回类型
@overload
def standard_exponential(self, size: None = ...) -> float: ... # type: ignore[misc]
# 定义一个方法,生成一个标准指数分布的随机数数组
def standard_exponential(self, size: _ShapeLike) -> NDArray[float64]: ...
# 重载方法签名,将生成的随机数数组转换为整数类型的最大整数值
def tomaxint(self, size: None = ...) -> int: ... # type: ignore[misc]
# 重载方法签名,生成一个指定大小的整数数组,存储在64位整数中
# 生成的随机数范围为low到high之间(包括low但不包括high)
def tomaxint(self, size: _ShapeLike) -> NDArray[int64]: ...
# 重载方法签名,生成一个指定范围的随机整数
# 如果未提供size,默认生成一个整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
) -> int: ...
# 重载方法签名,生成一个指定范围的随机布尔值
# 如果未提供size,默认生成一个布尔值
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: type[bool] = ...,
) -> bool: ...
# 重载方法签名,生成一个指定范围的随机NumPy布尔值
# 如果未提供size,默认生成一个NumPy布尔值
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: type[np.bool] = ...,
) -> np.bool: ...
# 重载方法签名,生成一个指定范围的随机整数
# 如果未提供size,默认生成一个整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: type[int] = ...,
) -> int: ...
# 重载方法签名,生成一个指定范围的随机8位无符号整数
# 如果未提供size,默认生成一个8位无符号整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[uint8] | type[uint8] | _UInt8Codes | _SupportsDType[dtype[uint8]] = ...,
) -> uint8: ...
# 重载方法签名,生成一个指定范围的随机16位无符号整数
# 如果未提供size,默认生成一个16位无符号整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[uint16] | type[uint16] | _UInt16Codes | _SupportsDType[dtype[uint16]] = ...,
) -> uint16: ...
# 重载方法签名,生成一个指定范围的随机32位无符号整数
# 如果未提供size,默认生成一个32位无符号整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[uint32] | type[uint32] | _UInt32Codes | _SupportsDType[dtype[uint32]] = ...,
) -> uint32: ...
# 重载方法签名,生成一个指定范围的随机无符号整数
# 如果未提供size,默认生成一个无符号整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[uint] | type[uint] | _UIntCodes | _SupportsDType[dtype[uint]] = ...,
) -> uint: ...
# 重载方法签名,生成一个指定范围的随机无符号长整数
# 如果未提供size,默认生成一个无符号长整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[ulong] | type[ulong] | _ULongCodes | _SupportsDType[dtype[ulong]] = ...,
) -> ulong: ...
# 重载方法签名,生成一个指定范围的随机64位无符号整数
# 如果未提供size,默认生成一个64位无符号整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[uint64] | type[uint64] | _UInt64Codes | _SupportsDType[dtype[uint64]] = ...,
) -> uint64: ...
# 重载方法签名,生成一个指定范围的随机8位有符号整数
# 如果未提供size,默认生成一个8位有符号整数
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[int8] | type[int8] | _Int8Codes | _SupportsDType[dtype[int8]] = ...,
) -> int8: ...
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[int16] | type[int16] | _Int16Codes | _SupportsDType[dtype[int16]] = ...,
) -> int16: ...
```
# 定义名为 `randint` 的方法,用于生成随机整数
# `self`: 方法的隐含参数,指代对象实例本身
# `low`: 最小的可能返回值
# `high`: 可选参数,最大的可能返回值
# `size`: 可选参数,控制返回值的形状或大小
# `dtype`: 可选参数,指定返回值的数据类型
# `-> int16`: 方法返回一个 `int16` 类型的整数
@overload
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[int32] | type[int32] | _Int32Codes | _SupportsDType[dtype[int32]] = ...,
) -> int32: ...
```py
# 方法的重载定义,接受不同的参数组合来支持返回不同数据类型的整数
@overload
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[int_] | type[int_] | _IntCodes | _SupportsDType[dtype[int_]] = ...,
) -> int_: ...
```
# 另一种重载定义,支持返回 `int_` 类型的整数
@overload
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[long] | type[long] | _LongCodes | _SupportsDType[dtype[long]] = ...,
) -> long: ...
```py
# 又一种重载定义,支持返回 `long` 类型的整数
@overload
def randint( # type: ignore[misc]
self,
low: int,
high: None | int = ...,
size: None = ...,
dtype: dtype[int64] | type[int64] | _Int64Codes | _SupportsDType[dtype[int64]] = ...,
) -> int64: ...
```
# 再一种重载定义,支持返回 `int64` 类型的整数
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[long]: ...
```py
# 支持接受数组形式的 `low` 参数,并返回一个 `NDArray[long]` 类型的数组
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: _DTypeLikeBool = ...,
) -> NDArray[np.bool]: ...
```
# 支持接受数组形式的 `low` 参数,并返回一个 `NDArray[np.bool]` 类型的布尔数组
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[int8] | type[int8] | _Int8Codes | _SupportsDType[dtype[int8]] = ...,
) -> NDArray[int8]: ...
```py
# 支持接受数组形式的 `low` 参数,并返回一个 `NDArray[int8]` 类型的整数数组
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[int16] | type[int16] | _Int16Codes | _SupportsDType[dtype[int16]] = ...,
) -> NDArray[int16]: ...
```
# 支持接受数组形式的 `low` 参数,并返回一个 `NDArray[int16]` 类型的整数数组
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[int32] | type[int32] | _Int32Codes | _SupportsDType[dtype[int32]] = ...,
) -> NDArray[int32]: ...
```py
# 支持接受数组形式的 `low` 参数,并返回一个 `NDArray[int32]` 类型的整数数组
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: None | dtype[int64] | type[int64] | _Int64Codes | _SupportsDType[dtype[int64]] = ...,
) -> NDArray[int64]: ...
```
# 支持接受数组形式的 `low` 参数,并返回一个 `NDArray[int64]` 类型的整数数组
@overload
```py
# 最后一种重载定义,支持不同的参数组合,以适应不同的调用需求
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[uint8] | type[uint8] | _UInt8Codes | _SupportsDType[dtype[uint8]] = ...,
) -> NDArray[uint8]: ...
# 定义了一个名为 `randint` 的方法,用于生成随机整数数组。此处的注释用于指示类型检查器忽略与杂项相关的类型错误。
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[uint16] | type[uint16] | _UInt16Codes | _SupportsDType[dtype[uint16]] = ...,
) -> NDArray[uint16]: ...
# `randint` 方法的重载,用于生成 `uint16` 类型的随机整数数组。同样使用了类型检查器忽略与杂项相关的类型错误。
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[uint32] | type[uint32] | _UInt32Codes | _SupportsDType[dtype[uint32]] = ...,
) -> NDArray[uint32]: ...
# `randint` 方法的重载,用于生成 `uint32` 类型的随机整数数组。同样使用了类型检查器忽略与杂项相关的类型错误。
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[uint64] | type[uint64] | _UInt64Codes | _SupportsDType[dtype[uint64]] = ...,
) -> NDArray[uint64]: ...
# `randint` 方法的重载,用于生成 `uint64` 类型的随机整数数组。同样使用了类型检查器忽略与杂项相关的类型错误。
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[long] | type[int] | type[long] | _LongCodes | _SupportsDType[dtype[long]] = ...,
) -> NDArray[long]: ...
# `randint` 方法的重载,用于生成 `long` 类型的随机整数数组。同样使用了类型检查器忽略与杂项相关的类型错误。
@overload
def randint( # type: ignore[misc]
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
dtype: dtype[ulong] | type[ulong] | _ULongCodes | _SupportsDType[dtype[ulong]] = ...,
) -> NDArray[ulong]: ...
# `randint` 方法的重载,用于生成 `ulong` 类型的随机整数数组。同样使用了类型检查器忽略与杂项相关的类型错误。
def bytes(self, length: int) -> builtins.bytes: ...
# 定义了一个名为 `bytes` 的方法,用于生成指定长度的字节数组。
@overload
def choice(
self,
a: int,
size: None = ...,
replace: bool = ...,
p: None | _ArrayLikeFloat_co = ...,
) -> int: ...
# `choice` 方法的重载,用于从整数 `a` 中做出选择,并返回一个整数。可选的参数包括选择结果的尺寸 `size`、是否替换 `replace`,以及概率分布 `p`。
@overload
def choice(
self,
a: int,
size: _ShapeLike = ...,
replace: bool = ...,
p: None | _ArrayLikeFloat_co = ...,
) -> NDArray[long]: ...
# `choice` 方法的重载,用于从整数 `a` 中做出选择,并返回一个 `long` 类型的数组。可选的参数包括选择结果的尺寸 `size`、是否替换 `replace`,以及概率分布 `p`。
@overload
def choice(
self,
a: ArrayLike,
size: None = ...,
replace: bool = ...,
p: None | _ArrayLikeFloat_co = ...,
) -> Any: ...
# `choice` 方法的重载,用于从数组 `a` 中做出选择,并返回任意类型的结果。可选的参数包括选择结果的尺寸 `size`、是否替换 `replace`,以及概率分布 `p`。
@overload
def choice(
self,
a: ArrayLike,
size: _ShapeLike = ...,
replace: bool = ...,
p: None | _ArrayLikeFloat_co = ...,
) -> NDArray[Any]: ...
# `choice` 方法的重载,用于从数组 `a` 中做出选择,并返回一个 `Any` 类型的数组。可选的参数包括选择结果的尺寸 `size`、是否替换 `replace`,以及概率分布 `p`。
@overload
def uniform(self, low: float = ..., high: float = ..., size: None = ...) -> float: ... # type: ignore[misc]
# 定义了一个名为 `uniform` 的方法,用于生成指定范围内的均匀分布的随机浮点数。此处的注释用于指示类型检查器忽略与杂项相关的类型错误。
@overload
def uniform(
self,
low: _ArrayLikeFloat_co = ...,
high: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]: ...
# `uniform` 方法的重载,用于生成指定范围内的均匀分布的随机浮点数数组。同样使用了类型检查器忽略与杂项相关的类型错误。
# 定义一个 rand 方法,返回一个随机浮点数
def rand(self) -> float: ...
# 使用装饰器声明一个 rand 方法的重载,接受任意个整数参数,返回一个浮点数的 NumPy 数组
@overload
def rand(self, *args: int) -> NDArray[float64]: ...
# 定义一个 randn 方法,返回一个标准正态分布的随机浮点数
@overload
def randn(self) -> float: ...
# 使用装饰器声明一个 randn 方法的重载,接受任意个整数参数,返回一个浮点数的 NumPy 数组,表示标准正态分布
@overload
def randn(self, *args: int) -> NDArray[float64]: ...
# 定义一个 random_integers 方法,返回一个指定范围内的随机整数
@overload
def random_integers(self, low: int, high: None | int = ..., size: None = ...) -> int: ... # type: ignore[misc]
# 使用装饰器声明一个 random_integers 方法的重载,接受一个整数或整数数组作为 low 参数,返回一个长整型的 NumPy 数组
@overload
def random_integers(
self,
low: _ArrayLikeInt_co,
high: None | _ArrayLikeInt_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[long]: ...
# 定义一个 standard_normal 方法,返回一个标准正态分布的随机浮点数
@overload
def standard_normal(self, size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 standard_normal 方法的重载,接受一个形状参数 size,返回一个浮点数的 NumPy 数组,表示标准正态分布
@overload
def standard_normal(
self, size: _ShapeLike = ...
) -> NDArray[float64]: ...
# 定义一个 normal 方法,返回一个指定均值和标准差的随机浮点数
@overload
def normal(self, loc: float = ..., scale: float = ..., size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 normal 方法的重载,接受均值和标准差参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示正态分布
@overload
def normal(
self,
loc: _ArrayLikeFloat_co = ...,
scale: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]: ...
# 定义一个 standard_gamma 方法,返回一个形状参数指定的标准 Gamma 分布的随机浮点数
@overload
def standard_gamma( # type: ignore[misc]
self,
shape: float,
size: None = ...,
) -> float: ...
# 使用装饰器声明一个 standard_gamma 方法的重载,接受形状参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示标准 Gamma 分布
@overload
def standard_gamma(
self,
shape: _ArrayLikeFloat_co,
size: None | _ShapeLike = ...,
) -> NDArray[float64]: ...
# 定义一个 gamma 方法,返回一个形状和尺度参数指定的 Gamma 分布的随机浮点数
@overload
def gamma(self, shape: float, scale: float = ..., size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 gamma 方法的重载,接受形状和尺度参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示 Gamma 分布
@overload
def gamma(
self,
shape: _ArrayLikeFloat_co,
scale: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]: ...
# 定义一个 f 方法,返回自由度参数指定的 F 分布的随机浮点数
@overload
def f(self, dfnum: float, dfden: float, size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 f 方法的重载,接受自由度参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示 F 分布
@overload
def f(
self, dfnum: _ArrayLikeFloat_co, dfden: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 定义一个 noncentral_f 方法,返回自由度和非心参数指定的非心 F 分布的随机浮点数
@overload
def noncentral_f(self, dfnum: float, dfden: float, nonc: float, size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 noncentral_f 方法的重载,接受自由度和非心参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示非心 F 分布
@overload
def noncentral_f(
self,
dfnum: _ArrayLikeFloat_co,
dfden: _ArrayLikeFloat_co,
nonc: _ArrayLikeFloat_co,
size: None | _ShapeLike = ...,
) -> NDArray[float64]: ...
# 定义一个 chisquare 方法,返回自由度参数指定的卡方分布的随机浮点数
@overload
def chisquare(self, df: float, size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 chisquare 方法的重载,接受自由度参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示卡方分布
@overload
def chisquare(
self, df: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 定义一个 noncentral_chisquare 方法,返回自由度和非心参数指定的非心卡方分布的随机浮点数
@overload
def noncentral_chisquare(self, df: float, nonc: float, size: None = ...) -> float: ... # type: ignore[misc]
# 使用装饰器声明一个 noncentral_chisquare 方法的重载,接受自由度和非心参数可以是单个数或数组,返回一个浮点数的 NumPy 数组,表示非心卡方分布
@overload
def noncentral_chisquare(
self, df: _ArrayLikeFloat_co, nonc: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 定义一个 standard_t 方法,返回自由度参数指定的 t 分布的随机浮点数
@overload
def standard_t(self, df: float, size: None = ...) -> float: ... # type: ignore[misc]
def standard_t(
self, df: _ArrayLikeFloat_co, size: None = ...
) -> NDArray[float64]:
# 标准 t 分布函数的声明,接受一个自由度参数 df 和一个可选的尺寸参数 size
...
@overload
def standard_t(
self, df: _ArrayLikeFloat_co, size: _ShapeLike = ...
) -> NDArray[float64]:
# 标准 t 分布函数的重载声明,接受一个自由度参数 df 和一个形状参数 size
...
@overload
def vonmises(self, mu: float, kappa: float, size: None = ...) -> float:
# 冯·米塞斯分布函数的声明,接受一个均值参数 mu,一个集中度参数 kappa 和一个可选的尺寸参数 size
...
@overload
def vonmises(
self, mu: _ArrayLikeFloat_co, kappa: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]:
# 冯·米塞斯分布函数的重载声明,接受一个均值参数 mu,一个集中度参数 kappa 和一个可选的形状参数 size
...
@overload
def pareto(self, a: float, size: None = ...) -> float:
# 帕累托分布函数的声明,接受一个形状参数 a 和一个可选的尺寸参数 size
...
@overload
def pareto(
self, a: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]:
# 帕累托分布函数的重载声明,接受一个形状参数 a 和一个可选的形状参数 size
...
@overload
def weibull(self, a: float, size: None = ...) -> float:
# 威布尔分布函数的声明,接受一个形状参数 a 和一个可选的尺寸参数 size
...
@overload
def weibull(
self, a: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]:
# 威布尔分布函数的重载声明,接受一个形状参数 a 和一个可选的形状参数 size
...
@overload
def power(self, a: float, size: None = ...) -> float:
# 功率分布函数的声明,接受一个形状参数 a 和一个可选的尺寸参数 size
...
@overload
def power(
self, a: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]:
# 功率分布函数的重载声明,接受一个形状参数 a 和一个可选的形状参数 size
...
@overload
def standard_cauchy(self, size: None = ...) -> float:
# 标准柯西分布函数的声明,接受一个可选的尺寸参数 size
...
@overload
def standard_cauchy(self, size: _ShapeLike = ...) -> NDArray[float64]:
# 标准柯西分布函数的重载声明,接受一个形状参数 size
...
@overload
def laplace(self, loc: float = ..., scale: float = ..., size: None = ...) -> float:
# 拉普拉斯分布函数的声明,接受一个位置参数 loc,一个尺度参数 scale 和一个可选的尺寸参数 size
...
@overload
def laplace(
self,
loc: _ArrayLikeFloat_co = ...,
scale: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]:
# 拉普拉斯分布函数的重载声明,接受一个位置参数 loc,一个尺度参数 scale 和一个可选的形状参数 size
...
@overload
def gumbel(self, loc: float = ..., scale: float = ..., size: None = ...) -> float:
# 甘贝尔分布函数的声明,接受一个位置参数 loc,一个尺度参数 scale 和一个可选的尺寸参数 size
...
@overload
def gumbel(
self,
loc: _ArrayLikeFloat_co = ...,
scale: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]:
# 甘贝尔分布函数的重载声明,接受一个位置参数 loc,一个尺度参数 scale 和一个可选的形状参数 size
...
@overload
def logistic(self, loc: float = ..., scale: float = ..., size: None = ...) -> float:
# 逻辑斯蒂分布函数的声明,接受一个位置参数 loc,一个尺度参数 scale 和一个可选的尺寸参数 size
...
@overload
def logistic(
self,
loc: _ArrayLikeFloat_co = ...,
scale: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]:
# 逻辑斯蒂分布函数的重载声明,接受一个位置参数 loc,一个尺度参数 scale 和一个可选的形状参数 size
...
@overload
def lognormal(self, mean: float = ..., sigma: float = ..., size: None = ...) -> float:
# 对数正态分布函数的声明,接受一个均值参数 mean,一个标准差参数 sigma 和一个可选的尺寸参数 size
...
@overload
def lognormal(
self,
mean: _ArrayLikeFloat_co = ...,
sigma: _ArrayLikeFloat_co = ...,
size: None | _ShapeLike = ...,
) -> NDArray[float64]:
# 对数正态分布函数的重载声明,接受一个均值参数 mean,一个标准差参数 sigma 和一个可选的形状参数 size
...
@overload
def rayleigh(self, scale: float = ..., size: None = ...) -> float:
# 瑞利分布函数的声明,接受一个尺度参数 scale 和一个可选的尺寸参数 size
...
@overload
def rayleigh(
self, scale: _ArrayLikeFloat_co = ..., size: None | _ShapeLike = ...
) -> NDArray[float64]:
# 瑞利分布函数的重载声明,接受一个尺度参数 scale 和一个可选的形状参数 size
...
@overload
```
def wald(self, mean: float, scale: float, size: None = ...) -> float: ... # type: ignore[misc]
# 定义 Wald 分布的概率密度函数,接受平均值和尺度参数
@overload
def wald(
self, mean: _ArrayLikeFloat_co, scale: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[float64]
@overload
def triangular(self, left: float, mode: float, right: float, size: None = ...) -> float: ... # type: ignore[misc]
# 定义三角分布的概率密度函数,接受左侧、众数和右侧参数
@overload
def triangular(
self,
left: _ArrayLikeFloat_co,
mode: _ArrayLikeFloat_co,
right: _ArrayLikeFloat_co,
size: None | _ShapeLike = ...,
) -> NDArray[float64]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[float64]
@overload
def binomial(self, n: int, p: float, size: None = ...) -> int: ... # type: ignore[misc]
# 定义二项分布的概率质量函数,接受试验次数和成功概率参数
@overload
def binomial(
self, n: _ArrayLikeInt_co, p: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long],表示每个试验的成功次数
@overload
def negative_binomial(self, n: float, p: float, size: None = ...) -> int: ... # type: ignore[misc]
# 定义负二项分布的概率质量函数,接受成功次数和成功概率参数
@overload
def negative_binomial(
self, n: _ArrayLikeFloat_co, p: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long],表示达到指定成功次数前所需的失败次数
@overload
def poisson(self, lam: float = ..., size: None = ...) -> int: ... # type: ignore[misc]
# 定义泊松分布的概率质量函数,接受泊松率参数
@overload
def poisson(
self, lam: _ArrayLikeFloat_co = ..., size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long],表示指定区间内的事件发生次数
@overload
def zipf(self, a: float, size: None = ...) -> int: ... # type: ignore[misc]
# 定义 Zipf 分布的概率质量函数,接受参数 a
@overload
def zipf(
self, a: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long]
@overload
def geometric(self, p: float, size: None = ...) -> int: ... # type: ignore[misc]
# 定义几何分布的概率质量函数,接受成功概率参数
@overload
def geometric(
self, p: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long],表示首次成功所需的试验次数
@overload
def hypergeometric(self, ngood: int, nbad: int, nsample: int, size: None = ...) -> int: ... # type: ignore[misc]
# 定义超几何分布的概率质量函数,接受总体好样本数、总体坏样本数和样本量参数
@overload
def hypergeometric(
self,
ngood: _ArrayLikeInt_co,
nbad: _ArrayLikeInt_co,
nsample: _ArrayLikeInt_co,
size: None | _ShapeLike = ...,
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long],表示样本中好样本的数量
@overload
def logseries(self, p: float, size: None = ...) -> int: ... # type: ignore[misc]
# 定义对数系列分布的概率质量函数,接受参数 p
@overload
def logseries(
self, p: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 重载函数:处理数组输入的情况,返回 NumPy 数组 NDArray[long],表示首次成功所需的试验次数
def multivariate_normal(
self,
mean: _ArrayLikeFloat_co,
cov: _ArrayLikeFloat_co,
size: None | _ShapeLike = ...,
check_valid: Literal["warn", "raise", "ignore"] = ...,
tol: float = ...,
) -> NDArray[float64]: ...
# 定义多元正态分布的概率密度函数,接受均值向量和协方差矩阵参数
def multinomial(
self, n: _ArrayLikeInt_co, pvals: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[long]: ...
# 定义多项式分布的概率质量函数,接受试验次数和每个类别的概率参数
def dirichlet(
self, alpha: _ArrayLikeFloat_co, size: None | _ShapeLike = ...
) -> NDArray[float64]: ...
# 定义狄利克雷分布的概率密度函数,接受参数 alpha
def shuffle(self, x: ArrayLike) -> None: ...
# 对数组 x 进行随机重排
# 标注函数的重载方法,用于不同类型参数的排列组合生成
@overload
def permutation(self, x: int) -> NDArray[long]: ...
# 标注函数的重载方法,用于不同类型参数的排列组合生成,支持任意数组类型
@overload
def permutation(self, x: ArrayLike) -> NDArray[Any]: ...
# 初始化一个 RandomState 对象,用于生成随机数
_rand: RandomState
# 以下是 RandomState 对象提供的一些随机数生成方法
beta = _rand.beta # 生成 Beta 分布的随机数
binomial = _rand.binomial # 生成二项分布的随机数
bytes = _rand.bytes # 生成指定长度的随机字节串
chisquare = _rand.chisquare # 生成卡方分布的随机数
choice = _rand.choice # 从给定的样本中随机抽取元素
dirichlet = _rand.dirichlet # 生成 Dirichlet 分布的随机数
exponential = _rand.exponential # 生成指数分布的随机数
f = _rand.f # 生成 F 分布的随机数
gamma = _rand.gamma # 生成 Gamma 分布的随机数
get_state = _rand.get_state # 获取当前 RandomState 对象的状态
geometric = _rand.geometric # 生成几何分布的随机数
gumbel = _rand.gumbel # 生成 Gumbel 分布的随机数
hypergeometric = _rand.hypergeometric # 生成超几何分布的随机数
laplace = _rand.laplace # 生成拉普拉斯分布的随机数
logistic = _rand.logistic # 生成 Logistic 分布的随机数
lognormal = _rand.lognormal # 生成对数正态分布的随机数
logseries = _rand.logseries # 生成对数级数分布的随机数
multinomial = _rand.multinomial # 生成多项分布的随机数
multivariate_normal = _rand.multivariate_normal # 生成多变量正态分布的随机数
negative_binomial = _rand.negative_binomial # 生成负二项分布的随机数
noncentral_chisquare = _rand.noncentral_chisquare # 生成非中心卡方分布的随机数
noncentral_f = _rand.noncentral_f # 生成非中心 F 分布的随机数
normal = _rand.normal # 生成正态分布的随机数
pareto = _rand.pareto # 生成帕累托分布的随机数
permutation = _rand.permutation # 对给定序列进行随机排列
poisson = _rand.poisson # 生成泊松分布的随机数
power = _rand.power # 生成 Power 分布的随机数
rand = _rand.rand # 生成均匀分布的随机数
randint = _rand.randint # 生成指定范围内的随机整数
randn = _rand.randn # 生成标准正态分布的随机数
random = _rand.random # 生成 [0.0, 1.0) 范围内的随机浮点数
random_integers = _rand.random_integers # 生成指定范围内的随机整数(包括上下界)
random_sample = _rand.random_sample # 生成 [0.0, 1.0) 范围内的随机浮点数
rayleigh = _rand.rayleigh # 生成 Rayleigh 分布的随机数
seed = _rand.seed # 设置随机数生成器的种子
set_state = _rand.set_state # 设置 RandomState 对象的状态
shuffle = _rand.shuffle # 将序列随机打乱
standard_cauchy = _rand.standard_cauchy # 生成标准 Cauchy 分布的随机数
standard_exponential = _rand.standard_exponential # 生成标准指数分布的随机数
standard_gamma = _rand.standard_gamma # 生成标准 Gamma 分布的随机数
standard_normal = _rand.standard_normal # 生成标准正态分布的随机数
standard_t = _rand.standard_t # 生成标准 t 分布的随机数
triangular = _rand.triangular # 生成三角分布的随机数
uniform = _rand.uniform # 生成均匀分布的随机数
vonmises = _rand.vonmises # 生成 Von Mises 分布的随机数
wald = _rand.wald # 生成 Wald 分布的随机数
weibull = _rand.weibull # 生成 Weibull 分布的随机数
zipf = _rand.zipf # 生成 Zipf 分布的随机数
# 以下两个是 random_sample 方法的别名,保留为向后兼容
sample = _rand.random_sample # 生成 [0.0, 1.0) 范围内的随机浮点数
ranf = _rand.random_sample # 生成 [0.0, 1.0) 范围内的随机浮点数
# 设置位生成器为指定的 BitGenerator 对象
def set_bit_generator(bitgen: BitGenerator) -> None:
...
# 获取当前的位生成器对象
def get_bit_generator() -> BitGenerator:
...
.\numpy\numpy\random\mtrand.pyx
# 导入运算符模块,提供了各种运算符的函数实现
import operator
# 导入警告模块,用于发出警告信息
import warnings
# 从collections.abc模块中导入Sequence类,用于定义抽象基类
from collections.abc import Sequence
# 导入NumPy库,并使用np作为别名
import numpy as np
# 从cpython.pycapsule中的cimport部分导入PyCapsule_IsValid和PyCapsule_GetPointer函数
from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
# 从cpython中的cimport部分导入Py_INCREF和PyFloat_AsDouble函数
from cpython cimport (Py_INCREF, PyFloat_AsDouble)
# 使用cython声明cimport导入NumPy库
cimport cython
cimport numpy as np
# 从libc中的cimport部分导入string和stdint模块
from libc cimport string
from libc.stdint cimport int64_t, uint64_t
# 从._bounded_integers模块的cimport部分导入各种随机整数生成函数
from ._bounded_integers cimport (_rand_bool, _rand_int32, _rand_int64,
_rand_int16, _rand_int8, _rand_uint64, _rand_uint32, _rand_uint16,
_rand_uint8,)
# 从._mt19937模块导入MT19937类,并使用_MT19937作为别名
from ._mt19937 import MT19937 as _MT19937
# 从numpy.random中的cimport部分导入bitgen_t结构体
from numpy.random cimport bitgen_t
# 从._common模块的cimport部分导入各种常量和函数
from ._common cimport (POISSON_LAM_MAX, CONS_POSITIVE, CONS_NONE,
CONS_NON_NEGATIVE, CONS_BOUNDED_0_1, CONS_BOUNDED_GT_0_1,
CONS_BOUNDED_LT_0_1, CONS_GTE_1, CONS_GT_1, LEGACY_CONS_POISSON,
LEGACY_CONS_NON_NEGATIVE_INBOUNDS_LONG,
double_fill, cont, kahan_sum, cont_broadcast_3,
check_array_constraint, check_constraint, disc, discrete_broadcast_iii,
validate_output_shape
)
# 从NumPy随机分布头文件中的cdef extern部分声明s_binomial_t结构体
cdef extern from "numpy/random/distributions.h":
struct s_binomial_t:
int has_binomial
double psave
int64_t nsave
double r
double q
double fm
int64_t m
double p1
double xm
double xl
double xr
double c
double laml
double lamr
double p2
double p3
double p4
ctypedef s_binomial_t binomial_t
# 声明多个随机数生成函数,使用nogil关键字表示函数是无GIL(全局解释器锁)的
void random_standard_uniform_fill(bitgen_t* bitgen_state, np.npy_intp cnt, double *out) nogil
int64_t random_positive_int(bitgen_t *bitgen_state) nogil
double random_uniform(bitgen_t *bitgen_state, double lower, double range) nogil
double random_laplace(bitgen_t *bitgen_state, double loc, double scale) nogil
double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) nogil
double random_logistic(bitgen_t *bitgen_state, double loc, double scale) nogil
double random_rayleigh(bitgen_t *bitgen_state, double mode) nogil
double random_triangular(bitgen_t *bitgen_state, double left, double mode,
double right) nogil
uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) nogil
# 从包含遗留分布的头文件中的cdef extern部分声明aug_bitgen结构体
cdef extern from "include/legacy-distributions.h":
struct aug_bitgen:
bitgen_t *bit_generator
int has_gauss
double gauss
ctypedef aug_bitgen aug_bitgen_t
# 声明多个遗留分布函数,使用nogil关键字表示函数是无GIL的
double legacy_gauss(aug_bitgen_t *aug_state) nogil
double legacy_pareto(aug_bitgen_t *aug_state, double a) nogil
double legacy_weibull(aug_bitgen_t *aug_state, double a) nogil
double legacy_standard_gamma(aug_bitgen_t *aug_state, double shape) nogil
double legacy_normal(aug_bitgen_t *aug_state, double loc, double scale) nogil
double legacy_standard_t(aug_bitgen_t *aug_state, double df) nogil
// 计算服从标准指数分布的随机数,使用给定的随机数生成器状态
double legacy_standard_exponential(aug_bitgen_t *aug_state) nogil
// 计算服从幂律分布的随机数,使用给定的随机数生成器状态和指数参数
double legacy_power(aug_bitgen_t *aug_state, double a) nogil
// 计算服从伽马分布的随机数,使用给定的随机数生成器状态、形状参数和尺度参数
double legacy_gamma(aug_bitgen_t *aug_state, double shape, double scale) nogil
// 计算服从卡方分布的随机数,使用给定的随机数生成器状态和自由度
double legacy_chisquare(aug_bitgen_t *aug_state, double df) nogil
// 计算服从瑞利分布的随机数,使用给定的随机数生成器状态和模式参数
double legacy_rayleigh(aug_bitgen_t *aug_state, double mode) nogil
// 计算服从非中心卡方分布的随机数,使用给定的随机数生成器状态、自由度和非中心参数
double legacy_noncentral_chisquare(aug_bitgen_t *aug_state, double df, double nonc) nogil
// 计算服从非中心 F 分布的随机数,使用给定的随机数生成器状态、分子自由度、分母自由度和非中心参数
double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum, double dfden, double nonc) nogil
// 计算服从瓦尔德分布的随机数,使用给定的随机数生成器状态、均值和尺度参数
double legacy_wald(aug_bitgen_t *aug_state, double mean, double scale) nogil
// 计算服从对数正态分布的随机数,使用给定的随机数生成器状态、均值和标准差参数
double legacy_lognormal(aug_bitgen_t *aug_state, double mean, double sigma) nogil
// 生成服从二项分布的随机数,使用给定的随机数生成器状态、成功概率和试验次数
int64_t legacy_random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) nogil
// 生成服从负二项分布的随机数,使用给定的随机数生成器状态、失败次数和成功概率
int64_t legacy_negative_binomial(aug_bitgen_t *aug_state, double n, double p) nogil
// 生成服从超几何分布的随机数,使用给定的随机数生成器状态、成功数、失败数和样本数
int64_t legacy_random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad, int64_t sample) nogil
// 生成服从对数级数分布的随机数,使用给定的随机数生成器状态和概率参数
int64_t legacy_logseries(bitgen_t *bitgen_state, double p) nogil
// 生成服从泊松分布的随机数,使用给定的随机数生成器状态和均值参数
int64_t legacy_random_poisson(bitgen_t *bitgen_state, double lam) nogil
// 生成服从 Zipf 分布的随机数,使用给定的随机数生成器状态和参数 a
int64_t legacy_random_zipf(bitgen_t *bitgen_state, double a) nogil
// 生成服从几何分布的随机数,使用给定的随机数生成器状态和成功概率参数
int64_t legacy_random_geometric(bitgen_t *bitgen_state, double p) nogil
// 生成多项式分布的随机数,使用给定的随机数生成器状态、总数、各类别数量和各类别概率
void legacy_random_multinomial(bitgen_t *bitgen_state, long n, long *mnix, double *pix, np.npy_intp d, binomial_t *binomial) nogil
// 计算服从标准柯西分布的随机数,使用给定的随机数生成器状态
double legacy_standard_cauchy(aug_bitgen_t *state) nogil
// 计算服从 Beta 分布的随机数,使用给定的随机数生成器状态、参数 a 和 b
double legacy_beta(aug_bitgen_t *aug_state, double a, double b) nogil
// 计算服从 F 分布的随机数,使用给定的随机数生成器状态、分子自由度和分母自由度
double legacy_f(aug_bitgen_t *aug_state, double dfnum, double dfden) nogil
// 计算服从指数分布的随机数,使用给定的随机数生成器状态和尺度参数
double legacy_exponential(aug_bitgen_t *aug_state, double scale) nogil
// 计算服从幂律分布的随机数,使用给定的随机数生成器状态和指数参数
double legacy_power(aug_bitgen_t *state, double a) nogil
// 计算服从 von Mises 分布的随机数,使用给定的随机数生成器状态、均值和集中度参数
double legacy_vonmises(bitgen_t *bitgen_state, double mu, double kappa) nogil
# 导入 NumPy 库,并确保其内部 C 函数可以正常使用
np.import_array()
# 定义一个 C 函数 int64_to_long,用于将 int64 类型转换为 long 类型以保持向后兼容性
cdef object int64_to_long(object x):
"""
Convert int64 to long for legacy compatibility, which used long for integer
distributions
"""
cdef int64_t x64
# 如果 x 是标量,则直接转换为 int64,并返回其 long 类型值
if np.isscalar(x):
x64 = x
return <long>x64
# 否则,将 x 转换为 long 类型并返回
return x.astype('l', casting='unsafe')
# 定义一个 Cython 类 RandomState,用于包装 Mersenne Twister 伪随机数生成器
cdef class RandomState:
"""
RandomState(seed=None)
Container for the slow Mersenne Twister pseudo-random number generator.
Consider using a different BitGenerator with the Generator container
instead.
`RandomState` and `Generator` expose a number of methods for generating
random numbers drawn from a variety of probability distributions. In
addition to the distribution-specific arguments, each method takes a
keyword argument `size` that defaults to ``None``. If `size` is ``None``,
then a single value is generated and returned. If `size` is an integer,
then a 1-D array filled with generated values is returned. If `size` is a
tuple, then an array with that shape is filled and returned.
**Compatibility Guarantee**
A fixed bit generator using a fixed seed and a fixed series of calls to
'RandomState' methods using the same parameters will always produce the
same results up to roundoff error except when the values were incorrect.
`RandomState` is effectively frozen and will only receive updates that
are required by changes in the internals of Numpy. More substantial
changes, including algorithmic improvements, are reserved for
`Generator`.
Parameters
----------
seed : {None, int, array_like, BitGenerator}, optional
Random seed used to initialize the pseudo-random number generator or
an instantized BitGenerator. If an integer or array, used as a seed for
the MT19937 BitGenerator. Values can be any integer between 0 and
2**32 - 1 inclusive, an array (or other sequence) of such integers,
or ``None`` (the default). If `seed` is ``None``, then the `MT19937`
BitGenerator is initialized by reading data from ``/dev/urandom``
(or the Windows analogue) if available or seed from the clock
otherwise.
Notes
-----
The Python stdlib module "random" also contains a Mersenne Twister
pseudo-random number generator with a number of methods that are similar
to the ones available in `RandomState`. `RandomState`, besides being
NumPy-aware, has the advantage that it provides a much larger number
of probability distributions to choose from.
See Also
--------
Generator
MT19937
numpy.random.BitGenerator
"""
cdef public object _bit_generator
cdef bitgen_t _bitgen
cdef aug_bitgen_t _aug_state
cdef binomial_t _binomial
cdef object lock
_poisson_lam_max = POISSON_LAM_MAX
def __init__(self, seed=None):
# 如果未提供种子,则使用默认的 MT19937 生成器
if seed is None:
bit_generator = _MT19937()
# 如果种子不是一个带有 'capsule' 属性的对象,则使用默认的 MT19937 生成器并进行传统种子生成
elif not hasattr(seed, 'capsule'):
bit_generator = _MT19937()
bit_generator._legacy_seeding(seed)
# 否则,使用给定的种子作为生成器
else:
bit_generator = seed
# 初始化 BitGenerator
self._initialize_bit_generator(bit_generator)
def __repr__(self):
# 返回对象的字符串表示形式,包括对象的类名和位生成器的类名
return self.__str__() + ' at 0x{:X}'.format(id(self))
def __str__(self):
# 返回对象的字符串表示形式,包括对象的类名和位生成器的类名
_str = self.__class__.__name__
_str += '(' + self._bit_generator.__class__.__name__ + ')'
return _str
# Pickling support:
def __getstate__(self):
# 获取对象的状态信息,不使用遗留模式
return self.get_state(legacy=False)
def __setstate__(self, state):
# 设置对象的状态信息
self.set_state(state)
def __reduce__(self):
from ._pickle import __randomstate_ctor
# 为了支持序列化,返回一个元组,包含用于重建对象的构造函数和状态信息
return __randomstate_ctor, (self._bit_generator, ), self.get_state(legacy=False)
cdef _initialize_bit_generator(self, bit_generator):
# 初始化位生成器,并检查其有效性
self._bit_generator = bit_generator
capsule = bit_generator.capsule
cdef const char *name = "BitGenerator"
if not PyCapsule_IsValid(capsule, name):
raise ValueError("Invalid bit generator. The bit generator must "
"be instantized.")
# 获取位生成器的指针并设置对象状态
self._bitgen = (<bitgen_t *> PyCapsule_GetPointer(capsule, name))[0]
self._aug_state.bit_generator = &self._bitgen
# 重置高斯随机数状态
self._reset_gauss()
self.lock = bit_generator.lock
cdef _reset_gauss(self):
# 重置高斯随机数状态
self._aug_state.has_gauss = 0
self._aug_state.gauss = 0.0
def seed(self, seed=None):
"""
seed(seed=None)
Reseed a legacy MT19937 BitGenerator
Notes
-----
This is a convenience, legacy function.
The best practice is to **not** reseed a BitGenerator, rather to
recreate a new one. This method is here for legacy reasons.
This example demonstrates best practice.
>>> from numpy.random import MT19937
>>> from numpy.random import RandomState, SeedSequence
>>> rs = RandomState(MT19937(SeedSequence(123456789)))
# Later, you want to restart the stream
>>> rs = RandomState(MT19937(SeedSequence(987654321)))
"""
# 如果不是 MT19937 类型的生成器,则抛出类型错误
if not isinstance(self._bit_generator, _MT19937):
raise TypeError('can only re-seed a MT19937 BitGenerator')
# 使用给定的种子重新生成生成器的状态
self._bit_generator._legacy_seeding(seed)
# 重置高斯随机数状态
self._reset_gauss()
# 定义一个方法用于获取生成器的内部状态
def get_state(self, legacy=True):
"""
get_state(legacy=True)
返回表示生成器内部状态的元组或字典。
更多细节请参见 `set_state`。
Parameters
----------
legacy : bool, optional
标志,指示是否返回 MT19937 生成器的传统元组状态,而不是字典。
如果底层的位生成器不是 MT19937 的实例,则抛出 ValueError。
Returns
-------
out : {tuple(str, ndarray of 624 uints, int, int, float), dict}
如果 legacy 为 True,则返回的元组包含以下项:
1. 字符串 'MT19937'。
2. 624 个无符号整数组成的一维数组。
3. 整数 `pos`。
4. 整数 `has_gauss`。
5. 浮点数 `cached_gaussian`。
如果 `legacy` 为 False,或者位生成器不是 MT19937,则作为字典返回状态。
See Also
--------
set_state
Notes
-----
`set_state` 和 `get_state` 对于使用 NumPy 中的任何随机分布都是不必要的。
如果手动更改内部状态,则用户必须清楚自己在做什么。
"""
# 获取位生成器的当前状态
st = self._bit_generator.state
# 如果位生成器不是 MT19937,并且 legacy 为 True,则发出警告并将 legacy 置为 False
if st['bit_generator'] != 'MT19937' and legacy:
warnings.warn('get_state 和 legacy 仅可与 MT19937 位生成器一起使用。'
'要消除此警告,请将 `legacy` 设置为 False。',
RuntimeWarning)
legacy = False
# 将增强状态中的高斯值添加到状态字典中
st['has_gauss'] = self._aug_state.has_gauss
st['gauss'] = self._aug_state.gauss
# 如果 legacy 为 True 并且位生成器不是 _MT19937 的实例,则引发 ValueError
if legacy and not isinstance(self._bit_generator, _MT19937):
raise ValueError(
"legacy 仅在底层位生成器是 MT19937 的实例时才能为 True。"
)
# 如果 legacy 为 True,则返回传统元组状态
if legacy:
return (st['bit_generator'], st['state']['key'], st['state']['pos'],
st['has_gauss'], st['gauss'])
# 否则返回状态字典
return st
def set_state(self, state):
"""
set_state(state)
Set the internal state of the generator from a tuple.
For use if one has reason to manually (re-)set the internal state of
the bit generator used by the RandomState instance. By default,
RandomState uses the "Mersenne Twister"[1]_ pseudo-random number
generating algorithm.
Parameters
----------
state : {tuple(str, ndarray of 624 uints, int, int, float), dict}
The `state` tuple has the following items:
1. the string 'MT19937', specifying the Mersenne Twister algorithm.
2. a 1-D array of 624 unsigned integers ``keys``.
3. an integer ``pos``.
4. an integer ``has_gauss``.
5. a float ``cached_gaussian``.
If state is a dictionary, it is directly set using the BitGenerators
`state` property.
Returns
-------
out : None
Returns 'None' on success.
See Also
--------
get_state
Notes
-----
`set_state` and `get_state` are not needed to work with any of the
random distributions in NumPy. If the internal state is manually altered,
the user should know exactly what he/she is doing.
For backwards compatibility, the form (str, array of 624 uints, int) is
also accepted although it is missing some information about the cached
Gaussian value: ``state = ('MT19937', keys, pos)``.
References
----------
.. [1] M. Matsumoto and T. Nishimura, "Mersenne Twister: A
623-dimensionally equidistributed uniform pseudorandom number
generator," *ACM Trans. on Modeling and Computer Simulation*,
Vol. 8, No. 1, pp. 3-30, Jan. 1998.
"""
# 如果 state 是字典类型
if isinstance(state, dict):
# 检查字典中是否包含必要的 'bit_generator' 和 'state' 键
if 'bit_generator' not in state or 'state' not in state:
raise ValueError('state dictionary is not valid.')
# 直接使用给定的字典作为状态 st
st = state
else:
# 如果 state 不是字典,必须是元组或列表类型
if not isinstance(state, (tuple, list)):
raise TypeError('state must be a dict or a tuple.')
# 使用 Cython 检查边界
with cython.boundscheck(True):
# 检查是否使用了正确的 Mersenne Twister 状态实例
if state[0] != 'MT19937':
raise ValueError('set_state can only be used with legacy '
'MT19937 state instances.')
# 构建状态字典 st,包括键、位置等信息
st = {'bit_generator': state[0],
'state': {'key': state[1], 'pos': state[2]}}
# 如果状态元组长度大于3,也包括额外的高斯信息
if len(state) > 3:
st['has_gauss'] = state[3]
st['gauss'] = state[4]
# 设置增强状态中的高斯值和高斯标志
self._aug_state.gauss = st.get('gauss', 0.0)
self._aug_state.has_gauss = st.get('has_gauss', 0)
# 设置位生成器的状态
self._bit_generator.state = st
def random_sample(self, size=None):
"""
random_sample(size=None)
Return random floats in the half-open interval [0.0, 1.0).
Results are from the "continuous uniform" distribution over the
stated interval. To sample :math:`Unif[a, b), b > a` multiply
the output of `random_sample` by `(b-a)` and add `a`::
(b - a) * random_sample() + a
.. note::
New code should use the `~numpy.random.Generator.random`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
Returns
-------
out : float or ndarray of floats
Array of random floats of shape `size` (unless ``size=None``, in which
case a single float is returned).
See Also
--------
random.Generator.random: which should be used for new code.
Examples
--------
>>> np.random.random_sample()
0.47108547995356098 # random
>>> type(np.random.random_sample())
<class 'float'>
>>> np.random.random_sample((5,))
array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) # random
Three-by-two array of random numbers from [-5, 0):
>>> 5 * np.random.random_sample((3, 2)) - 5
array([[-3.99149989, -0.52338984], # random
[-2.99091858, -0.79479508],
[-1.23204345, -1.75224494]])
"""
cdef double temp
return double_fill(&random_standard_uniform_fill, &self._bitgen, size, self.lock, None)
def beta(self, a, b, size=None):
"""
beta(a, b, size=None)
Draw samples from a Beta distribution.
The Beta distribution is a special case of the Dirichlet distribution,
and is related to the Gamma distribution. It has the probability
distribution function
.. math:: f(x; a,b) = \\frac{1}{B(\\alpha, \\beta)} x^{\\alpha - 1}
(1 - x)^{\\beta - 1},
where the normalization, B, is the beta function,
.. math:: B(\\alpha, \\beta) = \\int_0^1 t^{\\alpha - 1}
(1 - t)^{\\beta - 1} dt.
It is often seen in Bayesian inference and order statistics.
.. note::
New code should use the `~numpy.random.Generator.beta`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
a : float or array_like of floats
Alpha, positive (>0).
b : float or array_like of floats
Beta, positive (>0).
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
a single value is returned if ``a`` and ``b`` are both scalars.
Otherwise, ``np.broadcast(a, b).size`` samples are drawn.
Returns
-------
out : ndarray or scalar
Drawn samples from the parameterized beta distribution.
See Also
--------
random.Generator.beta: which should be used for new code.
"""
# 调用Cython实现的底层函数,用于生成 Beta 分布的样本
return cont(&legacy_beta, &self._aug_state, size, self.lock, 2,
a, 'a', CONS_POSITIVE,
b, 'b', CONS_POSITIVE,
0.0, '', CONS_NONE, None)
def standard_exponential(self, size=None):
"""
standard_exponential(size=None)
Draw samples from the standard exponential distribution.
`standard_exponential` is identical to the exponential distribution
with a scale parameter of 1.
.. note::
New code should use the
`~numpy.random.Generator.standard_exponential`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
Returns
-------
out : float or ndarray
Drawn samples.
See Also
--------
random.Generator.standard_exponential: which should be used for new code.
Examples
--------
Output a 3x8000 array:
>>> n = np.random.standard_exponential((3, 8000))
"""
# 调用 legacy_standard_exponential 函数从指定的随机状态中生成标准指数分布的样本
return cont(&legacy_standard_exponential, &self._aug_state, size, self.lock, 0,
None, None, CONS_NONE,
None, None, CONS_NONE,
None, None, CONS_NONE,
None)
def tomaxint(self, size=None):
"""
tomaxint(size=None)
Return a sample of uniformly distributed random integers in the interval
[0, ``np.iinfo("long").max``].
.. warning::
This function uses the C-long dtype, which is 32bit on windows
and otherwise 64bit on 64bit platforms (and 32bit on 32bit ones).
Since NumPy 2.0, NumPy's default integer is 32bit on 32bit platforms
and 64bit on 64bit platforms.
Parameters
----------
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
Returns
-------
out : ndarray
Drawn samples, with shape `size`.
See Also
--------
randint : Uniform sampling over a given half-open interval of integers.
random_integers : Uniform sampling over a given closed interval of
integers.
Examples
--------
>>> rs = np.random.RandomState() # need a RandomState object
>>> rs.tomaxint((2,2,2))
array([[[1170048599, 1600360186], # random
[ 739731006, 1947757578]],
[[1871712945, 752307660],
[1601631370, 1479324245]]])
>>> rs.tomaxint((2,2,2)) < np.iinfo(np.int_).max
array([[[ True, True],
[ True, True]],
[[ True, True],
[ True, True]]])
"""
# 声明变量和数组以存储随机数
cdef np.npy_intp n
cdef np.ndarray randoms
cdef int64_t *randoms_data
# 如果 size 为 None,则返回单个随机整数值
if size is None:
# 使用锁保证线程安全,返回从位生成器中生成的随机正整数
with self.lock:
return random_positive_int(&self._bitgen)
# 创建一个空的 ndarray,用于存储随机数,指定数据类型为 np.int64
randoms = <np.ndarray>np.empty(size, dtype=np.int64)
# 获取 randoms 数组的数据指针
randoms_data = <int64_t*>np.PyArray_DATA(randoms)
# 获取 randoms 数组的大小
n = np.PyArray_SIZE(randoms)
# 遍历数组中的每个位置
for i in range(n):
# 使用锁保证线程安全,并且不使用全局解释器锁(GIL)
with self.lock, nogil:
# 调用 random_positive_int 函数生成随机正整数,并将其存储在数组中
randoms_data[i] = random_positive_int(&self._bitgen)
# 返回生成的随机数数组
return randoms
# 定义一个方法 bytes,接受一个整数参数 length
def bytes(self, np.npy_intp length):
"""
bytes(length)
Return random bytes.
.. note::
New code should use the `~numpy.random.Generator.bytes`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
length : int
Number of random bytes.
Returns
-------
out : bytes
String of length `length`.
See Also
--------
random.Generator.bytes: which should be used for new code.
Examples
--------
>>> np.random.bytes(10)
b' eh\\x85\\x022SZ\\xbf\\xa4' #random
"""
# 计算需要的 uint32 数组的长度
cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1)
# 使用 self.randint 生成指定范围内的随机整数数组,并转换为 bytes 类型
# 截取所需长度的字节数据并返回
return self.randint(0, 4294967296, size=n_uint32,
dtype=np.uint32).astype('<u4').tobytes()[:length]
# 定义一个装饰器为 True 的方法 rand,接受可变数量的参数
@cython.wraparound(True)
def rand(self, *args):
"""
rand(d0, d1, ..., dn)
Random values in a given shape.
.. note::
This is a convenience function for users porting code from Matlab,
and wraps `random_sample`. That function takes a
tuple to specify the size of the output, which is consistent with
other NumPy functions like `numpy.zeros` and `numpy.ones`.
Create an array of the given shape and populate it with
random samples from a uniform distribution
over ``[0, 1)``.
Parameters
----------
d0, d1, ..., dn : int, optional
The dimensions of the returned array, must be non-negative.
If no argument is given a single Python float is returned.
Returns
-------
out : ndarray, shape ``(d0, d1, ..., dn)``
Random values.
See Also
--------
random
Examples
--------
>>> np.random.rand(3,2)
array([[ 0.14022471, 0.96360618], #random
[ 0.37601032, 0.25528411], #random
[ 0.49313049, 0.94909878]]) #random
"""
# 如果没有传入参数,则调用 self.random_sample() 返回随机样本
if len(args) == 0:
return self.random_sample()
else:
# 否则,根据传入的参数 size,调用 self.random_sample(size=args) 返回随机样本
return self.random_sample(size=args)
# 定义一个方法 randn,用于生成服从标准正态分布的随机数或数组
"""
randn(d0, d1, ..., dn)
从标准正态分布中返回一个样本(或多个样本)。
.. note::
这是一个方便的函数,用于从 Matlab 移植代码,
它封装了 `standard_normal`。该函数接受一个元组来指定输出的大小,
这与 `numpy.zeros` 和 `numpy.ones` 等其他 NumPy 函数保持一致。
.. note::
新代码应该使用 `~numpy.random.Generator.standard_normal`
方法的方式来生成随机数;
请参阅 :ref:`random-quick-start`。
如果提供了正整数参数,`randn` 将生成一个形状为 ``(d0, d1, ..., dn)`` 的数组,
其中填充有从均值为 0、方差为 1 的单变量“正态”(高斯)分布中随机抽取的浮点数。
如果没有提供参数,则返回从分布中随机抽取的单个浮点数。
Parameters
----------
d0, d1, ..., dn : int, optional
返回数组的维度,必须是非负整数。
如果没有给出参数,则返回一个 Python 浮点数。
Returns
-------
Z : ndarray or float
形状为 ``(d0, d1, ..., dn)`` 的浮点数样本数组,
或者如果未提供参数,则返回单个这样的浮点数。
See Also
--------
standard_normal : 类似,但接受一个元组作为其参数。
normal : 还接受 mu 和 sigma 参数。
random.Generator.standard_normal: 新代码应使用此方法。
Notes
-----
对于均值为 ``mu``,标准差为 ``sigma`` 的正态分布的随机样本,请使用::
sigma * np.random.randn(...) + mu
Examples
--------
>>> np.random.randn()
2.1923875335537315 # 随机数
从均值为 3、标准差为 2.5 的正态分布中抽取的 2x4 数组样本:
>>> 3 + 2.5 * np.random.randn(2, 4)
array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # 随机数
[ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # 随机数
"""
# 如果参数长度为 0,调用 self.standard_normal() 返回一个随机数
if len(args) == 0:
return self.standard_normal()
# 否则,调用 self.standard_normal(size=args) 返回一个随机数组
else:
return self.standard_normal(size=args)
# 复杂、连续分布的生成函数:
def standard_normal(self, size=None):
"""
standard_normal(size=None)
Draw samples from a standard Normal distribution (mean=0, stdev=1).
.. note::
New code should use the
`~numpy.random.Generator.standard_normal`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
Returns
-------
out : float or ndarray
A floating-point array of shape ``size`` of drawn samples, or a
single sample if ``size`` was not specified.
See Also
--------
normal :
Equivalent function with additional ``loc`` and ``scale`` arguments
for setting the mean and standard deviation.
random.Generator.standard_normal: which should be used for new code.
Notes
-----
For random samples from the normal distribution with mean ``mu`` and
standard deviation ``sigma``, use one of::
mu + sigma * np.random.standard_normal(size=...)
np.random.normal(mu, sigma, size=...)
Examples
--------
>>> np.random.standard_normal()
2.1923875335537315 #random
>>> s = np.random.standard_normal(8000)
>>> s
array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, # random
-0.38672696, -0.4685006 ]) # random
>>> s.shape
(8000,)
>>> s = np.random.standard_normal(size=(3, 4, 2))
>>> s.shape
(3, 4, 2)
Two-by-four array of samples from the normal distribution with
mean 3 and standard deviation 2.5:
>>> 3 + 2.5 * np.random.standard_normal(size=(2, 4))
array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random
[ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
"""
使用C语言扩展函数cont()来生成标准正态分布的随机数样本,此函数接受多个参数用于控制生成的随机数属性和状态。
返回生成的随机数数组或单个随机数值。
"""
return cont(&legacy_gauss, &self._aug_state, size, self.lock, 0,
None, None, CONS_NONE,
None, None, CONS_NONE,
None, None, CONS_NONE,
None)
def chisquare(self, df, size=None):
"""
chisquare(df, size=None)
Draw samples from a chi-square distribution.
When `df` independent random variables, each with standard normal
distributions (mean 0, variance 1), are squared and summed, the
resulting distribution is chi-square (see Notes). This distribution
is often used in hypothesis testing.
.. note::
New code should use the `~numpy.random.Generator.chisquare`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
df : float or array_like of floats
Number of degrees of freedom, must be > 0.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
a single value is returned if ``df`` is a scalar. Otherwise,
``np.array(df).size`` samples are drawn.
Returns
-------
out : ndarray or scalar
Drawn samples from the parameterized chi-square distribution.
Raises
------
ValueError
When `df` <= 0 or when an inappropriate `size` (e.g. ``size=-1``)
is given.
See Also
--------
random.Generator.chisquare: which should be used for new code.
Notes
-----
The variable obtained by summing the squares of `df` independent,
standard normally distributed random variables:
.. math:: Q = \\sum_{i=0}^{\\mathtt{df}} X^2_i
is chi-square distributed, denoted
.. math:: Q \\sim \\chi^2_k.
The probability density function of the chi-squared distribution is
.. math:: p(x) = \\frac{(1/2)^{k/2}}{\\Gamma(k/2)}
x^{k/2 - 1} e^{-x/2},
where :math:`\\Gamma` is the gamma function,
.. math:: \\Gamma(x) = \\int_0^{-\\infty} t^{x - 1} e^{-t} dt.
References
----------
.. [1] NIST "Engineering Statistics Handbook"
https://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm
Examples
--------
>>> np.random.chisquare(2,4)
array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random
"""
# 调用 legacy_chisquare 函数生成卡方分布的样本,并返回结果
return cont(&legacy_chisquare, &self._aug_state, size, self.lock, 1,
df, 'df', CONS_POSITIVE,
0.0, '', CONS_NONE,
0.0, '', CONS_NONE, None)
def standard_cauchy(self, size=None):
"""
standard_cauchy(size=None)
Draw samples from a standard Cauchy distribution with mode = 0.
Also known as the Lorentz distribution.
.. note::
New code should use the
`~numpy.random.Generator.standard_cauchy`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
single value is returned.
Returns
-------
samples : ndarray or scalar
The drawn samples.
See Also
--------
random.Generator.standard_cauchy: which should be used for new code.
Notes
-----
The probability density function for the full Cauchy distribution is
.. math:: P(x; x_0, \\gamma) = \\frac{1}{\\pi \\gamma \\bigl[ 1+
(\\frac{x-x_0}{\\gamma})^2 \\bigr] }
and the Standard Cauchy distribution just sets :math:`x_0=0` and
:math:`\\gamma=1`
The Cauchy distribution arises in the solution to the driven harmonic
oscillator problem, and also describes spectral line broadening. It
also describes the distribution of values at which a line tilted at
a random angle will cut the x axis.
When studying hypothesis tests that assume normality, seeing how the
tests perform on data from a Cauchy distribution is a good indicator of
their sensitivity to a heavy-tailed distribution, since the Cauchy looks
very much like a Gaussian distribution, but with heavier tails.
References
----------
.. [1] NIST/SEMATECH e-Handbook of Statistical Methods, "Cauchy
Distribution",
https://www.itl.nist.gov/div898/handbook/eda/section3/eda3663.htm
.. [2] Weisstein, Eric W. "Cauchy Distribution." From MathWorld--A
Wolfram Web Resource.
https://mathworld.wolfram.com/CauchyDistribution.html
.. [3] Wikipedia, "Cauchy distribution"
https://en.wikipedia.org/wiki/Cauchy_distribution
Examples
--------
Draw samples and plot the distribution:
>>> import matplotlib.pyplot as plt
>>> s = np.random.standard_cauchy(1000000)
>>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well
>>> plt.hist(s, bins=100)
>>> plt.show()
"""
# 返回一个从标准 Cauchy 分布中抽取的样本
return cont(&legacy_standard_cauchy, &self._aug_state, size, self.lock, 0,
0.0, '', CONS_NONE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None)
# 定义一个 rayleigh 方法,用于生成 Rayleigh 分布的随机样本
def rayleigh(self, scale=1.0, size=None):
"""
rayleigh(scale=1.0, size=None)
Draw samples from a Rayleigh distribution.
The :math:`\\chi` and Weibull distributions are generalizations of the
Rayleigh.
.. note::
New code should use the `~numpy.random.Generator.rayleigh`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
scale : float or array_like of floats, optional
Scale, also equals the mode. Must be non-negative. Default is 1.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
a single value is returned if ``scale`` is a scalar. Otherwise,
``np.array(scale).size`` samples are drawn.
Returns
-------
out : ndarray or scalar
Drawn samples from the parameterized Rayleigh distribution.
See Also
--------
random.Generator.rayleigh: which should be used for new code.
Notes
-----
The probability density function for the Rayleigh distribution is
.. math:: P(x;scale) = \\frac{x}{scale^2}e^{\\frac{-x^2}{2 \\cdotp scale^2}}
The Rayleigh distribution would arise, for example, if the East
and North components of the wind velocity had identical zero-mean
Gaussian distributions. Then the wind speed would have a Rayleigh
distribution.
References
----------
.. [1] Brighton Webs Ltd., "Rayleigh Distribution,"
https://web.archive.org/web/20090514091424/http://brighton-webs.co.uk:80/distributions/rayleigh.asp
.. [2] Wikipedia, "Rayleigh distribution"
https://en.wikipedia.org/wiki/Rayleigh_distribution
Examples
--------
Draw values from the distribution and plot the histogram
>>> from matplotlib.pyplot import hist
>>> values = hist(np.random.rayleigh(3, 100000), bins=200, density=True)
Wave heights tend to follow a Rayleigh distribution. If the mean wave
height is 1 meter, what fraction of waves are likely to be larger than 3
meters?
>>> meanvalue = 1
>>> modevalue = np.sqrt(2 / np.pi) * meanvalue
>>> s = np.random.rayleigh(modevalue, 1000000)
The percentage of waves larger than 3 meters is:
>>> 100.*sum(s>3)/1000000.
0.087300000000000003 # random
"""
# 调用底层 C 函数生成 Rayleigh 分布的样本
return cont(&legacy_rayleigh, &self._bitgen, size, self.lock, 1,
scale, 'scale', CONS_NON_NEGATIVE,
0.0, '', CONS_NONE,
0.0, '', CONS_NONE, None)
# Complicated, discrete distributions:
def poisson(self, lam=1.0, size=None):
"""
poisson(lam=1.0, size=None)
Draw samples from a Poisson distribution.
The Poisson distribution is the limit of the binomial distribution
for large N.
.. note::
New code should use the `~numpy.random.Generator.poisson`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
lam : float or array_like of floats
Expected number of events occurring in a fixed-time interval,
must be >= 0. A sequence must be broadcastable over the requested
size.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
a single value is returned if ``lam`` is a scalar. Otherwise,
``np.array(lam).size`` samples are drawn.
Returns
-------
out : ndarray or scalar
Drawn samples from the parameterized Poisson distribution.
See Also
--------
random.Generator.poisson: which should be used for new code.
Notes
-----
The Poisson distribution
.. math:: f(k; \\lambda)=\\frac{\\lambda^k e^{-\\lambda}}{k!}
For events with an expected separation :math:`\\lambda` the Poisson
distribution :math:`f(k; \\lambda)` describes the probability of
:math:`k` events occurring within the observed
interval :math:`\\lambda`.
Because the output is limited to the range of the C int64 type, a
ValueError is raised when `lam` is within 10 sigma of the maximum
representable value.
References
----------
.. [1] Weisstein, Eric W. "Poisson Distribution."
From MathWorld--A Wolfram Web Resource.
https://mathworld.wolfram.com/PoissonDistribution.html
.. [2] Wikipedia, "Poisson distribution",
https://en.wikipedia.org/wiki/Poisson_distribution
Examples
--------
Draw samples from the distribution:
>>> import numpy as np
>>> s = np.random.poisson(5, 10000)
Display histogram of the sample:
>>> import matplotlib.pyplot as plt
>>> count, bins, ignored = plt.hist(s, 14, density=True)
>>> plt.show()
Draw each 100 values for lambda 100 and 500:
>>> s = np.random.poisson(lam=(100., 500.), size=(100, 2))
"""
# 使用底层函数 disc() 生成泊松分布的随机样本
out = disc(&legacy_random_poisson, &self._bitgen, size, self.lock, 1, 0,
lam, 'lam', LEGACY_CONS_POISSON,
0.0, '', CONS_NONE,
0.0, '', CONS_NONE)
# 将输出从 int64 转换为 Python long 类型,以匹配历史输出类型
return int64_to_long(out)
def geometric(self, p, size=None):
"""
geometric(p, size=None)
Draw samples from the geometric distribution.
Bernoulli trials are experiments with one of two outcomes:
success or failure (an example of such an experiment is flipping
a coin). The geometric distribution models the number of trials
that must be run in order to achieve success. It is therefore
supported on the positive integers, ``k = 1, 2, ...``.
The probability mass function of the geometric distribution is
.. math:: f(k) = (1 - p)^{k - 1} p
where `p` is the probability of success of an individual trial.
.. note::
New code should use the `~numpy.random.Generator.geometric`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
p : float or array_like of floats
The probability of success of an individual trial.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
a single value is returned if ``p`` is a scalar. Otherwise,
``np.array(p).size`` samples are drawn.
Returns
-------
out : ndarray or scalar
Drawn samples from the parameterized geometric distribution.
See Also
--------
random.Generator.geometric: which should be used for new code.
Examples
--------
Draw ten thousand values from the geometric distribution,
with the probability of an individual success equal to 0.35:
>>> z = np.random.geometric(p=0.35, size=10000)
How many trials succeeded after a single run?
>>> (z == 1).sum() / 10000.
0.34889999999999999 #random
"""
# 调用底层函数 disc,实现几何分布的采样
out = disc(&legacy_random_geometric, &self._bitgen, size, self.lock, 1, 0,
p, 'p', CONS_BOUNDED_GT_0_1,
0.0, '', CONS_NONE,
0.0, '', CONS_NONE)
# 将输出转换为 long 类型并返回,以匹配历史输出类型
return int64_to_long(out)
# Multivariate distributions:
# Shuffling and permutations:
# 在原地对数据进行混洗操作,实现洗牌和排列
cdef inline _shuffle_raw(self, np.npy_intp n, np.npy_intp itemsize,
np.npy_intp stride, char* data, char* buf):
cdef np.npy_intp i, j
# 从 n-1 到 1 的范围内反向遍历
for i in reversed(range(1, n)):
# 使用随机数生成器选择一个随机位置 j
j = random_interval(&self._bitgen, i)
# 将位置 j 的数据复制到缓冲区
string.memcpy(buf, data + j * stride, itemsize)
# 将位置 i 的数据复制到位置 j
string.memcpy(data + j * stride, data + i * stride, itemsize)
# 将缓冲区的数据复制到位置 i
string.memcpy(data + i * stride, buf, itemsize)
def permutation(self, object x):
"""
permutation(x)
Randomly permute a sequence, or return a permuted range.
If `x` is a multi-dimensional array, it is only shuffled along its
first index.
.. note::
New code should use the
`~numpy.random.Generator.permutation`
method of a `~numpy.random.Generator` instance instead;
please see the :ref:`random-quick-start`.
Parameters
----------
x : int or array_like
If `x` is an integer, randomly permute ``np.arange(x)``.
If `x` is an array, make a copy and shuffle the elements
randomly.
Returns
-------
out : ndarray
Permuted sequence or array range.
See Also
--------
random.Generator.permutation: which should be used for new code.
Examples
--------
>>> np.random.permutation(10)
array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random
>>> np.random.permutation([1, 4, 9, 12, 15])
array([15, 1, 9, 4, 12]) # random
>>> arr = np.arange(9).reshape((3, 3))
>>> np.random.permutation(arr)
array([[6, 7, 8], # random
[0, 1, 2],
[3, 4, 5]])
"""
if isinstance(x, (int, np.integer)):
# 创建一个整数范围的数组 arr,使用 long 作为默认类型(主 numpy 已切换到 intp)
arr = np.arange(x, dtype=np.result_type(x, np.long))
# 对数组 arr 进行洗牌操作
self.shuffle(arr)
# 返回洗牌后的数组 arr
return arr
arr = np.asarray(x)
if arr.ndim < 1:
# 如果 x 不是整数且不是至少一维的数组,则引发索引错误
raise IndexError("x must be an integer or at least 1-dimensional")
# 对于一维数组,shuffle 方法有快速路径
if arr.ndim == 1:
# 如果 arr 和 x 共享内存,则返回 arr 的拷贝
if np.may_share_memory(arr, x):
arr = np.array(arr)
# 对 arr 进行洗牌操作
self.shuffle(arr)
# 返回洗牌后的数组 arr
return arr
# 洗牌索引数组 idx,指定 dtype 以确保快速路径
idx = np.arange(arr.shape[0], dtype=np.intp)
self.shuffle(idx)
# 根据洗牌后的 idx 对 arr 进行索引,返回重新排列后的数组
return arr[idx]
# 创建一个名为 _rand 的 RandomState 的实例,用于生成随机数
_rand = RandomState()
# 以下是一系列变量,它们分别是 _rand 实例的不同随机变量生成方法
beta = _rand.beta # 生成 Beta 分布的随机数
binomial = _rand.binomial # 生成二项分布的随机数
bytes = _rand.bytes # 生成随机字节串
chisquare = _rand.chisquare # 生成卡方分布的随机数
choice = _rand.choice # 从给定序列中随机选择元素
dirichlet = _rand.dirichlet # 生成 Dirichlet 分布的随机数
exponential = _rand.exponential # 生成指数分布的随机数
f = _rand.f # 生成 F 分布的随机数
gamma = _rand.gamma # 生成 Gamma 分布的随机数
get_state = _rand.get_state # 获取 RandomState 实例的状态
geometric = _rand.geometric # 生成几何分布的随机数
gumbel = _rand.gumbel # 生成 Gumbel 分布的随机数
hypergeometric = _rand.hypergeometric # 生成超几何分布的随机数
laplace = _rand.laplace # 生成拉普拉斯分布的随机数
logistic = _rand.logistic # 生成 Logistic 分布的随机数
lognormal = _rand.lognormal # 生成对数正态分布的随机数
logseries = _rand.logseries # 生成对数级数分布的随机数
multinomial = _rand.multinomial # 生成多项分布的随机数
multivariate_normal = _rand.multivariate_normal # 生成多元正态分布的随机数
negative_binomial = _rand.negative_binomial # 生成负二项分布的随机数
noncentral_chisquare = _rand.noncentral_chisquare # 生成非中心卡方分布的随机数
noncentral_f = _rand.noncentral_f # 生成非中心 F 分布的随机数
normal = _rand.normal # 生成正态分布的随机数
pareto = _rand.pareto # 生成帕累托分布的随机数
permutation = _rand.permutation # 随机排列给定序列
poisson = _rand.poisson # 生成泊松分布的随机数
power = _rand.power # 生成功率分布的随机数
rand = _rand.rand # 生成均匀分布的随机数
randint = _rand.randint # 生成指定范围内的随机整数
randn = _rand.randn # 生成标准正态分布的随机数
random = _rand.random # 生成 [0, 1) 范围内的随机数
random_integers = _rand.random_integers # 生成指定范围内的随机整数
random_sample = _rand.random_sample # 生成 [0, 1) 范围内的随机数
rayleigh = _rand.rayleigh # 生成瑞利分布的随机数
set_state = _rand.set_state # 设置 RandomState 实例的状态
shuffle = _rand.shuffle # 将序列随机排序
standard_cauchy = _rand.standard_cauchy # 生成标准 Cauchy 分布的随机数
standard_exponential = _rand.standard_exponential # 生成标准指数分布的随机数
standard_gamma = _rand.standard_gamma # 生成标准 Gamma 分布的随机数
standard_normal = _rand.standard_normal # 生成标准正态分布的随机数
standard_t = _rand.standard_t # 生成标准 t 分布的随机数
triangular = _rand.triangular # 生成三角分布的随机数
uniform = _rand.uniform # 生成均匀分布的随机数
vonmises = _rand.vonmises # 生成 Von Mises 分布的随机数
wald = _rand.wald # 生成 Wald 分布的随机数
weibull = _rand.weibull # 生成 Weibull 分布的随机数
zipf = _rand.zipf # 生成 Zipf 分布的随机数
def seed(seed=None):
"""
设置 RandomState 单例实例的随机数种子
Parameters
----------
seed : int or None, optional
随机数种子,若为 None,则使用系统时间
Notes
-----
这是一个便利的、遗留的函数,用于支持旧代码中使用的单例 RandomState。
最佳实践是使用专用的 ``Generator`` 实例,而不是直接在 random 模块中暴露的随机变量生成方法。
See Also
--------
numpy.random.Generator
"""
if isinstance(_rand._bit_generator, _MT19937):
return _rand.seed(seed)
else:
bg_type = type(_rand._bit_generator)
_rand._bit_generator.state = bg_type(seed).state
def get_bit_generator():
"""
返回 RandomState 单例实例的比特生成器
Returns
-------
BitGenerator
单例 RandomState 实例下面的比特生成器
Notes
-----
单例 RandomState 提供了 ``numpy.random`` 命名空间中的随机变量生成器。
这个函数及其对应的设置方法提供了一条路径,可以用用户提供的替代方案
替换默认的 MT19937 比特生成器。这些函数旨在提供一个连续的路径,
单个底层比特生成器可以同时用于 ``Generator`` 实例和单例 RandomState 实例。
See Also
--------
set_bit_generator
numpy.random.Generator
"""
return _rand._bit_generator
def set_bit_generator(bitgen):
"""
设置 RandomState 单例实例的比特生成器
Parameters
----------
bitgen
比特生成器实例
Notes
-----
这个函数用于设置单例 RandomState 的比特生成器。
"""
# 创建一个变量 singleton,用于存储 _rand 的 RandomState 实例
cdef RandomState singleton
# 将 _rand 赋值给 singleton,使其成为 RandomState 的单例实例
singleton = _rand
# 使用给定的 bitgen 参数初始化 singleton 的位生成器
singleton._initialize_bit_generator(bitgen)
# 定义函数 `sample`,作为 `random_sample` 的别名,详细文档请参考 `random_sample`
def sample(*args, **kwargs):
# 调用 `_rand` 模块的 `random_sample` 函数,并将参数和关键字参数传递给它
return _rand.random_sample(*args, **kwargs)
# 定义函数 `ranf`,作为 `random_sample` 的别名,详细文档请参考 `random_sample`
def ranf(*args, **kwargs):
# 调用 `_rand` 模块的 `random_sample` 函数,并将参数和关键字参数传递给它
return _rand.random_sample(*args, **kwargs)
# 列出该模块中公开的所有函数和类的名称,以便通过 `from module import *` 导入
__all__ = [
'beta',
'binomial',
'bytes',
'chisquare',
'choice',
'dirichlet',
'exponential',
'f',
'gamma',
'geometric',
'get_bit_generator',
'get_state',
'gumbel',
'hypergeometric',
'laplace',
'logistic',
'lognormal',
'logseries',
'multinomial',
'multivariate_normal',
'negative_binomial',
'noncentral_chisquare',
'noncentral_f',
'normal',
'pareto',
'permutation',
'poisson',
'power',
'rand',
'randint',
'randn',
'random',
'random_integers',
'random_sample',
'ranf',
'rayleigh',
'sample',
'seed',
'set_bit_generator',
'set_state',
'shuffle',
'standard_cauchy',
'standard_exponential',
'standard_gamma',
'standard_normal',
'standard_t',
'triangular',
'uniform',
'vonmises',
'wald',
'weibull',
'zipf',
'RandomState',
]
.\numpy\numpy\random\src\distributions\distributions.c
/* 包含头文件 numpy/random/distributions.h */
#include "numpy/random/distributions.h"
/* 包含头文件 ziggurat_constants.h */
#include "ziggurat_constants.h"
/* 包含头文件 logfactorial.h */
#include "logfactorial.h"
/* 如果编译器是 MSC 并且是 64 位 Windows */
#if defined(_MSC_VER) && defined(_WIN64)
/* 包含内置函数头文件 */
#include <intrin.h>
#endif
/* 包含标准断言头文件 */
#include <assert.h>
/* 内联函数定义,生成内部使用的 uint32_t 类型随机数 */
static inline uint32_t next_uint32(bitgen_t *bitgen_state) {
return bitgen_state->next_uint32(bitgen_state->state);
}
/* 内联函数定义,生成内部使用的 uint64_t 类型随机数 */
static inline uint64_t next_uint64(bitgen_t *bitgen_state) {
return bitgen_state->next_uint64(bitgen_state->state);
}
/* 内联函数定义,生成内部使用的 float 类型随机数 */
static inline float next_float(bitgen_t *bitgen_state) {
return (next_uint32(bitgen_state) >> 8) * (1.0f / 16777216.0f);
}
/* 外部使用的随机数生成器,生成标准均匀分布的 float 类型随机数 */
float random_standard_uniform_f(bitgen_t *bitgen_state) {
return next_float(bitgen_state);
}
/* 外部使用的随机数生成器,生成标准均匀分布的 double 类型随机数 */
double random_standard_uniform(bitgen_t *bitgen_state) {
return next_double(bitgen_state);
}
/* 外部使用的随机数生成器,将标准均匀分布的 double 类型随机数填充到数组中 */
void random_standard_uniform_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) {
npy_intp i;
for (i = 0; i < cnt; i++) {
out[i] = next_double(bitgen_state);
}
}
/* 外部使用的随机数生成器,将标准均匀分布的 float 类型随机数填充到数组中 */
void random_standard_uniform_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) {
npy_intp i;
for (i = 0; i < cnt; i++) {
out[i] = next_float(bitgen_state);
}
}
/* 内部静态函数定义,生成不常见的指数分布随机数 */
static double standard_exponential_unlikely(bitgen_t *bitgen_state,
uint8_t idx, double x) {
if (idx == 0) {
/* 切换到 1.0 - U 以避免 log(0.0),参见 GitHub 13361 */
return ziggurat_exp_r - npy_log1p(-next_double(bitgen_state));
} else if ((fe_double[idx - 1] - fe_double[idx]) * next_double(bitgen_state) +
fe_double[idx] <
exp(-x)) {
return x;
} else {
return random_standard_exponential(bitgen_state);
}
}
/* 外部使用的随机数生成器,生成标准指数分布的 double 类型随机数 */
double random_standard_exponential(bitgen_t *bitgen_state) {
uint64_t ri;
uint8_t idx;
double x;
ri = next_uint64(bitgen_state);
ri >>= 3;
idx = ri & 0xFF;
ri >>= 8;
x = ri * we_double[idx];
if (ri < ke_double[idx]) {
return x; /* 98.9% 的时间我们在第一次尝试时返回这里 */
}
return standard_exponential_unlikely(bitgen_state, idx, x);
}
/* 外部使用的随机数生成器,将标准指数分布的 double 类型随机数填充到数组中 */
void random_standard_exponential_fill(bitgen_t * bitgen_state, npy_intp cnt, double * out)
{
npy_intp i;
for (i = 0; i < cnt; i++) {
out[i] = random_standard_exponential(bitgen_state);
}
}
/* 内部静态函数定义,生成不常见的指数分布随机数 */
static float standard_exponential_unlikely_f(bitgen_t *bitgen_state,
uint8_t idx, float x) {
if (idx == 0) {
/* 切换到 1.0 - U 以避免 log(0.0),参见 GitHub 13361 */
return ziggurat_exp_r_f - npy_log1pf(-next_float(bitgen_state));
} else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(bitgen_state) +
fe_float[idx] <
expf(-x)) {
return x;
} else {
return random_standard_exponential_f(bitgen_state);
}
}
float random_standard_exponential_f(bitgen_t *bitgen_state) {
uint32_t ri; /* 声明一个无符号32位整数变量 ri */
uint8_t idx; /* 声明一个无符号8位整数变量 idx */
float x; /* 声明一个单精度浮点数变量 x */
ri = next_uint32(bitgen_state); /* 调用函数 next_uint32 获取一个随机的32位无符号整数并赋值给 ri */
ri >>= 1; /* 将 ri 右移1位 */
idx = ri & 0xFF; /* 将 ri 的低8位保存到 idx 中 */
ri >>= 8; /* 将 ri 右移8位 */
x = ri * we_float[idx]; /* 计算 x = ri * we_float[idx],其中 we_float 是一个预先定义的数组 */
if (ri < ke_float[idx]) { /* 如果 ri 小于 ke_float[idx],返回 x */
return x; /* 98.9% of the time we return here 1st try */
}
return standard_exponential_unlikely_f(bitgen_state, idx, x); /* 否则调用函数 standard_exponential_unlikely_f 处理 */
}
void random_standard_exponential_fill_f(bitgen_t * bitgen_state, npy_intp cnt, float * out)
{
npy_intp i; /* 声明一个用于循环的变量 i */
for (i = 0; i < cnt; i++) { /* 循环 cnt 次 */
out[i] = random_standard_exponential_f(bitgen_state); /* 调用函数 random_standard_exponential_f 获取一个随机指数分布数值并存入 out 数组 */
}
}
void random_standard_exponential_inv_fill(bitgen_t * bitgen_state, npy_intp cnt, double * out)
{
npy_intp i; /* 声明一个用于循环的变量 i */
for (i = 0; i < cnt; i++) { /* 循环 cnt 次 */
out[i] = -npy_log1p(-next_double(bitgen_state)); /* 使用 next_double 获取一个随机的双精度浮点数,计算其负对数并存入 out 数组 */
}
}
void random_standard_exponential_inv_fill_f(bitgen_t * bitgen_state, npy_intp cnt, float * out)
{
npy_intp i; /* 声明一个用于循环的变量 i */
for (i = 0; i < cnt; i++) { /* 循环 cnt 次 */
out[i] = -npy_log1p(-next_float(bitgen_state)); /* 使用 next_float 获取一个随机的单精度浮点数,计算其负对数并存入 out 数组 */
}
}
double random_standard_normal(bitgen_t *bitgen_state) {
uint64_t r; /* 声明一个无符号64位整数变量 r */
int sign; /* 声明一个整数变量 sign */
uint64_t rabs; /* 声明一个无符号64位整数变量 rabs */
int idx; /* 声明一个整数变量 idx */
double x, xx, yy; /* 声明三个双精度浮点数变量 x, xx, yy */
for (;;) { /* 无限循环 */
/* r = e3n52sb8 */
r = next_uint64(bitgen_state); /* 调用函数 next_uint64 获取一个随机的64位无符号整数并赋值给 r */
idx = r & 0xff; /* 将 r 的低8位保存到 idx 中 */
r >>= 8; /* 将 r 右移8位 */
sign = r & 0x1; /* 将 r 的最低位保存到 sign 中 */
rabs = (r >> 1) & 0x000fffffffffffff; /* 将 r 的除最低位外的部分保存到 rabs 中 */
x = rabs * wi_double[idx]; /* 计算 x = rabs * wi_double[idx],其中 wi_double 是一个预先定义的数组 */
if (sign & 0x1) /* 如果 sign 的最低位为1 */
x = -x; /* 将 x 取负 */
if (rabs < ki_double[idx]) /* 如果 rabs 小于 ki_double[idx] */
return x; /* 99.3% of the time return here */
if (idx == 0) { /* 如果 idx 等于0 */
for (;;) { /* 无限循环 */
/* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */
xx = -ziggurat_nor_inv_r * npy_log1p(-next_double(bitgen_state)); /* 使用 next_double 获取一个随机的双精度浮点数,计算其负对数并乘以常数 xx */
yy = -npy_log1p(-next_double(bitgen_state)); /* 使用 next_double 获取一个随机的双精度浮点数,计算其负对数并保存到 yy */
if (yy + yy > xx * xx) /* 如果 yy 的两倍大于 xx 的平方 */
return ((rabs >> 8) & 0x1) ? -(ziggurat_nor_r + xx) : ziggurat_nor_r + xx; /* 返回 ziggurat_nor_r 和 xx 的和或差 */
}
} else {
if (((fi_double[idx - 1] - fi_double[idx]) * next_double(bitgen_state) + fi_double[idx]) < exp(-0.5 * x * x))
return x; /* 返回 x */
}
}
}
void random_standard_normal_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) {
npy_intp i; /* 声明一个用于循环的变量 i */
for (i = 0; i < cnt; i++) { /* 循环 cnt 次 */
out[i] = random_standard_normal(bitgen_state); /* 调用函数 random_standard_normal 获取一个随机正态分布数值并存入 out 数组 */
}
}
float random_standard_normal_f(bitgen_t *bitgen_state) {
uint32_t r; /* 声明一个无符号32位整数变量 r */
int sign; /* 声明一个整数变量 sign */
uint32_t rabs; /* 声明一个无符号32位整数变量 rabs */
int idx; /* 声明一个整数变量 idx */
float x, xx, yy; /* 声明三个单精度浮点数变量 x, xx, yy */
for (;;) { /* 无限循环 */
/* r = n23sb8 */
r = next_uint32(bitgen_state); /* 调用函数 next_uint32 获取一个随机的32位无符号整数并赋值给 r */
idx = r & 0xff; /* 将 r 的低8位保存到 idx 中 */
sign = (r >> 8) & 0x1; /* 将 r 的第9位保存到 sign 中 */
rabs = (r >> 9) & 0x0007fffff; /* 将 r 的第10位到第30位保存到 rabs 中 */
x = rabs * wi_float[idx]; /* 计算 x = rabs * wi_float[idx],其中 wi_float 是一个预先定义的数组 */
if (sign & 0x1) /* 如果 sign 的最低位为1 */
x = -x; /* 将 x 取负 */
if (rabs < ki_float[idx]) /* 如果 rabs 小于 ki_float[idx] */
return x; /* # 99.3% of the time return here */
if (idx == 0) { /* 如果 idx 等于0 */
for (;;) { /* 无限循环 */
/* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */
xx = -ziggurat_nor_inv_r_f * npy_log1pf(-next_float(bitgen_state)); /* 使用 next_float 获取一个随机的单精度浮点数,计算其负对数并乘以常数 xx */
yy = -npy_log1pf(-next_float(bitgen_state));
} else {
# 如果条件不满足上述第一个条件,执行以下代码块
if (((fi_float[idx - 1] - fi_float[idx]) * next_float(bitgen_state) +
fi_float[idx]) < exp(-0.5 * x * x))
# 如果计算出的新值小于指数函数的结果,则返回当前的 x 值
return x;
}
}
/* 从正态分布中生成随机数填充到浮点数数组中 */
void random_standard_normal_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) {
npy_intp i;
// 循环生成指定数量的随机数
for (i = 0; i < cnt; i++) {
// 调用 random_standard_normal_f 函数生成一个标准正态分布的随机数,并填充到数组中
out[i] = random_standard_normal_f(bitgen_state);
}
}
/* 生成标准 Gamma 分布的随机数 */
double random_standard_gamma(bitgen_t *bitgen_state, double shape) {
double b, c;
double U, V, X, Y;
// 如果形状参数 shape 等于 1.0,则返回标准指数分布的随机数
if (shape == 1.0) {
return random_standard_exponential(bitgen_state);
}
// 如果形状参数 shape 等于 0.0,则直接返回 0.0
else if (shape == 0.0) {
return 0.0;
}
// 如果形状参数 shape 小于 1.0
else if (shape < 1.0) {
// 开始无限循环,直到生成符合条件的随机数
for (;;) {
// 生成 [0, 1) 区间内的均匀分布随机数 U 和标准指数分布随机数 V
U = next_double(bitgen_state);
V = random_standard_exponential(bitgen_state);
if (U <= 1.0 - shape) {
// 如果 U 小于等于 1-shape,则根据逆变换法计算 X
X = pow(U, 1. / shape);
if (X <= V) {
return X;
}
} else {
// 否则,根据逆变换法计算 Y 和 X
Y = -log((1 - U) / shape);
X = pow(1.0 - shape + shape * Y, 1. / shape);
if (X <= (V + Y)) {
return X;
}
}
}
}
// 如果形状参数 shape 大于等于 1.0
else {
// 计算辅助变量 b 和 c
b = shape - 1. / 3.;
c = 1. / sqrt(9 * b);
// 开始无限循环,直到生成符合条件的随机数
for (;;) {
do {
// 生成标准正态分布的随机数 X 和 V
X = random_standard_normal(bitgen_state);
V = 1.0 + c * X;
} while (V <= 0.0);
V = V * V * V;
// 生成 [0, 1) 区间内的均匀分布随机数 U
U = next_double(bitgen_state);
if (U < 1.0 - 0.0331 * (X * X) * (X * X))
return (b * V);
// log(0.0) 在这里是允许的,用于比较
if (log(U) < 0.5 * X * X + b * (1. - V + log(V)))
return (b * V);
}
}
}
/* 生成标准 Gamma 分布的随机数(单精度浮点数版本) */
float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) {
float b, c;
float U, V, X, Y;
// 如果形状参数 shape 等于 1.0f,则返回标准指数分布的随机数(单精度)
if (shape == 1.0f) {
return random_standard_exponential_f(bitgen_state);
}
// 如果形状参数 shape 等于 0.0,则直接返回 0.0(单精度)
else if (shape == 0.0) {
return 0.0;
}
// 如果形状参数 shape 小于 1.0f
else if (shape < 1.0f) {
// 开始无限循环,直到生成符合条件的随机数
for (;;) {
// 生成 [0, 1) 区间内的均匀分布随机数 U 和标准指数分布随机数 V
U = next_float(bitgen_state);
V = random_standard_exponential_f(bitgen_state);
if (U <= 1.0f - shape) {
// 如果 U 小于等于 1-shape,则根据逆变换法计算 X
X = powf(U, 1.0f / shape);
if (X <= V) {
return X;
}
} else {
// 否则,根据逆变换法计算 Y 和 X
Y = -logf((1.0f - U) / shape);
X = powf(1.0f - shape + shape * Y, 1.0f / shape);
if (X <= (V + Y)) {
return X;
}
}
}
}
// 如果形状参数 shape 大于等于 1.0f
else {
// 计算辅助变量 b 和 c
b = shape - 1.0f / 3.0f;
c = 1.0f / sqrtf(9.0f * b);
// 开始无限循环,直到生成符合条件的随机数
for (;;) {
do {
// 生成标准正态分布的随机数 X 和 V
X = random_standard_normal_f(bitgen_state);
V = 1.0f + c * X;
} while (V <= 0.0f);
V = V * V * V;
// 生成 [0, 1) 区间内的均匀分布随机数 U
U = next_float(bitgen_state);
if (U < 1.0f - 0.0331f * (X * X) * (X * X))
return (b * V);
// logf(0.0f) 在这里是允许的,用于比较
if (logf(U) < 0.5f * X * X + b * (1.0f - V + logf(V)))
return (b * V);
}
}
}
/* 生成正整数类型的随机数(64位) */
int64_t random_positive_int64(bitgen_t *bitgen_state) {
return next_uint64(bitgen_state) >> 1;
}
/* 生成正整数类型的随机数(32位) */
int32_t random_positive_int32(bitgen_t *bitgen_state) {
return next_uint32(bitgen_state) >> 1;
}
/* 生成正整数类型的随机数,根据平台确定返回类型 */
int64_t random_positive_int(bitgen_t *bitgen_state) {
#if ULONG_MAX <= 0xffffffffUL
return (int64_t)(next_uint32(bitgen_state) >> 1);
#else
return (int64_t)(next_uint64(bitgen_state) >> 1);
#endif
}
#if ULONG_MAX <= 0xffffffffUL
// 如果 ULONG_MAX 小于等于 0xffffffffUL,则返回一个 32 位随机数
return next_uint32(bitgen_state);
#else
// 否则返回一个 64 位随机数
return next_uint64(bitgen_state);
#endif
}
/*
* log-gamma 函数用于支持某些分布。该算法来源于张善杰和金建明的《Computation of Special Functions》。
* 如果 random_loggam(k+1) 用于计算整数 k 的 log(k!),建议使用 logfactorial(k)。
*/
double random_loggam(double x) {
double x0, x2, lg2pi, gl, gl0;
RAND_INT_TYPE k, n;
static double a[10] = {8.333333333333333e-02, -2.777777777777778e-03,
7.936507936507937e-04, -5.952380952380952e-04,
8.417508417508418e-04, -1.917526917526918e-03,
6.410256410256410e-03, -2.955065359477124e-02,
1.796443723688307e-01, -1.39243221690590e+00};
if ((x == 1.0) || (x == 2.0)) {
// 当 x 为 1.0 或 2.0 时,直接返回 0.0
return 0.0;
} else if (x < 7.0) {
// 当 x 小于 7.0 时,计算 n
n = (RAND_INT_TYPE)(7 - x);
} else {
// 否则 n 等于 0
n = 0;
}
x0 = x + n;
x2 = (1.0 / x0) * (1.0 / x0);
/* log(2 * M_PI) */
lg2pi = 1.8378770664093453e+00;
gl0 = a[9];
for (k = 8; k >= 0; k--) {
// 使用级数计算 gamma 函数的对数值
gl0 *= x2;
gl0 += a[k];
}
// 计算 gamma 函数的对数值
gl = gl0 / x0 + 0.5 * lg2pi + (x0 - 0.5) * log(x0) - x0;
if (x < 7.0) {
// 如果 x 小于 7.0,进一步调整 gl 的值
for (k = 1; k <= n; k++) {
gl -= log(x0 - 1.0);
x0 -= 1.0;
}
}
// 返回 gamma 函数的对数值
return gl;
}
/*
double random_normal(bitgen_t *bitgen_state, double loc, double scale) {
return loc + scale * random_gauss(bitgen_state);
}
*/
// 使用正态分布函数 random_standard_normal 计算正态分布随机数
double random_normal(bitgen_t *bitgen_state, double loc, double scale) {
return loc + scale * random_standard_normal(bitgen_state);
}
// 使用指数分布函数 random_standard_exponential 计算指数分布随机数
double random_exponential(bitgen_t *bitgen_state, double scale) {
return scale * random_standard_exponential(bitgen_state);
}
// 使用均匀分布函数 next_double 计算均匀分布随机数
double random_uniform(bitgen_t *bitgen_state, double lower, double range) {
return lower + range * next_double(bitgen_state);
}
// 使用 gamma 分布函数 random_standard_gamma 计算 gamma 分布随机数
double random_gamma(bitgen_t *bitgen_state, double shape, double scale) {
return scale * random_standard_gamma(bitgen_state, shape);
}
// 使用 gamma 分布函数 random_standard_gamma_f 计算 gamma 分布随机数(单精度浮点数版本)
float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale) {
return scale * random_standard_gamma_f(bitgen_state, shape);
}
#define BETA_TINY_THRESHOLD 3e-103
/*
* 注意:random_beta 假设 a != 0 且 b != 0。
*/
double random_beta(bitgen_t *bitgen_state, double a, double b) {
double Ga, Gb;
if ((a <= 1.0) && (b <= 1.0)) {
double U, V, X, Y, XpY;
if (a < BETA_TINY_THRESHOLD && b < BETA_TINY_THRESHOLD) {
/*
* 当 a 和 b 很小时,生成随机数的概率非常低,因此使用 a/(a + b) 和一个均匀随机数 U 来生成结果。
*/
U = next_double(bitgen_state);
return (a + b)*U < a;
}
/* 使用 Johnk's 算法 */
U = next_double(bitgen_state);
V = next_double(bitgen_state);
X = pow(U, 1.0 / a);
Y = pow(V, 1.0 / b);
XpY = X + Y;
if (XpY <= 1.0) {
return X / XpY;
} else {
return 1.0;
}
}
/* 使用 Gauss 近似法 */
Ga = random_gamma(bitgen_state, a, 1.0);
Gb = random_gamma(bitgen_state, b, 1.0);
return Ga / (Ga + Gb);
} else {
double alpha, beta, r;
if (a < BETA_TINY_THRESHOLD) {
alpha = 1.0 + b;
beta = 1.0 + b * tan(M_PI * a / 2.0);
r = pow(next_double(bitgen_state), 1.0 / a);
return r / (r + pow(next_double(bitgen_state), 1.0 / (alpha * a)));
}
if (b < BETA_TINY_THRESHOLD) {
alpha = 1.0 + a;
beta = 1.0 + a * tan(M_PI * b / 2.0);
r = pow(next_double(bitgen_state), 1.0 / (alpha * b));
return 1.0 - r / (r + pow(next_double(bitgen_state), 1.0 / b));
}
alpha = a + b;
beta = sqrt((alpha - 2.0) / (2.0 * a * b - alpha));
r = random_normal(bitgen_state, 1.0, beta);
return (1.0 + a * r) / (alpha + alpha * r);
}
}
while (1) {
// 从随机数生成器中获取下一个双精度随机数 U 和 V
U = next_double(bitgen_state);
V = next_double(bitgen_state);
// 计算 U 和 V 的 a 次方根 X 和 b 次方根 Y
X = pow(U, 1.0 / a);
Y = pow(V, 1.0 / b);
// 计算 X 和 Y 的和
XpY = X + Y;
/* 如果 XpY 小于等于 1.0 并且 U + V 大于 0.0,则接受生成的随机数 */
if ((XpY <= 1.0) && (U + V > 0.0)) {
if (XpY > 0) {
// 如果 XpY 大于 0,则返回 X / XpY
return X / XpY;
} else {
// 否则计算对数变换的加权平均数,返回对应的概率密度函数值
double logX = log(U) / a;
double logY = log(V) / b;
double logM = logX > logY ? logX : logY;
logX -= logM;
logY -= logM;
return exp(logX - log(exp(logX) + exp(logY)));
}
}
}
} else {
// 使用标准 Gamma 分布生成器生成随机变量 Ga 和 Gb
Ga = random_standard_gamma(bitgen_state, a);
Gb = random_standard_gamma(bitgen_state, b);
// 返回 Ga / (Ga + Gb) 作为生成的随机数
return Ga / (Ga + Gb);
}
}
// 生成自由度为 df 的卡方分布随机变量的函数
double random_chisquare(bitgen_t *bitgen_state, double df) {
// 调用标准伽马分布函数生成自由度为 df/2 的随机变量,再进行线性变换得到卡方分布随机变量
return 2.0 * random_standard_gamma(bitgen_state, df / 2.0);
}
// 生成自由度为 dfnum 和 dfden 的 F 分布随机变量的函数
double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) {
// 使用随机卡方分布函数生成自由度为 dfnum 和 dfden 的两个卡方分布随机变量,并进行线性变换得到 F 分布随机变量
return ((random_chisquare(bitgen_state, dfnum) * dfden) /
(random_chisquare(bitgen_state, dfden) * dfnum));
}
// 生成标准柯西分布随机变量的函数
double random_standard_cauchy(bitgen_t *bitgen_state) {
// 生成两个标准正态分布随机变量,并用其比值得到标准柯西分布随机变量
return random_standard_normal(bitgen_state) / random_standard_normal(bitgen_state);
}
// 生成参数为 a 的帕累托分布随机变量的函数
double random_pareto(bitgen_t *bitgen_state, double a) {
// 生成标准指数分布随机变量,进行线性变换得到帕累托分布随机变量
return expm1(random_standard_exponential(bitgen_state) / a);
}
// 生成参数为 a 的威布尔分布随机变量的函数
double random_weibull(bitgen_t *bitgen_state, double a) {
if (a == 0.0) {
return 0.0;
}
// 生成标准指数分布随机变量,进行幂运算得到威布尔分布随机变量
return pow(random_standard_exponential(bitgen_state), 1. / a);
}
// 生成参数为 a 的幂律分布随机变量的函数
double random_power(bitgen_t *bitgen_state, double a) {
// 生成标准指数分布随机变量,进行幂运算和逆运算得到幂律分布随机变量
return pow(-expm1(-random_standard_exponential(bitgen_state)), 1. / a);
}
// 生成参数为 loc 和 scale 的拉普拉斯分布随机变量的函数
double random_laplace(bitgen_t *bitgen_state, double loc, double scale) {
double U;
U = next_double(bitgen_state);
if (U >= 0.5) {
// 生成两个均匀分布随机变量,进行对数变换得到拉普拉斯分布随机变量
U = loc - scale * log(2.0 - U - U);
} else if (U > 0.0) {
// 生成两个均匀分布随机变量,进行对数变换得到拉普拉斯分布随机变量
U = loc + scale * log(U + U);
} else {
/* 拒绝 U == 0.0 并重新调用以获取下一个值 */
U = random_laplace(bitgen_state, loc, scale);
}
return U;
}
// 生成参数为 loc 和 scale 的冈伯尔分布随机变量的函数
double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) {
double U;
U = 1.0 - next_double(bitgen_state);
if (U < 1.0) {
// 生成均匀分布随机变量,进行对数变换得到冈伯尔分布随机变量
return loc - scale * log(-log(U));
}
/* 拒绝 U == 1.0 并重新调用以获取下一个值 */
return random_gumbel(bitgen_state, loc, scale);
}
// 生成参数为 loc 和 scale 的逻辑斯蒂分布随机变量的函数
double random_logistic(bitgen_t *bitgen_state, double loc, double scale) {
double U;
U = next_double(bitgen_state);
if (U > 0.0) {
// 生成均匀分布随机变量,进行对数变换得到逻辑斯蒂分布随机变量
return loc + scale * log(U / (1.0 - U));
}
/* 拒绝 U == 0.0 并重新调用以获取下一个值 */
return random_logistic(bitgen_state, loc, scale);
}
// 生成参数为 mean 和 sigma 的对数正态分布随机变量的函数
double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) {
// 生成正态分布随机变量,进行指数变换得到对数正态分布随机变量
return exp(random_normal(bitgen_state, mean, sigma));
}
// 生成参数为 mode 的瑞利分布随机变量的函数
double random_rayleigh(bitgen_t *bitgen_state, double mode) {
// 生成标准指数分布随机变量,进行线性变换得到瑞利分布随机变量
return mode * sqrt(2.0 * random_standard_exponential(bitgen_state));
}
// 生成自由度为 df 的标准 t 分布随机变量的函数
double random_standard_t(bitgen_t *bitgen_state, double df) {
double num, denom;
num = random_standard_normal(bitgen_state);
denom = random_standard_gamma(bitgen_state, df / 2);
// 对标准正态分布和标准卡方分布随机变量进行线性变换得到标准 t 分布随机变量
return sqrt(df / 2) * num / sqrt(denom);
}
// 用于生成泊松随机变量的转换拒绝法函数
static RAND_INT_TYPE random_poisson_mult(bitgen_t *bitgen_state, double lam) {
RAND_INT_TYPE X;
double prod, U, enlam;
enlam = exp(-lam);
X = 0;
prod = 1.0;
while (1) {
U = next_double(bitgen_state);
prod *= U;
if (prod > enlam) {
X += 1;
} else {
return X;
}
}
}
/*
* 用于生成泊松随机变量的变换拒绝法函数
* W. Hoermann
* Insurance: Mathematics and Economics 12, 39-45 (1993)
*/
#define LS2PI 0.91893853320467267
#define TWELFTH 0.083333333333333333333333
static RAND_INT_TYPE random_poisson_ptrs(bitgen_t *bitgen_state, double lam) {
RAND_INT_TYPE k;
double U, V, slam, loglam, a, b, invalpha, vr, us;
slam = sqrt(lam); // 计算 lam 的平方根
loglam = log(lam); // 计算 lam 的自然对数
b = 0.931 + 2.53 * slam; // 根据 slam 计算 b 的值
a = -0.059 + 0.02483 * b; // 根据 b 计算 a 的值
invalpha = 1.1239 + 1.1328 / (b - 3.4); // 根据 b 计算 invalpha 的值
vr = 0.9277 - 3.6224 / (b - 2); // 根据 b 计算 vr 的值
while (1) {
U = next_double(bitgen_state) - 0.5; // 生成 U,范围在 [-0.5, 0.5]
V = next_double(bitgen_state); // 生成 V,范围在 [0, 1)
us = 0.5 - fabs(U); // 计算 us,范围在 [0, 0.5]
k = (RAND_INT_TYPE)floor((2 * a / us + b) * U + lam + 0.43); // 根据 U、us、a、b、lam 计算 k
// 根据生成的 U、V、us、vr 进行条件判断
if ((us >= 0.07) && (V <= vr)) {
return k; // 返回 k
}
if ((k < 0) || ((us < 0.013) && (V > us))) {
continue; // 如果不满足条件则继续循环
}
/* log(V) == log(0.0) ok here */
/* if U==0.0 so that us==0.0, log is ok since always returns */
// 根据生成的 V、invalpha、a、us 进行条件判断
if ((log(V) + log(invalpha) - log(a / (us * us) + b)) <=
(-lam + k * loglam - random_loggam(k + 1))) {
return k; // 返回 k
}
}
}
RAND_INT_TYPE random_poisson(bitgen_t *bitgen_state, double lam) {
if (lam >= 10) {
return random_poisson_ptrs(bitgen_state, lam); // 如果 lam 大于等于 10,调用 random_poisson_ptrs 函数
} else if (lam == 0) {
return 0; // 如果 lam 等于 0,返回 0
} else {
return random_poisson_mult(bitgen_state, lam); // 否则调用 random_poisson_mult 函数
}
}
RAND_INT_TYPE random_negative_binomial(bitgen_t *bitgen_state, double n,
double p) {
double Y = random_gamma(bitgen_state, n, (1 - p) / p); // 调用 random_gamma 函数生成 Y
return random_poisson(bitgen_state, Y); // 调用 random_poisson 函数,传入 Y 作为参数
}
RAND_INT_TYPE random_binomial_btpe(bitgen_t *bitgen_state, RAND_INT_TYPE n,
double p, binomial_t *binomial) {
double r, q, fm, p1, xm, xl, xr, c, laml, lamr, p2, p3, p4;
double a, u, v, s, F, rho, t, A, nrq, x1, x2, f1, f2, z, z2, w, w2, x;
RAND_INT_TYPE m, y, k, i;
if (!(binomial->has_binomial) || (binomial->nsave != n) ||
(binomial->psave != p)) {
/* initialize */
binomial->nsave = n;
binomial->psave = p;
binomial->has_binomial = 1;
binomial->r = r = MIN(p, 1.0 - p);
binomial->q = q = 1.0 - r;
binomial->fm = fm = n * r + r;
binomial->m = m = (RAND_INT_TYPE)floor(binomial->fm);
binomial->p1 = p1 = floor(2.195 * sqrt(n * r * q) - 4.6 * q) + 0.5;
binomial->xm = xm = m + 0.5;
binomial->xl = xl = xm - p1;
binomial->xr = xr = xm + p1;
binomial->c = c = 0.134 + 20.5 / (15.3 + m);
a = (fm - xl) / (fm - xl * r);
binomial->laml = laml = a * (1.0 + a / 2.0);
a = (xr - fm) / (xr * q);
binomial->lamr = lamr = a * (1.0 + a / 2.0);
binomial->p2 = p2 = p1 * (1.0 + 2.0 * c);
binomial->p3 = p3 = p2 + c / laml;
binomial->p4 = p4 = p3 + c / lamr;
} else {
r = binomial->r;
q = binomial->q;
fm = binomial->fm;
m = binomial->m;
p1 = binomial->p1;
xm = binomial->xm;
xl = binomial->xl;
xr = binomial->xr;
c = binomial->c;
laml = binomial->laml;
lamr = binomial->lamr;
p2 = binomial->p2;
p3 = binomial->p3;
p4 = binomial->p4;
}
/* sigh ... */
Step10:
nrq = n * r * q; // 计算 n * r * q
u = next_double(bitgen_state) * p4; // 生成 u,范围在 [0, p4)
v = next_double(bitgen_state); // 生成 v,范围在 [0, 1)
if (u > p1) // 判断 u 是否大于 p1
# 转到步骤20的标签,即代码跳转到后续步骤的标记点
goto Step20;
# 计算 y 的值,使用 floor 函数对 xm - p1 * v + u 进行向下取整,并将结果转换为 RAND_INT_TYPE 类型
y = (RAND_INT_TYPE)floor(xm - p1 * v + u);
# 转到步骤60的标签,即代码跳转到后续步骤的标记点
goto Step60;
Step20:
// 如果随机数大于 p2,则跳转到 Step30
if (u > p2)
goto Step30;
// 计算随机数对应的变量 x
x = xl + (u - p1) / c;
// 更新 v,这里的操作是根据变量 m 和 x 计算 v 的新值
v = v * c + 1.0 - fabs(m - x + 0.5) / p1;
// 如果 v 大于 1.0,则跳转到 Step10
if (v > 1.0)
goto Step10;
// 计算 x 的整数部分作为 y,并跳转到 Step50
y = (RAND_INT_TYPE)floor(x);
goto Step50;
Step30:
// 如果随机数大于 p3,则跳转到 Step40
if (u > p3)
goto Step40;
// 根据公式计算 y 的值
y = (RAND_INT_TYPE)floor(xl + log(v) / laml);
/* 如果 v 等于 0.0,则拒绝,因为前面的转换是未定义的 */
if ((y < 0) || (v == 0.0))
goto Step10;
// 更新 v
v = v * (u - p2) * laml;
goto Step50;
Step40:
// 根据公式计算 y 的值
y = (RAND_INT_TYPE)floor(xr - log(v) / lamr);
/* 如果 v 等于 0.0,则拒绝,因为前面的转换是未定义的 */
if ((y > n) || (v == 0.0))
goto Step10;
// 更新 v
v = v * (u - p3) * lamr;
Step50:
// 计算 k 的绝对值
k = llabs(y - m);
// 如果 k 在指定的范围内,则跳转到 Step52
if ((k > 20) && (k < ((nrq) / 2.0 - 1)))
goto Step52;
// 计算 s,a 和 F
s = r / q;
a = s * (n + 1);
F = 1.0;
// 根据条件更新 F 的值
if (m < y) {
for (i = m + 1; i <= y; i++) {
F *= (a / i - s);
}
} else if (m > y) {
for (i = y + 1; i <= m; i++) {
F /= (a / i - s);
}
}
// 如果 v 大于 F,则跳转到 Step10
if (v > F)
goto Step10;
// 跳转到 Step60
goto Step60;
Step52:
// 计算 rho 和 t
rho =
(k / (nrq)) * ((k * (k / 3.0 + 0.625) + 0.16666666666666666) / nrq + 0.5);
t = -k * k / (2 * nrq);
/* log(0.0) 在这里是允许的 */
A = log(v);
// 根据条件判断是否跳转到 Step60 或 Step10
if (A < (t - rho))
goto Step60;
if (A > (t + rho))
goto Step10;
// 根据一系列公式计算和比较,判断是否跳转到 Step10
x1 = y + 1;
f1 = m + 1;
z = n + 1 - m;
w = n - y + 1;
x2 = x1 * x1;
f2 = f1 * f1;
z2 = z * z;
w2 = w * w;
if (A > (xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) +
(y - m) * log(w * r / (x1 * q)) +
(13680. - (462. - (132. - (99. - 140. / f2) / f2) / f2) / f2) / f1 /
166320. +
(13680. - (462. - (132. - (99. - 140. / z2) / z2) / z2) / z2) / z /
166320. +
(13680. - (462. - (132. - (99. - 140. / x2) / x2) / x2) / x2) / x1 /
166320. +
(13680. - (462. - (132. - (99. - 140. / w2) / w2) / w2) / w2) / w /
166320.)) {
goto Step10;
}
Step60:
// 如果 p 大于 0.5,则更新 y
if (p > 0.5) {
y = n - y;
}
// 返回最终的 y 值
return y;
}
RAND_INT_TYPE random_binomial_inversion(bitgen_t *bitgen_state, RAND_INT_TYPE n,
double p, binomial_t *binomial) {
double q, qn, np, px, U;
RAND_INT_TYPE X, bound;
// 如果 binomial 结构体中的参数与当前传入的不一致,则重新初始化
if (!(binomial->has_binomial) || (binomial->nsave != n) ||
(binomial->psave != p)) {
binomial->nsave = n;
binomial->psave = p;
binomial->has_binomial = 1;
binomial->q = q = 1.0 - p;
binomial->r = qn = exp(n * log(q));
binomial->c = np = n * p;
binomial->m = bound = (RAND_INT_TYPE)MIN(n, np + 10.0 * sqrt(np * q + 1));
} else {
// 否则,使用已存储的参数
q = binomial->q;
qn = binomial->r;
np = binomial->c;
bound = binomial->m;
}
X = 0;
px = qn;
// 使用指定算法生成服从二项分布的随机数 X
U = next_double(bitgen_state);
while (U > px) {
X++;
if (X > bound) {
X = 0;
px = qn;
U = next_double(bitgen_state);
} else {
U -= px;
px = ((n - X + 1) * p * px) / (X * q);
}
}
// 返回生成的随机数 X
return X;
}
// 计算二项分布随机变量的函数,返回计算结果
int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n,
binomial_t *binomial) {
double q;
// 如果 n 为 0 或者 p 为 0,则直接返回 0
if ((n == 0LL) || (p == 0.0f))
return 0;
// 如果 p <= 0.5,根据 p * n 的大小选择不同的方法计算
if (p <= 0.5) {
// 如果 p * n <= 30.0,使用反向变换法计算二项分布
if (p * n <= 30.0) {
return random_binomial_inversion(bitgen_state, n, p, binomial);
} else {
// 否则使用 BTPE 算法计算二项分布
return random_binomial_btpe(bitgen_state, n, p, binomial);
}
} else {
// 如果 p > 0.5,计算 q = 1 - p
q = 1.0 - p;
// 如果 q * n <= 30.0,使用反向变换法计算 n - 二项分布的值
if (q * n <= 30.0) {
return n - random_binomial_inversion(bitgen_state, n, q, binomial);
} else {
// 否则使用 BTPE 算法计算 n - 二项分布的值
return n - random_binomial_btpe(bitgen_state, n, q, binomial);
}
}
}
// 计算非中心卡方分布的随机变量,返回计算结果
double random_noncentral_chisquare(bitgen_t *bitgen_state, double df,
double nonc) {
// 如果 nonc 是 NaN,则返回 NaN
if (npy_isnan(nonc)) {
return NPY_NAN;
}
// 如果 nonc 为 0,则返回 df 自由度的卡方分布的随机变量
if (nonc == 0) {
return random_chisquare(bitgen_state, df);
}
// 如果 df > 1,则进行非中心卡方分布的计算
if (1 < df) {
const double Chi2 = random_chisquare(bitgen_state, df - 1);
const double n = random_standard_normal(bitgen_state) + sqrt(nonc);
return Chi2 + n * n;
} else {
// 如果 df <= 1,则使用泊松分布和卡方分布计算非中心卡方分布
const RAND_INT_TYPE i = random_poisson(bitgen_state, nonc / 2.0);
return random_chisquare(bitgen_state, df + 2 * i);
}
}
// 计算非中心 F 分布的随机变量,返回计算结果
double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden,
double nonc) {
// 计算非中心卡方分布随机变量乘以 dfden
double t = random_noncentral_chisquare(bitgen_state, dfnum, nonc) * dfden;
return t / (random_chisquare(bitgen_state, dfden) * dfnum);
}
// 计算瓦尔德分布的随机变量,返回计算结果
double random_wald(bitgen_t *bitgen_state, double mean, double scale) {
double U, X, Y;
double mu_2l;
// 计算 mu / (2 * scale)
mu_2l = mean / (2 * scale);
// 生成标准正态分布的随机变量 Y
Y = random_standard_normal(bitgen_state);
// 计算 X 和 U
Y = mean * Y * Y;
X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y));
U = next_double(bitgen_state);
// 根据 U 的值选择返回 X 或者 mean * mean / X
if (U <= mean / (mean + X)) {
return X;
} else {
return mean * mean / X;
}
}
// 计算冯·米塞斯分布的随机变量,返回计算结果
double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) {
double s;
double U, V, W, Y, Z;
double result, mod;
int neg;
// 如果 kappa 是 NaN,则返回 NaN
if (npy_isnan(kappa)) {
return NPY_NAN;
}
// 如果 kappa < 1e-8,使用均匀分布生成随机变量
if (kappa < 1e-8) {
return M_PI * (2 * next_double(bitgen_state) - 1);
} else {
// 对于其他情况,根据 kappa 的大小选择不同的计算方法
if (kappa < 1e-5) {
// 当 1e-5 <= kappa <= 1e-6 时,使用二阶泰勒展开计算
s = (1. / kappa + kappa);
} else {
if (kappa <= 1e6) {
// 当 1e-5 < kappa <= 1e6 时,使用特定的数学公式计算
double r = 1 + sqrt(1 + 4 * kappa * kappa);
double rho = (r - sqrt(2 * r)) / (2 * kappa);
s = (1 + rho * rho) / (2 * rho);
} else {
// 当 kappa > 1e6 时,使用包裹的正态分布计算
result = mu + sqrt(1. / kappa) * random_standard_normal(bitgen_state);
// 确保结果在 -π 到 π 之间
if (result < -M_PI) {
result += 2*M_PI;
}
if (result > M_PI) {
result -= 2*M_PI;
}
return result;
}
}
// 返回计算结果
return result;
}
}
}
这是一个 do-while 循环的结束标志,表示前面的循环体结束。
while (1) {
开始一个无限循环,直到满足条件跳出循环。
U = next_double(bitgen_state);
Z = cos(M_PI * U);
W = (1 + s * Z) / (s + Z);
Y = kappa * (s - W);
V = next_double(bitgen_state);
生成随机数并计算出变量 Z, W, Y 和 V,这些变量将用于接下来的条件判断。
/*
* V==0.0 is ok here since Y >= 0 always leads
* to accept, while Y < 0 always rejects
*/
if ((Y * (2 - Y) - V >= 0) || (log(Y / V) + 1 - Y >= 0)) {
break;
}
条件判断语句,根据 Y 和 V 的值来决定是否跳出循环。注释解释了为什么 V 可以等于 0 的情况。
U = next_double(bitgen_state);
生成下一个随机数 U。
result = acos(W);
if (U < 0.5) {
result = -result;
}
result += mu;
根据 U 的值对 result 进行调整,先求 acos(W),然后根据 U 的大小确定是否取反,最后加上 mu。
neg = (result < 0);
mod = fabs(result);
mod = (fmod(mod + M_PI, 2 * M_PI) - M_PI);
if (neg) {
mod *= -1;
}
处理 result 的符号和将其调整到 [-π, π] 范围内。
return mod;
}
返回处理后的 mod 值,作为函数的输出结果。
}
/*
* 生成符合对数级数分布的随机数
* bitgen_state: 随机数生成器状态
* p: 成功概率
*/
int64_t random_logseries(bitgen_t *bitgen_state, double p) {
double q, r, U, V;
int64_t result;
r = npy_log1p(-p);
while (1) {
V = next_double(bitgen_state); // 生成一个均匀分布的随机数 V
if (V >= p) { // 如果 V 大于等于成功概率 p,返回 1
return 1;
}
U = next_double(bitgen_state); // 生成另一个均匀分布的随机数 U
q = -expm1(r * U); // 计算 q 值
if (V <= q * q) { // 如果 V 小于等于 q 的平方,执行以下操作
result = (int64_t)floor(1 + log(V) / log(q)); // 计算结果并返回
if ((result < 1) || (V == 0.0)) { // 如果结果小于 1 或者 V 等于 0,继续循环
continue;
} else {
return result; // 返回结果
}
}
if (V >= q) { // 如果 V 大于等于 q,返回 1
return 1;
}
return 2; // 默认情况下返回 2
}
}
/*
* 生成符合几何分布的随机数
* bitgen_state: 随机数生成器状态
* p: 成功概率
*/
RAND_INT_TYPE random_geometric_search(bitgen_t *bitgen_state, double p) {
double U;
RAND_INT_TYPE X;
double sum, prod, q;
X = 1;
sum = prod = p;
q = 1.0 - p;
U = next_double(bitgen_state); // 生成一个均匀分布的随机数 U
while (U > sum) { // 循环直到 U 大于 sum
prod *= q; // 更新 prod
sum += prod; // 更新 sum
X++; // X 自增
}
return X; // 返回生成的随机数 X
}
/*
* 使用反转方法生成符合几何分布的随机数
* bitgen_state: 随机数生成器状态
* p: 成功概率
*/
int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) {
double z = ceil(-random_standard_exponential(bitgen_state) / npy_log1p(-p));
/*
* 常量 9.223372036854776e+18 是大于 INT64_MAX 的最小双精度浮点数。
* 如果 z 大于等于此常量,返回 INT64_MAX。
*/
if (z >= 9.223372036854776e+18) {
return INT64_MAX;
}
return (int64_t) z; // 返回生成的随机数 z
}
/*
* 生成符合几何分布的随机数
* bitgen_state: 随机数生成器状态
* p: 成功概率
*/
int64_t random_geometric(bitgen_t *bitgen_state, double p) {
if (p >= 0.333333333333333333333333) {
return random_geometric_search(bitgen_state, p); // 使用搜索方法生成
} else {
return random_geometric_inversion(bitgen_state, p); // 使用反转方法生成
}
}
/*
* 生成符合 Zipf 分布的随机数
* bitgen_state: 随机数生成器状态
* a: 分布参数
*/
RAND_INT_TYPE random_zipf(bitgen_t *bitgen_state, double a) {
double am1, b;
am1 = a - 1.0;
b = pow(2.0, am1);
while (1) {
double T, U, V, X;
U = 1.0 - next_double(bitgen_state); // 生成一个均匀分布的随机数 U
V = next_double(bitgen_state); // 生成另一个均匀分布的随机数 V
X = floor(pow(U, -1.0 / am1)); // 计算 X 值
/*
* 如果 X 大于 RAND_INT_MAX 或者小于 1.0,则继续循环。
* 因为这是一个简单的拒绝采样算法,所以可以拒绝这个值。
* 此函数模拟了一个被截断到 sys.maxint 的 Zipf 分布。
*/
if (X > (double)RAND_INT_MAX || X < 1.0) {
continue;
}
T = pow(1.0 + 1.0 / X, am1); // 计算 T 值
if (V * X * (T - 1.0) / (b - 1.0) <= T / b) { // 如果条件满足,返回 X
return (RAND_INT_TYPE)X;
}
}
}
/*
* 生成符合三角分布的随机数
* bitgen_state: 随机数生成器状态
* left: 左边界
* mode: 众数
* right: 右边界
*/
double random_triangular(bitgen_t *bitgen_state, double left, double mode,
double right) {
double base, leftbase, ratio, leftprod, rightprod;
double U;
base = right - left; // 计算基础值
leftbase = mode - left; // 计算左基础值
ratio = leftbase / base; // 计算比率
leftprod = leftbase * base; // 计算左乘积
rightprod = (right - mode) * base; // 计算右乘积
U = next_double(bitgen_state); // 生成一个均匀分布的随机数 U
if (U <= ratio) { // 如果 U 小于等于比率,返回左边界加上开方后的值
return left + sqrt(U * leftprod);
} else { // 否则返回右边界减去开方后的值
return right - sqrt((1.0 - U) * rightprod);
}
}
/* 生成一个指定范围内的随机数
* 使用掩码来确保生成的随机数不超出指定的最大值
* 如果最大值为0,则直接返回0
*/
uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) {
uint64_t mask, value;
if (max == 0) {
return 0;
}
mask = max;
/* 找到最小的大于等于 max 的位掩码 */
mask |= mask >> 1;
mask |= mask >> 2;
mask |= mask >> 4;
mask |= mask >> 8;
mask |= mask >> 16;
mask |= mask >> 32;
/* 在 [0..mask] 范围内搜索一个随机值使其 <= max */
if (max <= 0xffffffffUL) {
while ((value = (next_uint32(bitgen_state) & mask)) > max)
;
} else {
while ((value = (next_uint64(bitgen_state) & mask)) > max)
;
}
return value;
}
/* 生成一个用于生成随机数的掩码
* 掩码用于确保生成的随机数在指定的范围内
*/
static inline uint64_t gen_mask(uint64_t max) {
uint64_t mask = max;
mask |= mask >> 1;
mask |= mask >> 2;
mask |= mask >> 4;
mask |= mask >> 8;
mask |= mask >> 16;
mask |= mask >> 32;
return mask;
}
/* 使用 32 位缓冲区生成 16 位随机数 */
static inline uint16_t buffered_uint16(bitgen_t *bitgen_state, int *bcnt,
uint32_t *buf) {
if (!(bcnt[0])) {
buf[0] = next_uint32(bitgen_state);
bcnt[0] = 1;
} else {
buf[0] >>= 16;
bcnt[0] -= 1;
}
return (uint16_t)buf[0];
}
/* 使用 32 位缓冲区生成 8 位随机数 */
static inline uint8_t buffered_uint8(bitgen_t *bitgen_state, int *bcnt,
uint32_t *buf) {
if (!(bcnt[0])) {
buf[0] = next_uint32(bitgen_state);
bcnt[0] = 3;
} else {
buf[0] >>= 8;
bcnt[0] -= 1;
}
return (uint8_t)buf[0];
}
/* 静态的 `masked rejection` 函数,由 random_bounded_uint64(...) 调用 */
static inline uint64_t bounded_masked_uint64(bitgen_t *bitgen_state,
uint64_t rng, uint64_t mask) {
uint64_t val;
while ((val = (next_uint64(bitgen_state) & mask)) > rng)
;
return val;
}
/* 静态的 `masked rejection` 函数,由 random_buffered_bounded_uint32(...) 调用 */
static inline uint32_t
buffered_bounded_masked_uint32(bitgen_t *bitgen_state, uint32_t rng,
uint32_t mask, int *bcnt, uint32_t *buf) {
/*
* 缓冲区和缓冲区计数在此处未使用,但包含在内是为了与类似的 uint8 和 uint16 函数进行模板化
*/
uint32_t val;
while ((val = (next_uint32(bitgen_state) & mask)) > rng)
;
return val;
}
/* 静态的 `masked rejection` 函数,由 random_buffered_bounded_uint16(...) 调用 */
static inline uint16_t
buffered_bounded_masked_uint16(bitgen_t *bitgen_state, uint16_t rng,
uint16_t mask, int *bcnt, uint32_t *buf) {
uint16_t val;
while ((val = (buffered_uint16(bitgen_state, bcnt, buf) & mask)) > rng)
;
return val;
}
/* 静态的 `masked rejection` 函数,由 random_buffered_bounded_uint8(...) 调用 */
/*
* 从缓冲区获取一个受限制和掩码的无符号8位整数,并进行Lemire拒绝采样以确保在指定范围内。
* 这个函数是静态的,用于内部调用。
*/
static inline uint8_t buffered_bounded_masked_uint8(bitgen_t *bitgen_state,
uint8_t rng,
uint8_t mask,
int *bcnt,
uint32_t *buf) {
uint8_t val;
// 使用 buffered_uint8 函数获取一个无符号8位整数,并与掩码进行按位与操作
while ((val = (buffered_uint8(bitgen_state, bcnt, buf) & mask)) > rng)
; // 循环直到获取的值在指定的范围内
return val; // 返回满足条件的值
}
/*
* 从缓冲区获取一个受限制的布尔值,并进行Lemire拒绝采样以确保在指定范围内。
* 这个函数是静态的,用于内部调用。
*/
static inline npy_bool buffered_bounded_bool(bitgen_t *bitgen_state,
npy_bool off, npy_bool rng,
npy_bool mask, int *bcnt,
uint32_t *buf) {
if (rng == 0)
return off; // 如果范围为0,则直接返回 off
if (!(bcnt[0])) {
buf[0] = next_uint32(bitgen_state);
bcnt[0] = 31;
} else {
buf[0] >>= 1;
bcnt[0] -= 1;
}
// 返回缓冲区中的布尔值,确保在指定的范围内
return (buf[0] & 0x00000001UL) != 0;
}
/*
* 由 random_bounded_uint64(...) 调用的静态 `Lemire拒绝` 函数。
* 使用Lemire算法,确保生成的随机数在指定范围内。
*/
static inline uint64_t bounded_lemire_uint64(bitgen_t *bitgen_state,
uint64_t rng) {
/*
* 使用Lemire的算法 - https://arxiv.org/abs/1805.10941
*
* 注意: `rng` 不应为 0xFFFFFFFFFFFFFFFF。当发生这种情况时,`rng_excl` 变为零。
*/
const uint64_t rng_excl = rng + 1;
// 断言,确保 `rng` 不等于 0xFFFFFFFFFFFFFFFFULL
assert(rng != 0xFFFFFFFFFFFFFFFFULL);
#if __SIZEOF_INT128__
/* 128位无符号整数可用 (例如GCC/clang)。`m` 是缩放后的 __uint128_t 整数。 */
__uint128_t m;
uint64_t leftover;
// 生成一个缩放后的随机数
m = ((__uint128_t)next_uint64(bitgen_state)) * rng_excl;
// 使用拒绝采样消除任何偏差
leftover = m & 0xFFFFFFFFFFFFFFFFULL;
// 如果余数小于 `rng_excl`,继续循环直到符合条件
if (leftover < rng_excl) {
const uint64_t threshold = (UINT64_MAX - rng) % rng_excl;
while (leftover < threshold) {
m = ((__uint128_t)next_uint64(bitgen_state)) * rng_excl;
leftover = m & 0xFFFFFFFFFFFFFFFFULL;
}
}
// 返回缩放后的整数的高64位
return (m >> 64);
#else
/* 128位无符号整数不可用 (例如MSVS)。`m1` 是缩放后的整数的高64位。 */
uint64_t m1;
uint64_t x;
uint64_t leftover;
x = next_uint64(bitgen_state);
// 使用拒绝采样消除任何偏差
leftover = x * rng_excl;
// 如果余数小于 `rng_excl`,继续循环直到符合条件
if (leftover < rng_excl) {
const uint64_t threshold = (UINT64_MAX - rng) % rng_excl;
while (leftover < threshold) {
x = next_uint64(bitgen_state);
leftover = x * rng_excl;
}
}
#if defined(_MSC_VER) && defined(_WIN64)
// _WIN64 架构。使用 __umulh 内置函数计算 `m1`。
m1 = __umulh(x, rng_excl);
#else
// 32位架构。模拟 __umulh 函数计算 `m1`。
{
uint64_t x0, x1, rng_excl0, rng_excl1;
uint64_t w0, w1, w2, t;
x0 = x & 0xFFFFFFFFULL;
x1 = x >> 32;
# 将 rng_excl 的低 32 位保存到 rng_excl0 中
rng_excl0 = rng_excl & 0xFFFFFFFFULL;
# 将 rng_excl 的高 32 位保存到 rng_excl1 中
rng_excl1 = rng_excl >> 32;
# 计算 x0 乘以 rng_excl0 的结果,存入 w0 中
w0 = x0 * rng_excl0;
# 计算 x1 乘以 rng_excl0 的结果,加上 w0 的高 32 位部分,存入 t 中
t = x1 * rng_excl0 + (w0 >> 32);
# 提取 t 的低 32 位保存到 w1 中
w1 = t & 0xFFFFFFFFULL;
# 提取 t 的高 32 位保存到 w2 中
w2 = t >> 32;
# 计算 x0 乘以 rng_excl1 的结果,加上 w1 的高 32 位部分,存入 w1 中
w1 += x0 * rng_excl1;
# 计算 x1 乘以 rng_excl1 的结果,加上 w2 和 w1 的高 32 位部分,存入 m1 中
m1 = x1 * rng_excl1 + w2 + (w1 >> 32);
}
#endif
return m1;
#endif
}
/* Static `Lemire rejection` function called by
* random_buffered_bounded_uint32(...) */
static inline uint32_t buffered_bounded_lemire_uint32(
bitgen_t *bitgen_state, uint32_t rng, int *bcnt, uint32_t *buf) {
/*
* 使用Lemire算法 - https://arxiv.org/abs/1805.10941
*
* 缓冲区和缓冲区计数在这里未使用,但包含在此函数中以便与相似的uint8和uint16函数模板化
*
* 注意:`rng`不应为0xFFFFFFFF。当这种情况发生时,`rng_excl`变为零。
*/
const uint32_t rng_excl = rng + 1;
uint64_t m;
uint32_t leftover;
assert(rng != 0xFFFFFFFFUL);
/* 生成一个经过缩放的随机数。*/
m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl;
/* 拒绝采样以消除任何偏差 */
leftover = m & 0xFFFFFFFFUL;
if (leftover < rng_excl) {
/* `rng_excl`是`threshold`的简单上限。*/
const uint32_t threshold = (UINT32_MAX - rng) % rng_excl;
while (leftover < threshold) {
m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl;
leftover = m & 0xFFFFFFFFUL;
}
}
return (m >> 32);
}
/* Static `Lemire rejection` function called by
* random_buffered_bounded_uint16(...) */
static inline uint16_t buffered_bounded_lemire_uint16(
bitgen_t *bitgen_state, uint16_t rng, int *bcnt, uint32_t *buf) {
/*
* 使用Lemire算法 - https://arxiv.org/abs/1805.10941
*
* 注意:`rng`不应为0xFFFF。当这种情况发生时,`rng_excl`变为零。
*/
const uint16_t rng_excl = rng + 1;
uint32_t m;
uint16_t leftover;
assert(rng != 0xFFFFU);
/* 生成一个经过缩放的随机数。*/
m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl;
/* 拒绝采样以消除任何偏差 */
leftover = m & 0xFFFFUL;
if (leftover < rng_excl) {
/* `rng_excl`是`threshold`的简单上限。*/
const uint16_t threshold = (UINT16_MAX - rng) % rng_excl;
while (leftover < threshold) {
m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl;
leftover = m & 0xFFFFUL;
}
}
return (m >> 16);
}
/* Static `Lemire rejection` function called by
* random_buffered_bounded_uint8(...) */
static inline uint8_t buffered_bounded_lemire_uint8(bitgen_t *bitgen_state,
uint8_t rng, int *bcnt,
uint32_t *buf) {
/*
* 使用Lemire算法 - https://arxiv.org/abs/1805.10941
*
* 注意:`rng`不应为0xFF。当这种情况发生时,`rng_excl`变为零。
*/
const uint8_t rng_excl = rng + 1;
uint16_t m;
uint8_t leftover;
assert(rng != 0xFFU);
/* 生成一个经过缩放的随机数。*/
m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl;
/* 拒绝采样以消除任何偏差 */
leftover = m & 0xFFUL;
if (leftover < rng_excl) {
/* `rng_excl`是`threshold`的简单上限。*/
const uint8_t threshold = (UINT8_MAX - rng) % rng_excl;
m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl;
leftover = m & 0xFFUL;
}
}
return (m >> 8);
}
/* `rng_excl` 是 `threshold` 的简单上限。*/
const uint8_t threshold = (UINT8_MAX - rng) % rng_excl;
/* 当 `leftover` 小于 `threshold` 时执行循环。*/
while (leftover < threshold) {
/* 使用 `bitgen_state`、`bcnt` 和 `buf` 生成一个缓冲区中的无符号 8 位整数,
将其转换为无符号 16 位整数乘以 `rng_excl`。 */
m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl;
/* 更新 `leftover` 为 `m` 和 0xFF 之间的位与运算结果。 */
leftover = m & 0xFFUL;
}
/* 返回 `m` 右移 8 位后的结果。 */
return (m >> 8);
/*
* 返回一个在 off 和 off + rng 之间(包括边界)的随机 npy_uint64 数字。
* 如果 rng 足够大,数字将会循环。
*/
uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off,
uint64_t rng, uint64_t mask, bool use_masked) {
if (rng == 0) {
// 如果范围为0,直接返回 off
return off;
} else if (rng <= 0xFFFFFFFFUL) {
/* 如果范围在32位内,则调用32位生成器。 */
if (rng == 0xFFFFFFFFUL) {
/*
* 32位 Lemire 方法不支持 rng=0xFFFFFFFF,因此直接调用 next_uint32。
* 这也适用于 use_masked 为 True 的情况,因此这里处理两种情况。
*/
return off + (uint64_t) next_uint32(bitgen_state);
}
if (use_masked) {
// 使用掩码的缓冲有界32位无符号整数生成器
return off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, NULL,
NULL);
} else {
// 使用 Lemire 方法的缓冲有界32位无符号整数生成器
return off +
buffered_bounded_lemire_uint32(bitgen_state, rng, NULL, NULL);
}
} else if (rng == 0xFFFFFFFFFFFFFFFFULL) {
/* Lemire64 不支持包含 rng = 0xFFFFFFFFFFFFFFFF 的情况。 */
return off + next_uint64(bitgen_state);
} else {
if (use_masked) {
// 使用掩码的有界64位无符号整数生成器
return off + bounded_masked_uint64(bitgen_state, rng, mask);
} else {
// 使用 Lemire 方法的有界64位无符号整数生成器
return off + bounded_lemire_uint64(bitgen_state, rng);
}
}
}
/*
* 返回一个在 off 和 off + rng 之间(包括边界)的随机 npy_uint32 数字。
* 如果 rng 足够大,数字将会循环。
*/
uint32_t random_buffered_bounded_uint32(bitgen_t *bitgen_state, uint32_t off,
uint32_t rng, uint32_t mask,
bool use_masked, int *bcnt,
uint32_t *buf) {
/*
* 未使用的 bcnt 和 buf 仅用于允许与其他 uint 生成器进行模板化。
*/
if (rng == 0) {
// 如果范围为0,直接返回 off
return off;
} else if (rng == 0xFFFFFFFFUL) {
/* Lemire32 不支持包含 rng = 0xFFFFFFFF 的情况。 */
return off + next_uint32(bitgen_state);
} else {
if (use_masked) {
// 使用掩码的缓冲有界32位无符号整数生成器
return off +
buffered_bounded_masked_uint32(bitgen_state, rng, mask, bcnt, buf);
} else {
// 使用 Lemire 方法的缓冲有界32位无符号整数生成器
return off + buffered_bounded_lemire_uint32(bitgen_state, rng, bcnt, buf);
}
}
}
/*
* 返回一个在 off 和 off + rng 之间(包括边界)的随机 npy_uint16 数字。
* 如果 rng 足够大,数字将会循环。
*/
uint16_t random_buffered_bounded_uint16(bitgen_t *bitgen_state, uint16_t off,
uint16_t rng, uint16_t mask,
bool use_masked, int *bcnt,
uint32_t *buf) {
if (rng == 0) {
// 如果范围为0,直接返回 off
return off;
} else if (rng == 0xFFFFUL) {
/* Lemire16 不支持包含 rng = 0xFFFF 的情况。 */
return off + buffered_uint16(bitgen_state, bcnt, buf);
} else {
if (use_masked) {
// 使用掩码的缓冲有界16位无符号整数生成器
return off +
buffered_bounded_masked_uint16(bitgen_state, rng, mask, bcnt, buf);
} else {
# 如果不满足上述条件,执行以下代码块
# 返回调用函数 off + buffered_bounded_lemire_uint16 的结果
return off + buffered_bounded_lemire_uint16(bitgen_state, rng, bcnt, buf);
}
/*
* 返回一个介于 off 和 off + rng 之间(包括边界)的随机 npy_uint8 数字。
* 如果 rng 很大,则数字会循环。
*/
uint8_t random_buffered_bounded_uint8(bitgen_t *bitgen_state, uint8_t off,
uint8_t rng, uint8_t mask,
bool use_masked, int *bcnt,
uint32_t *buf) {
if (rng == 0) {
// 如果 rng 为 0,则直接返回 off
return off;
} else if (rng == 0xFFUL) {
/* Lemire8 不支持 inclusive rng = 0xFF。 */
// 如果 rng 是 0xFF,调用 buffered_uint8 获取随机数
return off + buffered_uint8(bitgen_state, bcnt, buf);
} else {
if (use_masked) {
// 如果 use_masked 为 true,使用 masked 方法获取随机数
return off +
buffered_bounded_masked_uint8(bitgen_state, rng, mask, bcnt, buf);
} else {
// 否则使用 Lemire 方法获取随机数
return off + buffered_bounded_lemire_uint8(bitgen_state, rng, bcnt, buf);
}
}
}
/*
* 返回一个随机的 npy_bool 值,介于 off 和 off + rng 之间(包括边界)。
*/
npy_bool random_buffered_bounded_bool(bitgen_t *bitgen_state, npy_bool off,
npy_bool rng, npy_bool mask,
bool use_masked, int *bcnt,
uint32_t *buf) {
// 调用 buffered_bounded_bool 函数返回随机的 npy_bool 值
return buffered_bounded_bool(bitgen_state, off, rng, mask, bcnt, buf);
}
/*
* 用 cnt 个随机 npy_uint64 数字填充数组 out,这些数字介于 off 和 off + rng 之间(包括边界)。
* 如果 rng 很大,则数字会循环。
*/
void random_bounded_uint64_fill(bitgen_t *bitgen_state, uint64_t off,
uint64_t rng, npy_intp cnt, bool use_masked,
uint64_t *out) {
npy_intp i;
if (rng == 0) {
// 如果 rng 为 0,将数组 out 填充为 off
for (i = 0; i < cnt; i++) {
out[i] = off;
}
} else if (rng <= 0xFFFFFFFFUL) {
/* 如果范围在 32 位内,则调用 32 位生成器。 */
/*
* 32 位 Lemire 方法不处理 rng=0xFFFFFFFF 的情况,因此我们直接调用 next_uint32。
* 当 use_masked 为 true 时,这也适用,因此我们在此处理两种情况。
*/
if (rng == 0xFFFFFFFFUL) {
// 如果 rng 是 0xFFFFFFFF,使用 next_uint32 填充数组 out
for (i = 0; i < cnt; i++) {
out[i] = off + (uint64_t) next_uint32(bitgen_state);
}
} else {
uint32_t buf = 0;
int bcnt = 0;
if (use_masked) {
/* 最小的位掩码 >= max */
uint64_t mask = gen_mask(rng);
// 使用 masked 方法填充数组 out
for (i = 0; i < cnt; i++) {
out[i] = off + buffered_bounded_masked_uint32(bitgen_state, rng, mask,
&bcnt, &buf);
}
} else {
// 使用 Lemire 方法填充数组 out
for (i = 0; i < cnt; i++) {
out[i] = off +
buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf);
}
}
}
} else if (rng == 0xFFFFFFFFFFFFFFFFULL) {
/* Lemire64 不支持 rng = 0xFFFFFFFFFFFFFFFF。 */
// 如果 rng 是 0xFFFFFFFFFFFFFFFF,使用 next_uint64 填充数组 out
for (i = 0; i < cnt; i++) {
out[i] = off + next_uint64(bitgen_state);
}
} else {
if (use_masked) {
/* 最小的位掩码 >= max */
uint64_t mask = gen_mask(rng);
// 使用 masked 方法填充数组 out
for (i = 0; i < cnt; i++) {
out[i] = off + bounded_masked_uint64(bitgen_state, rng, mask);
}
} else {
// 使用 Lemire 方法填充数组 out
for (i = 0; i < cnt; i++) {
out[i] = off + buffered_bounded_lemire_uint64(bitgen_state, rng, &bcnt, &buf);
}
}
}
}
} else {
# 如果条件不满足,则执行以下代码块
for (i = 0; i < cnt; i++) {
# 循环,从 i = 0 开始,直到 i < cnt 结束
out[i] = off + bounded_lemire_uint64(bitgen_state, rng);
# 将 out 数组的第 i 个元素赋值为 off 加上 bounded_lemire_uint64 函数返回的随机数
}
}
}
/*
* Fills an array with cnt random npy_uint32 between off and off + rng
* inclusive. The numbers wrap if rng is sufficiently large.
*/
void random_bounded_uint32_fill(bitgen_t *bitgen_state, uint32_t off,
uint32_t rng, npy_intp cnt, bool use_masked,
uint32_t *out) {
npy_intp i;
uint32_t buf = 0;
int bcnt = 0;
if (rng == 0) {
// 如果范围为0,填充数组所有元素为 off
for (i = 0; i < cnt; i++) {
out[i] = off;
}
} else if (rng == 0xFFFFFFFFUL) {
/* Lemire32 不支持 rng = 0xFFFFFFFF。*/
// 如果范围为 0xFFFFFFFF,使用 next_uint32 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off + next_uint32(bitgen_state);
}
} else {
if (use_masked) {
// 如果使用掩码方式
/* Smallest bit mask >= max */
uint32_t mask = (uint32_t)gen_mask(rng); // 生成掩码
// 使用 buffered_bounded_masked_uint32 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off + buffered_bounded_masked_uint32(bitgen_state, rng, mask,
&bcnt, &buf);
}
} else {
// 否则使用 buffered_bounded_lemire_uint32 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off +
buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf);
}
}
}
}
/*
* Fills an array with cnt random npy_uint16 between off and off + rng
* inclusive. The numbers wrap if rng is sufficiently large.
*/
void random_bounded_uint16_fill(bitgen_t *bitgen_state, uint16_t off,
uint16_t rng, npy_intp cnt, bool use_masked,
uint16_t *out) {
npy_intp i;
uint32_t buf = 0;
int bcnt = 0;
if (rng == 0) {
// 如果范围为0,填充数组所有元素为 off
for (i = 0; i < cnt; i++) {
out[i] = off;
}
} else if (rng == 0xFFFFUL) {
/* Lemire16 不支持 rng = 0xFFFF。*/
// 如果范围为 0xFFFF,使用 buffered_uint16 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off + buffered_uint16(bitgen_state, &bcnt, &buf);
}
} else {
if (use_masked) {
// 如果使用掩码方式
/* Smallest bit mask >= max */
uint16_t mask = (uint16_t)gen_mask(rng); // 生成掩码
// 使用 buffered_bounded_masked_uint16 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off + buffered_bounded_masked_uint16(bitgen_state, rng, mask,
&bcnt, &buf);
}
} else {
// 否则使用 buffered_bounded_lemire_uint16 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off +
buffered_bounded_lemire_uint16(bitgen_state, rng, &bcnt, &buf);
}
}
}
}
/*
* Fills an array with cnt random npy_uint8 between off and off + rng
* inclusive. The numbers wrap if rng is sufficiently large.
*/
void random_bounded_uint8_fill(bitgen_t *bitgen_state, uint8_t off, uint8_t rng,
npy_intp cnt, bool use_masked, uint8_t *out) {
npy_intp i;
uint32_t buf = 0;
int bcnt = 0;
if (rng == 0) {
// 如果范围为0,填充数组所有元素为 off
for (i = 0; i < cnt; i++) {
out[i] = off;
}
} else if (rng == 0xFFUL) {
/* Lemire8 不支持 rng = 0xFF。*/
// 如果范围为 0xFF,使用 buffered_uint8 填充数组元素
for (i = 0; i < cnt; i++) {
out[i] = off + buffered_uint8(bitgen_state, &bcnt, &buf);
}
} else {
if (use_masked) {
/* 如果 use_masked 为真,则使用掩码生成随机数 */
/* 生成大于等于最小值的掩码 */
uint8_t mask = (uint8_t)gen_mask(rng);
/* 对于给定的数量 cnt,循环生成掩码限定范围内的随机数 */
for (i = 0; i < cnt; i++) {
/* 调用函数生成带掩码的随机数,并将结果存入 out 数组 */
out[i] = off + buffered_bounded_masked_uint8(bitgen_state, rng, mask,
&bcnt, &buf);
}
} else {
/* 如果 use_masked 为假,则使用默认的 Lemire 方法生成随机数 */
/* 对于给定的数量 cnt,循环生成 Lemire 方法限定范围内的随机数 */
for (i = 0; i < cnt; i++) {
/* 调用函数生成 Lemire 方法的随机数,并将结果存入 out 数组 */
out[i] =
off + buffered_bounded_lemire_uint8(bitgen_state, rng, &bcnt, &buf);
}
}
/*
* Fills an array with cnt random npy_bool between off and off + rng
* inclusive.
*/
void random_bounded_bool_fill(bitgen_t *bitgen_state, npy_bool off,
npy_bool rng, npy_intp cnt, bool use_masked,
npy_bool *out) {
npy_bool mask = 0; // 初始化一个 npy_bool 类型的变量 mask,初始值为 0
npy_intp i; // 定义一个 npy_intp 类型的变量 i,用于循环计数
// 循环 cnt 次,填充数组 out,每次调用 buffered_bounded_bool 函数获取随机值
for (i = 0; i < cnt; i++) {
out[i] = buffered_bounded_bool(bitgen_state, off, rng, mask, &bcnt, &buf);
}
}
/*
* Generates multinomial random numbers based on given probabilities.
*/
void random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n,
RAND_INT_TYPE *mnix, double *pix, npy_intp d,
binomial_t *binomial) {
double remaining_p = 1.0; // 初始化 remaining_p 变量为 1.0,表示剩余的概率
npy_intp j; // 定义一个 npy_intp 类型的变量 j,用于循环计数
RAND_INT_TYPE dn = n; // 将参数 n 赋值给变量 dn
// 循环 d-1 次,生成多项式随机数,每次调用 random_binomial 函数
for (j = 0; j < (d - 1); j++) {
mnix[j] = random_binomial(bitgen_state, pix[j] / remaining_p, dn, binomial);
dn = dn - mnix[j]; // 更新剩余的随机数总数
if (dn <= 0) {
break; // 如果剩余随机数总数小于等于 0,跳出循环
}
remaining_p -= pix[j]; // 更新剩余的概率
}
// 如果仍有剩余随机数总数大于 0,将剩余随机数放入最后一个元素
if (dn > 0) {
mnix[d - 1] = dn;
}
}