1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
//! このライブラリは、疑似乱数を簡単に呼び出すことができるライブラリです。
//!
//! 例えば、```use rand_simple::Uniform;```と宣言するだけで、一様分布乱数を使用できます。
//!
//! 偉大な先達[rand](https://crates.io/crates/rand)と比較して、
//! 簡素なモジュール宣言と豊富な確率変数による使いやすさを目指しています。
//! # 使用例
//! ```
//! use rand_simple::Uniform;
//! let uniform = Uniform::new(1192u32);
//! let next = uniform.sample(); // 閉区間[0, 1]の一様乱数
//! println!("乱数: {}", next); // 0.8698977918526851f64
//! ```
//mod macros; // マクロモジュール
mod distributions; // 確率変数の詳細
#[cfg(test)] mod test_distributions; // テストモジュール
use std::cell::Cell; // 書き換え可能なメンバー変数
use std::time::{SystemTime, UNIX_EPOCH}; // 時刻の取得
// 共通処理
// 状態変数(x, y, z, w)を設定する
pub(crate) fn set_state(_seed: u32) -> (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>) {
let x: u32 = 123456789;
let y: u32 = (_seed as u64 >> 32) as u32 & 0xFFFFFFFF;
let z: u32 = _seed & 0xFFFFFFFF;
let w: u32 = x ^ z;
(Cell::<u32>::new(x), Cell::<u32>::new(y), Cell::<u32>::new(z), Cell::<u32>::new(w))
}
// 共通処理
// 閉区間[0, 1]の一様乱数を計算して、状態変数を更新する
pub(crate) fn update_and_uniform(_xyzw: &(Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>)) -> f64 {
// 一様乱数を計算する
let t: u32 = _xyzw.0.get() ^ (_xyzw.0.get() << 11);
let x: u32 = _xyzw.1.get();
let y: u32 = _xyzw.2.get();
let z: u32 = _xyzw.3.get();
let mut w: u32 = _xyzw.3.get();
w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
// 状態変数を更新する
_xyzw.0.set(x);
_xyzw.1.set(y);
_xyzw.2.set(z);
_xyzw.3.set(w);
// 一様乱数を返す
(w as f64) / MAX_U32_AS_F64
}
// 一様乱数を計算するための分母
// 一々呼び出すよりは定数にしておいた方が計算時間が短いのではないか?
const MAX_U32_AS_F64: f64 = std::u32::MAX as f64;
// 共通処理
/// 現在時刻から乱数の種を計算する関数
pub fn create_seed() -> u32 {
// 4_294_967_295u32 / 24 * 60 * 60 * 1000ミリ秒/日 ≒ 49.7日周期
SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis() as u32
}
// 共通処理
/// 正規分布等2つの乱数の種が必要な確率変数に対して、現在時刻から乱数の種を計算する
pub fn create_seeds() -> (u32, u32) {
let duration = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards");
// 49.7日周期と4秒周期の組み合わせ
(duration.as_millis() as u32, duration.as_nanos() as u32)
}
// 連続型確率変数
/// 一様乱数を計算する構造体
/// # 使用例 1 (new関数)
/// ```
/// use rand_simple::Uniform;
/// let uniform = Uniform::new(1192u32);
/// let next = uniform.sample(); // 閉区間[0, 1]の一様乱数
/// println!("乱数: {}", next); // 0.8698977918526851f64
/// ```
/// # 使用例 2 (マクロ・引数有り)
/// ```
/// use rand_simple::create_uniform;
/// let uniform = create_uniform!(1192u32);
/// let next = uniform.sample(); // 閉区間[0, 1]の一様乱数
/// println!("乱数: {}", next); // 0.8698977918526851f64
/// ```
/// # 使用例 3 (マクロ・引数無し)
/// ```
/// use rand_simple::create_uniform;
/// let uniform = create_uniform!();
/// let next = uniform.sample(); // 閉区間[0, 1]の一様乱数
/// println!("乱数: {}", next); // 値不明
/// ```
pub struct Uniform {
xyzw: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>) // 状態変数
}
/// オーバーロードを付与するためのテストトレイト
///
/// 運用がうまくいくことを確認した後、本番トレイトに置き換えて削除する
pub trait TestUniformSample {
fn test_sample(uniform: &Uniform, _foo: &Self) -> f64;
}
/// 正規分布を計算する構造体
/// # 使用例 1 (new関数)
/// ```
/// use rand_simple::Normal;
/// let normal = Normal::new(1192u32, 765u32);
/// let next = normal.sample(); // 平均値 0, 標準偏差 1 の標準正規分布
/// println!("乱数: {}", next); // -1.2296205447119757
/// ```
/// # 使用例 2 (マクロ・引数有り)
/// ```
/// use rand_simple::create_normal;
/// let create_normal = create_normal!(1192u32, 765u32);
/// let next = create_normal.sample(); // 平均値 0, 標準偏差 1 の標準正規分布
/// println!("乱数: {}", next); // -1.2296205447119757
/// ```
/// # 使用例 3 (マクロ・引数無し)
/// ```
/// use rand_simple::create_normal;
/// let create_normal = create_normal!();
/// let next = create_normal.sample(); // 平均値 0, 標準偏差 1 の標準正規分布
/// println!("乱数: {}", next); // 値不明
/// ```
pub struct Normal {
xyzw_1: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>), // 状態変数
xyzw_2: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>), // 状態変数
even_flag: Cell<bool>, // 乱数計算が偶数回目かどうかのフラグ
even_result: Cell<f64>, // 偶数回目の計算結果
}
/// 半正規分布を計算する構造体
/// # 使用例 1 (new関数)
/// ```
/// use rand_simple::HalfNormal;
/// let half_normal = HalfNormal::new(1192u32, 765u32);
/// let next = half_normal.sample(); // 標準偏差 1 の標準半正規分布
/// println!("乱数: {}", next); // 2.5308912695634582
/// ```
/// # 使用例 2 (マクロ・引数有り)
/// ```
/// use rand_simple::create_half_normal;
/// let half_normal = create_half_normal!(1192u32, 765u32);
/// let next = half_normal.sample(); // 標準偏差 1 の標準半正規分布
/// println!("乱数: {}", next); // 2.5308912695634582
/// ```
/// # 使用例 3 (マクロ・引数無し)
/// ```
/// use rand_simple::create_half_normal;
/// let half_normal = create_half_normal!();
/// let next = half_normal.sample(); // 標準偏差 1 の標準半正規分布
/// println!("乱数: {}", next); // 値不明
/// ```
pub struct HalfNormal {
xyzw_1: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>), // 状態変数
xyzw_2: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>), // 状態変数
even_flag: Cell<bool>, // 乱数計算が偶数回目かどうかのフラグ
even_result: Cell<f64>, // 偶数回目の計算結果
}
// 対数正規分布を計算する構造体
//pub struct LogNormal {}
/// コーシー分布を計算する構造体
/// # 使用例 1 (new関数)
/// ```
/// use rand_simple::Cauchy;
/// let cauchy = Cauchy::new(1192u32, 765u32);
/// let next = cauchy.sample(); // 位置母数 μ = 0, 尺度母数 θ = 1の乱数
/// println!("乱数: {}", next); // 1.0046339315561652f64
/// ```
/// # 使用例 2 (マクロ・引数有り)
/// ```
/// use rand_simple::create_cauchy;
/// let cauchy = create_cauchy!(1192u32, 765u32);
/// let next = cauchy.sample(); // 位置母数 μ = 0, 尺度母数 θ = 1の乱数
/// println!("乱数: {}", next); // 1.0046339315561652f64
/// ```
/// # 使用例 3 (マクロ・引数無し)
/// ```
/// use rand_simple::create_cauchy;
/// let cauchy = create_cauchy!();
/// let next = cauchy.sample(); // 位置母数 μ = 0, 尺度母数 θ = 1の乱数
/// println!("乱数: {}", next); // 値不明
/// ```
pub struct Cauchy {
xyzw_1: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>), // 状態変数
xyzw_2: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>), // 状態変数
}
// 半コーシー分布を計算する構造体
// pub struct HalfCauchy
// レヴィ分布を計算する構造体
//pub struct Levy {}
// 指数分布を計算する構造体
//pub struct Exponential {}
// ラプラス分布を計算する構造体
//pub struct Laplace {}
// レイリー分布を計算する構造体
//pub struct Rayleigh {}
// ワイブル分布を計算する構造体
//pub struct Weibull {}
// ガンベル分布を計算する構造体
//pub struct Gunbel {}
// ガンマ分布を計算する構造体
//pub struct Gamma {}
// ベータ分布を計算する構造体
//pub struct Beta {}
// ディリクレ分布を計算する構造体
//pub struct Dirichlet {}
// べき関数分布を計算する構造体
//pub struct PowerFunction {}
// 指数べき分布を計算する構造体
//pub struct ExponentialPower {}
// アーラン分布を計算する構造体
//pub struct Erlang {}
// ガンマ二乗分布を計算する構造体
//pub struct ChiSquare {}
// ガンマ分布を計算する構造体
//pub struct Chi {}
// F分布を計算する構造体
//pub struct FDistribution {}
// t分布を計算する構造体
//pub struct TDistribution {}
// 逆ガウス分布を計算する構造体
//pub struct InverseGaussian {}
// 三角分布を計算する構造体
//pub struct Triangular {}
// パレート分布を計算する構造体
//pub struct Pareto {}
// ロジスティック分布を計算する構造体
//pub struct Logistic {}
// 双曲線正割分布を計算する構造体
//pub struct HeyperbolicSecant {}
// 余弦分布を計算する構造体
//pub struct RaisedCosine {}
// 逆正弦分布を計算する構造体
//pub struct Arcsine {}
// フォン・ミーゼス分布を計算する構造体
//pub struct VonMises {}
// 非心ガンマ分布を計算する構造体
//pub struct NonCentralGamma {}
// 非心ベータ分布を計算する構造体
//pub struct NonCentralBeta {}
// 非心ガンマ二乗分布を計算する構造体
//pub struct NonCentralChiSquare {}
// 非心ガンマ分布を計算する構造体
//pub struct NonCentralChi {}
// 非心F分布を計算する構造体
//pub struct NonCentralF {}
// 非心t分布を計算する構造体
//pub struct NonCentralT {}
// プランク分布を計算する構造体
//pub struct Plank {}
// 離散型確率変数
/// ベルヌーイ分布を計算する構造体
/// # 使用例 1 (new関数)
/// ```
/// use rand_simple::Bernoulli;
/// let bernoulli = Bernoulli::new(1192u32);
/// let next = bernoulli.sample(0.5f64); // 発生確率 0.5の事象が生じたか(1)、否か(0)
/// println!("乱数: {}", next); // 0u32
/// ```
/// # 使用例 2 (マクロ・引数有り)
/// ```
/// use rand_simple::create_bernoulli;
/// let bernoulli = create_bernoulli!(1192u32);
/// let next = bernoulli.sample(0.5f64); // 発生確率 0.5の事象が生じたか(1)、否か(0)
/// println!("乱数: {}", next); // 0u32
/// ```
/// # 使用例 3 (マクロ・引数無し)
/// ```
/// use rand_simple::create_bernoulli;
/// let bernoulli = create_bernoulli!();
/// let next = bernoulli.sample(0.5f64); // 発生確率 0.5の事象が生じたか(1)、否か(0)
/// println!("乱数: {}", next); // 値不明
/// ```
pub struct Bernoulli {
xyzw: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>) // 状態変数
}
// 二項分布
//pub struct Binomial {}
/// 幾何分布を計算する構造体
/// # 使用例 1 (new関数)
/// ```
/// use rand_simple::Geometric;
/// let geometric = Geometric::new(1192u32);
/// let next = geometric.sample(0.5f64); // 発生確率 0.5の事象が初めて生じた試行回数
/// println!("乱数: {}", next); // 4u32
/// ```
/// # 使用例 2 (マクロ・引数有り)
/// ```
/// use rand_simple::create_geometric;
/// let geometric = create_geometric!(1192u32);
/// let next = geometric.sample(0.5f64); // 発生確率 0.5の事象が初めて生じた試行回数
/// println!("乱数: {}", next); // 4u32
/// ```
/// # 使用例 3 (マクロ・引数無し)
/// ```
/// use rand_simple::create_geometric;
/// let geometric = create_geometric!();
/// let next = geometric.sample(0.5f64); // 発生確率 0.5の事象が初めて生じた試行回数
/// println!("乱数: {}", next); // 値不明
/// ```
pub struct Geometric {
xyzw: (Cell<u32>, Cell<u32>, Cell<u32>, Cell<u32>) // 状態変数
}
// ポアソン分布を計算する構造体
//pub struct Poisson {}
// 超幾何分布を計算する構造体
//pub struct HeyperGeometric {}
// 多項分布を計算する構造体
//pub struct Multinominal {}
// 負の二項分布を計算する構造体
//pub struct NegativeBinomial {}
// 負の超幾何分布を計算する構造体
//pub struct NegativeHeyperGeometric {}
// 対数級数分布を計算する構造体
//pub struct LogarithmicSeries {}
// ユール・シモン分布を計算する構造体
//pub struct YuleSimon {}
// ジップ・マンデルブロート分布を計算する構造体
//pub struct ZipfMandelbrot {}
// ゼータ分布を計算する構造体
//pub struct Zeta {}