rand-0.7.2/.github/ISSUE_TEMPLATE/compile-issue.md010064400017500001750000000007501352222772600175220ustar0000000000000000--- name: Compile issue about: Report / ask about a compilation issue title: '' labels: '' assignees: '' --- # Common issues **Problem**: `rand_hc::Hc128Rng: rand_core::SeedableRng` (or other RNG) **Quick solution**: `cargo update` **Details**: This happens when multiple versions of the `rand_core` crate are in use. Check your `Cargo.lock` file for all versions of `rand_core`. Note that some versions (0.2.2 and 0.3.1) are compatibility shims and are not a problem by themselves. rand-0.7.2/.github/ISSUE_TEMPLATE/feature_request.md010064400017500001750000000004221352222772600201430ustar0000000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- ## Background **What is your motivation?** **What type of application is this?** (E.g. cryptography, game, numerical simulation) ## Feature request
rand-0.7.2/.github/ISSUE_TEMPLATE/other.md010064400017500001750000000001201352222772600160540ustar0000000000000000--- name: Other about: empty template title: '' labels: '' assignees: '' --- rand-0.7.2/CHANGELOG.md010064400017500001750000000456131353776312600125240ustar0000000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. ## [0.7.2] - 2019-09-16 ### Fixes - Fix dependency on `rand_core` 0.5.1 (#890) ### Additions - Unit tests for value stability of distributions added (#888) ## [0.7.1] - 2019-09-13 ### Fixes - Fix `no_std` behaviour, appropriately enable c2-chacha's `std` feature (#844) - `alloc` feature in `no_std` is available since Rust 1.36 (#856) - Fix or squelch issues from Clippy lints (#840) ### Additions - Add a `no_std` target to CI to continously evaluate `no_std` status (#844) - `WeightedIndex`: allow adjusting a sub-set of weights (#866) ## [0.7.0] - 2019-06-28 ### Fixes - Fix incorrect pointer usages revealed by Miri testing (#780, #781) - Fix (tiny!) bias in `Uniform` for 8- and 16-bit ints (#809) ### Crate - Bumped MSRV (min supported Rust version) to 1.32.0 - Updated to Rust Edition 2018 (#823, #824) - Removed dependence on `rand_xorshift`, `rand_isaac`, `rand_jitter` crates (#759, #765) - Remove dependency on `winapi` (#724) - Removed all `build.rs` files (#824) - Removed code already deprecated in version 0.6 (#757) - Removed the serde1 feature (It's still available for backwards compatibility, but it does not do anything. #830) - Many documentation changes ### rand_core - Updated to `rand_core` 0.5.0 - `Error` type redesigned with new API (#800) - Move `from_entropy` method to `SeedableRng` and remove `FromEntropy` (#800) - `SeedableRng::from_rng` is now expected to be value-stable (#815) ### Standard RNGs - OS interface moved from `rand_os` to new `getrandom` crate (#765, [getrandom](https://github.com/rust-random/getrandom)) - Use ChaCha for `StdRng` and `ThreadRng` (#792) - Feature-gate `SmallRng` (#792) - `ThreadRng` now supports `Copy` (#758) - Deprecated `EntropyRng` (#765) - Enable fork protection of ReseedingRng without `std` (#724) ### Distributions - Many distributions have been moved to `rand_distr` (#761) - `Bernoulli::new` constructor now returns a `Result` (#803) - `Distribution::sample_iter` adjusted for more flexibility (#758) - Added `distributions::weighted::alias_method::WeightedIndex` for `O(1)` sampling (#692) - Support sampling `NonZeroU*` types with the `Standard` distribution (#728) - Optimised `Binomial` distribution sampling (#735, #740, #752) - Optimised SIMD float sampling (#739) ### Sequences - Make results portable across 32- and 64-bit by using `u32` samples for `usize` where possible (#809) ## [0.6.5] - 2019-01-28 ### Crates - Update `rand_core` to 0.4 (#703) - Move `JitterRng` to its own crate (#685) - Add a wasm-bindgen test crate (#696) ### Platforms - Fuchsia: Replaced fuchsia-zircon with fuchsia-cprng ### Doc - Use RFC 1946 for doc links (#691) - Fix some doc links and notes (#711) ## [0.6.4] - 2019-01-08 ### Fixes - Move wasm-bindgen shims to correct crate (#686) - Make `wasm32-unknown-unknown` compile but fail at run-time if missing bindingsg (#686) ## [0.6.3] - 2019-01-04 ### Fixes - Make the `std` feature require the optional `rand_os` dependency (#675) - Re-export the optional WASM dependencies of `rand_os` from `rand` to avoid breakage (#674) ## [0.6.2] - 2019-01-04 ### Additions - Add `Default` for `ThreadRng` (#657) - Move `rngs::OsRng` to `rand_os` sub-crate; clean up code; use as dependency (#643) ##BLOCKER## - Add `rand_xoshiro` sub-crate, plus benchmarks (#642, #668) ### Fixes - Fix bias in `UniformInt::sample_single` (#662) - Use `autocfg` instead of `rustc_version` for rustc version detection (#664) - Disable `i128` and `u128` if the `target_os` is `emscripten` (#671: work-around Emscripten limitation) - CI fixes (#660, #671) ### Optimisations - Optimise memory usage of `UnitCircle` and `UnitSphereSurface` distributions (no PR) ## [0.6.1] - 2018-11-22 - Support sampling `Duration` also for `no_std` (only since Rust 1.25) (#649) - Disable default features of `libc` (#647) ## [0.6.0] - 2018-11-14 ### Project organisation - Rand has moved from [rust-lang-nursery](https://github.com/rust-lang-nursery/rand) to [rust-random](https://github.com/rust-random/rand)! (#578) - Created [The Rust Random Book](https://rust-random.github.io/book/) ([source](https://github.com/rust-random/book)) - Update copyright and licence notices (#591, #611) - Migrate policy documentation from the wiki (#544) ### Platforms - Add fork protection on Unix (#466) - Added support for wasm-bindgen. (#541, #559, #562, #600) - Enable `OsRng` for powerpc64, sparc and sparc64 (#609) - Use `syscall` from `libc` on Linux instead of redefining it (#629) ### RNGs - Switch `SmallRng` to use PCG (#623) - Implement `Pcg32` and `Pcg64Mcg` generators (#632) - Move ISAAC RNGs to a dedicated crate (#551) - Move Xorshift RNG to its own crate (#557) - Move ChaCha and HC128 RNGs to dedicated crates (#607, #636) - Remove usage of `Rc` from `ThreadRng` (#615) ### Sampling and distributions - Implement `Rng.gen_ratio()` and `Bernoulli::new_ratio()` (#491) - Make `Uniform` strictly respect `f32` / `f64` high/low bounds (#477) - Allow `gen_range` and `Uniform` to work on non-`Copy` types (#506) - `Uniform` supports inclusive ranges: `Uniform::from(a..=b)`. This is automatically enabled for Rust >= 1.27. (#566) - Implement `TrustedLen` and `FusedIterator` for `DistIter` (#620) #### New distributions - Add the `Dirichlet` distribution (#485) - Added sampling from the unit sphere and circle. (#567) - Implement the triangular distribution (#575) - Implement the Weibull distribution (#576) - Implement the Beta distribution (#574) #### Optimisations - Optimise `Bernoulli::new` (#500) - Optimise `char` sampling (#519) - Optimise sampling of `std::time::Duration` (#583) ### Sequences - Redesign the `seq` module (#483, #515) - Add `WeightedIndex` and `choose_weighted` (#518, #547) - Optimised and changed return type of the `sample_indices` function. (#479) - Use `Iterator::size_hint()` to speed up `IteratorRandom::choose` (#593) ### SIMD - Support for generating SIMD types (#523, #542, #561, #630) ### Other - Revise CI scripts (#632, #635) - Remove functionality already deprecated in 0.5 (#499) - Support for `i128` and `u128` is automatically enabled for Rust >= 1.26. This renders the `i128_support` feature obsolete. It still exists for backwards compatibility but does not have any effect. This breaks programs using Rand with `i128_support` on nightlies older than Rust 1.26. (#571) ## [0.5.5] - 2018-08-07 ### Documentation - Fix links in documentation (#582) ## [0.5.4] - 2018-07-11 ### Platform support - Make `OsRng` work via WASM/stdweb for WebWorkers ## [0.5.3] - 2018-06-26 ### Platform support - OpenBSD, Bitrig: fix compilation (broken in 0.5.1) (#530) ## [0.5.2] - 2018-06-18 ### Platform support - Hide `OsRng` and `JitterRng` on unsupported platforms (#512; fixes #503). ## [0.5.1] - 2018-06-08 ### New distributions - Added Cauchy distribution. (#474, #486) - Added Pareto distribution. (#495) ### Platform support and `OsRng` - Remove blanket Unix implementation. (#484) - Remove Wasm unimplemented stub. (#484) - Dragonfly BSD: read from `/dev/random`. (#484) - Bitrig: use `getentropy` like OpenBSD. (#484) - Solaris: (untested) use `getrandom` if available, otherwise `/dev/random`. (#484) - Emscripten, `stdweb`: split the read up in chunks. (#484) - Emscripten, Haiku: don't do an extra blocking read from `/dev/random`. (#484) - Linux, NetBSD, Solaris: read in blocking mode on first use in `fill_bytes`. (#484) - Fuchsia, CloudABI: fix compilation (broken in Rand 0.5). (#484) ## [0.5.0] - 2018-05-21 ### Crate features and organisation - Minimum Rust version update: 1.22.0. (#239) - Create a separate `rand_core` crate. (#288) - Deprecate `rand_derive`. (#256) - Add `prelude` (and module reorganisation). (#435) - Add `log` feature. Logging is now available in `JitterRng`, `OsRng`, `EntropyRng` and `ReseedingRng`. (#246) - Add `serde1` feature for some PRNGs. (#189) - `stdweb` feature for `OsRng` support on WASM via stdweb. (#272, #336) ### `Rng` trait - Split `Rng` in `RngCore` and `Rng` extension trait. `next_u32`, `next_u64` and `fill_bytes` are now part of `RngCore`. (#265) - Add `Rng::sample`. (#256) - Deprecate `Rng::gen_weighted_bool`. (#308) - Add `Rng::gen_bool`. (#308) - Remove `Rng::next_f32` and `Rng::next_f64`. (#273) - Add optimized `Rng::fill` and `Rng::try_fill` methods. (#247) - Deprecate `Rng::gen_iter`. (#286) - Deprecate `Rng::gen_ascii_chars`. (#279) ### `rand_core` crate - `rand` now depends on new `rand_core` crate (#288) - `RngCore` and `SeedableRng` are now part of `rand_core`. (#288) - Add modules to help implementing RNGs `impl` and `le`. (#209, #228) - Add `Error` and `ErrorKind`. (#225) - Add `CryptoRng` marker trait. (#273) - Add `BlockRngCore` trait. (#281) - Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325) - Revise the `SeedableRng` trait. (#233) - Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288) - Add `RngCore::try_fill_bytes`. (#225) ### Other traits and types - Add `FromEntropy` trait. (#233, #375) - Add `SmallRng` wrapper. (#296) - Rewrite `ReseedingRng` to only work with `BlockRngCore` (substantial performance improvement). (#281) - Deprecate `weak_rng`. Use `SmallRng` instead. (#296) - Deprecate `AsciiGenerator`. (#279) ### Random number generators - Switch `StdRng` and `thread_rng` to HC-128. (#277) - `StdRng` must now be created with `from_entropy` instead of `new` - Change `thread_rng` reseeding threshold to 32 MiB. (#277) - PRNGs no longer implement `Copy`. (#209) - `Debug` implementations no longer show internals. (#209) - Implement `Clone` for `ReseedingRng`, `JitterRng`, OsRng`. (#383, #384) - Implement serialization for `XorShiftRng`, `IsaacRng` and `Isaac64Rng` under the `serde1` feature. (#189) - Implement `BlockRngCore` for `ChaChaCore` and `Hc128Core`. (#281) - All PRNGs are now portable across big- and little-endian architectures. (#209) - `Isaac64Rng::next_u32` no longer throws away half the results. (#209) - Add `IsaacRng::new_from_u64` and `Isaac64Rng::new_from_u64`. (#209) - Add the HC-128 CSPRNG `Hc128Rng`. (#210) - Change ChaCha20 to have 64-bit counter and 64-bit stream. (#349) - Changes to `JitterRng` to get its size down from 2112 to 24 bytes. (#251) - Various performance improvements to all PRNGs. ### Platform support and `OsRng` - Add support for CloudABI. (#224) - Remove support for NaCl. (#225) - WASM support for `OsRng` via stdweb, behind the `stdweb` feature. (#272, #336) - Use `getrandom` on more platforms for Linux, and on Android. (#338) - Use the `SecRandomCopyBytes` interface on macOS. (#322) - On systems that do not have a syscall interface, only keep a single file descriptor open for `OsRng`. (#239) - On Unix, first try a single read from `/dev/random`, then `/dev/urandom`. (#338) - Better error handling and reporting in `OsRng` (using new error type). (#225) - `OsRng` now uses non-blocking when available. (#225) - Add `EntropyRng`, which provides `OsRng`, but has `JitterRng` as a fallback. (#235) ### Distributions - New `Distribution` trait. (#256) - Add `Distribution::sample_iter` and `Rng::::sample_iter`. (#361) - Deprecate `Rand`, `Sample` and `IndependentSample` traits. (#256) - Add a `Standard` distribution (replaces most `Rand` implementations). (#256) - Add `Binomial` and `Poisson` distributions. (#96) - Add `Bernoulli` dsitribution. (#411) - Add `Alphanumeric` distribution. (#279) - Remove `Closed01` distribution, add `OpenClosed01`. (#274, #420) - Rework `Range` type, making it possible to implement it for user types. (#274) - Rename `Range` to `Uniform`. (#395) - Add `Uniform::new_inclusive` for inclusive ranges. (#274) - Use widening multiply method for much faster integer range reduction. (#274) - `Standard` distribution for `char` uses `Uniform` internally. (#274) - `Standard` distribution for `bool` uses sign test. (#274) - Implement `Standard` distribution for `Wrapping`. (#436) - Implement `Uniform` distribution for `Duration`. (#427) ## [0.4.3] - 2018-08-16 ### Fixed - Use correct syscall number for PowerPC (#589) ## [0.4.2] - 2018-01-06 ### Changed - Use `winapi` on Windows - Update for Fuchsia OS - Remove dev-dependency on `log` ## [0.4.1] - 2017-12-17 ### Added - `no_std` support ## [0.4.0-pre.0] - 2017-12-11 ### Added - `JitterRng` added as a high-quality alternative entropy source using the system timer - new `seq` module with `sample_iter`, `sample_slice`, etc. - WASM support via dummy implementations (fail at run-time) - Additional benchmarks, covering generators and new seq code ### Changed - `thread_rng` uses `JitterRng` if seeding from system time fails (slower but more secure than previous method) ### Deprecated - `sample` function deprecated (replaced by `sample_iter`) ## [0.3.20] - 2018-01-06 ### Changed - Remove dev-dependency on `log` - Update `fuchsia-zircon` dependency to 0.3.2 ## [0.3.19] - 2017-12-27 ### Changed - Require `log <= 0.3.8` for dev builds - Update `fuchsia-zircon` dependency to 0.3 - Fix broken links in docs (to unblock compiler docs testing CI) ## [0.3.18] - 2017-11-06 ### Changed - `thread_rng` is seeded from the system time if `OsRng` fails - `weak_rng` now uses `thread_rng` internally ## [0.3.17] - 2017-10-07 ### Changed - Fuchsia: Magenta was renamed Zircon ## [0.3.16] - 2017-07-27 ### Added - Implement Debug for mote non-public types - implement `Rand` for (i|u)i128 - Support for Fuchsia ### Changed - Add inline attribute to SampleRange::construct_range. This improves the benchmark for sample in 11% and for shuffle in 16%. - Use `RtlGenRandom` instead of `CryptGenRandom` ## [0.3.15] - 2016-11-26 ### Added - Add `Rng` trait method `choose_mut` - Redox support ### Changed - Use `arc4rand` for `OsRng` on FreeBSD. - Use `arc4random(3)` for `OsRng` on OpenBSD. ### Fixed - Fix filling buffers 4 GiB or larger with `OsRng::fill_bytes` on Windows ## [0.3.14] - 2016-02-13 ### Fixed - Inline definitions from winapi/advapi32, wich decreases build times ## [0.3.13] - 2016-01-09 ### Fixed - Compatible with Rust 1.7.0-nightly (needed some extra type annotations) ## [0.3.12] - 2015-11-09 ### Changed - Replaced the methods in `next_f32` and `next_f64` with the technique described Saito & Matsumoto at MCQMC'08. The new method should exhibit a slightly more uniform distribution. - Depend on libc 0.2 ### Fixed - Fix iterator protocol issue in `rand::sample` ## [0.3.11] - 2015-08-31 ### Added - Implement `Rand` for arrays with n <= 32 ## [0.3.10] - 2015-08-17 ### Added - Support for NaCl platforms ### Changed - Allow `Rng` to be `?Sized`, impl for `&mut R` and `Box` where `R: ?Sized + Rng` ## [0.3.9] - 2015-06-18 ### Changed - Use `winapi` for Windows API things ### Fixed - Fixed test on stable/nightly - Fix `getrandom` syscall number for aarch64-unknown-linux-gnu ## [0.3.8] - 2015-04-23 ### Changed - `log` is a dev dependency ### Fixed - Fix race condition of atomics in `is_getrandom_available` ## [0.3.7] - 2015-04-03 ### Fixed - Derive Copy/Clone changes ## [0.3.6] - 2015-04-02 ### Changed - Move to stable Rust! ## [0.3.5] - 2015-04-01 ### Fixed - Compatible with Rust master ## [0.3.4] - 2015-03-31 ### Added - Implement Clone for `Weighted` ### Fixed - Compatible with Rust master ## [0.3.3] - 2015-03-26 ### Fixed - Fix compile on Windows ## [0.3.2] - 2015-03-26 ## [0.3.1] - 2015-03-26 ### Fixed - Fix compile on Windows ## [0.3.0] - 2015-03-25 ### Changed - Update to use log version 0.3.x ## [0.2.1] - 2015-03-22 ### Fixed - Compatible with Rust master - Fixed iOS compilation ## [0.2.0] - 2015-03-06 ### Fixed - Compatible with Rust master (move from `old_io` to `std::io`) ## [0.1.4] - 2015-03-04 ### Fixed - Compatible with Rust master (use wrapping ops) ## [0.1.3] - 2015-02-20 ### Fixed - Compatible with Rust master ### Removed - Removed Copy implementations from RNGs ## [0.1.2] - 2015-02-03 ### Added - Imported functionality from `std::rand`, including: - `StdRng`, `SeedableRng`, `TreadRng`, `weak_rng()` - `ReaderRng`: A wrapper around any Reader to treat it as an RNG. - Imported documentation from `std::rand` - Imported tests from `std::rand` ## [0.1.1] - 2015-02-03 ### Added - Migrate to a cargo-compatible directory structure. ### Fixed - Do not use entropy during `gen_weighted_bool(1)` ## [Rust 0.12.0] - 2014-10-09 ### Added - Impl Rand for tuples of arity 11 and 12 - Include ChaCha pseudorandom generator - Add `next_f64` and `next_f32` to Rng - Implement Clone for PRNGs ### Changed - Rename `TaskRng` to `ThreadRng` and `task_rng` to `thread_rng` (since a runtime is removed from Rust). ### Fixed - Improved performance of ISAAC and ISAAC64 by 30% and 12 % respectively, by informing the optimiser that indexing is never out-of-bounds. ### Removed - Removed the Deprecated `choose_option` ## [Rust 0.11.0] - 2014-07-02 ### Added - document when to use `OSRng` in cryptographic context, and explain why we use `/dev/urandom` instead of `/dev/random` - `Rng::gen_iter()` which will return an infinite stream of random values - `Rng::gen_ascii_chars()` which will return an infinite stream of random ascii characters ### Changed - Now only depends on libcore! - Remove `Rng.choose()`, rename `Rng.choose_option()` to `.choose()` - Rename OSRng to OsRng - The WeightedChoice structure is no longer built with a `Vec>`, but rather a `&mut [Weighted]`. This means that the WeightedChoice structure now has a lifetime associated with it. - The `sample` method on `Rng` has been moved to a top-level function in the `rand` module due to its dependence on `Vec`. ### Removed - `Rng::gen_vec()` was removed. Previous behavior can be regained with `rng.gen_iter().take(n).collect()` - `Rng::gen_ascii_str()` was removed. Previous behavior can be regained with `rng.gen_ascii_chars().take(n).collect()` - {IsaacRng, Isaac64Rng, XorShiftRng}::new() have all been removed. These all relied on being able to use an OSRng for seeding, but this is no longer available in librand (where these types are defined). To retain the same functionality, these types now implement the `Rand` trait so they can be generated with a random seed from another random number generator. This allows the stdlib to use an OSRng to create seeded instances of these RNGs. - Rand implementations for `Box` and `@T` were removed. These seemed to be pretty rare in the codebase, and it allows for librand to not depend on liballoc. Additionally, other pointer types like Rc and Arc were not supported. - Remove a slew of old deprecated functions ## [Rust 0.10] - 2014-04-03 ### Changed - replace `Rng.shuffle's` functionality with `.shuffle_mut` - bubble up IO errors when creating an OSRng ### Fixed - Use `fill()` instead of `read()` - Rewrite OsRng in Rust for windows ## [0.10-pre] - 2014-03-02 ### Added - Seperate `rand` out of the standard library rand-0.7.2/COPYRIGHT010064400017500001750000000010711347154030000121540ustar0000000000000000Copyrights in the Rand project are retained by their contributors. No copyright assignment is required to contribute to the Rand project. For full authorship information, see the version control history. Except as otherwise noted (below and/or in individual files), Rand is licensed under the Apache License, Version 2.0 or or the MIT license or , at your option. The Rand project includes code from the Rust project published under these same licenses. rand-0.7.2/Cargo.toml.orig010064400017500001750000000063271353776254600136060ustar0000000000000000[package] name = "rand" version = "0.7.2" authors = ["The Rand Project Developers", "The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/rust-random/rand" documentation = "https://rust-random.github.io/rand/" homepage = "https://crates.io/crates/rand" description = """ Random number generators and other randomness functionality. """ keywords = ["random", "rng"] categories = ["algorithms", "no-std"] exclude = ["/utils/*", "/.travis.yml", "/appveyor.yml", ".gitignore"] autobenches = true edition = "2018" [badges] travis-ci = { repository = "rust-random/rand" } appveyor = { repository = "rust-random/rand" } [features] # Meta-features: default = ["std"] # without "std" rand uses libcore nightly = ["simd_support"] # enables all features requiring nightly rust serde1 = [] # does nothing, deprecated # Optional dependencies: std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom"] alloc = ["rand_core/alloc"] # enables Vec and Box support (without std) # re-export optional WASM dependencies to avoid breakage: # Warning: wasm-bindgen and stdweb features will be removed in rand 0.8; # recommended to activate via the getrandom crate instead. wasm-bindgen = ["getrandom_package/wasm-bindgen"] stdweb = ["getrandom_package/stdweb"] getrandom = ["getrandom_package", "rand_core/getrandom"] # Configuration: simd_support = ["packed_simd"] # enables SIMD support small_rng = ["rand_pcg"] # enables SmallRng [workspace] members = [ "rand_core", "rand_distr", "rand_jitter", "rand_os", "rand_isaac", "rand_chacha", "rand_hc", "rand_pcg", "rand_xorshift", "rand_xoshiro", "tests/wasm_bindgen", ] [dependencies] rand_core = { path = "rand_core", version = "0.5.1" } rand_pcg = { path = "rand_pcg", version = "0.2", optional = true } # Do not depend on 'getrandom_package' directly; use the 'getrandom' feature! # This is a dependency because: we forward wasm feature flags # This is renamed because: we need getrandom to depend on rand_core/getrandom getrandom_package = { version = "0.1.1", package = "getrandom", optional = true } log = { version = "0.4.4", optional = true } [dependencies.packed_simd] # NOTE: so far no version works reliably due to dependence on unstable features version = "0.3" # git = "https://github.com/rust-lang-nursery/packed_simd" optional = true features = ["into_bits"] [target.'cfg(unix)'.dependencies] # Used for fork protection (reseeding.rs) libc = { version = "0.2.22", default-features = false } # Emscripten does not support 128-bit integers, which are used by ChaCha code. # We work around this by using a different RNG. [target.'cfg(not(target_os = "emscripten"))'.dependencies] rand_chacha = { path = "rand_chacha", version = "0.2.1", default-features = false } [target.'cfg(target_os = "emscripten")'.dependencies] rand_hc = { path = "rand_hc", version = "0.2" } [dev-dependencies] rand_pcg = { path = "rand_pcg", version = "0.2" } # Only for benches: rand_hc = { path = "rand_hc", version = "0.2" } rand_xoshiro = { path = "rand_xoshiro", version = "0.4" } rand_isaac = { path = "rand_isaac", version = "0.2" } rand_xorshift = { path = "rand_xorshift", version = "0.2" } [package.metadata.docs.rs] all-features = true rand-0.7.2/Cargo.toml0000644000000046150000000000000100310ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "rand" version = "0.7.2" authors = ["The Rand Project Developers", "The Rust Project Developers"] exclude = ["/utils/*", "/.travis.yml", "/appveyor.yml", ".gitignore"] autobenches = true description = "Random number generators and other randomness functionality.\n" homepage = "https://crates.io/crates/rand" documentation = "https://rust-random.github.io/rand/" readme = "README.md" keywords = ["random", "rng"] categories = ["algorithms", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-random/rand" [package.metadata.docs.rs] all-features = true [dependencies.getrandom_package] version = "0.1.1" optional = true package = "getrandom" [dependencies.log] version = "0.4.4" optional = true [dependencies.packed_simd] version = "0.3" features = ["into_bits"] optional = true [dependencies.rand_core] version = "0.5.1" [dependencies.rand_pcg] version = "0.2" optional = true [dev-dependencies.rand_hc] version = "0.2" [dev-dependencies.rand_isaac] version = "0.2" [dev-dependencies.rand_pcg] version = "0.2" [dev-dependencies.rand_xorshift] version = "0.2" [dev-dependencies.rand_xoshiro] version = "0.4" [features] alloc = ["rand_core/alloc"] default = ["std"] getrandom = ["getrandom_package", "rand_core/getrandom"] nightly = ["simd_support"] serde1 = [] simd_support = ["packed_simd"] small_rng = ["rand_pcg"] std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom"] stdweb = ["getrandom_package/stdweb"] wasm-bindgen = ["getrandom_package/wasm-bindgen"] [target."cfg(not(target_os = \"emscripten\"))".dependencies.rand_chacha] version = "0.2.1" default-features = false [target."cfg(target_os = \"emscripten\")".dependencies.rand_hc] version = "0.2" [target."cfg(unix)".dependencies.libc] version = "0.2.22" default-features = false [badges.appveyor] repository = "rust-random/rand" [badges.travis-ci] repository = "rust-random/rand" rand-0.7.2/LICENSE-APACHE010064400017500001750000000251411346725354400126310ustar0000000000000000 Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. rand-0.7.2/LICENSE-MIT010064400017500001750000000021351347154030000123170ustar0000000000000000Copyright 2018 Developers of the Rand project Copyright (c) 2014 The Rust Project 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. rand-0.7.2/README.md010064400017500001750000000124401353712175400121550ustar0000000000000000# Rand [![Build Status](https://travis-ci.org/rust-random/rand.svg?branch=master)](https://travis-ci.org/rust-random/rand) [![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-random/rand?svg=true)](https://ci.appveyor.com/project/rust-random/rand) [![Crate](https://img.shields.io/crates/v/rand.svg)](https://crates.io/crates/rand) [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand) [![API](https://docs.rs/rand/badge.svg)](https://docs.rs/rand) [![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements) A Rust library for random number generation. Rand provides utilities to generate random numbers, to convert them to useful types and distributions, and some randomness-related algorithms. The core random number generation traits of Rand live in the [rand_core]( https://crates.io/crates/rand_core) crate but are also exposed here; RNG implementations should prefer to use `rand_core` while most other users should depend on `rand`. Documentation: - [The Rust Rand Book](https://rust-random.github.io/book) - [API reference (master)](https://rust-random.github.io/rand) - [API reference (docs.rs)](https://docs.rs/rand) ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] rand = "0.7" ``` To get started using Rand, see [The Book](https://rust-random.github.io/book). ## Versions Rand libs have inter-dependencies and make use of the [semver trick](https://github.com/dtolnay/semver-trick/) in order to make traits compatible across crate versions. (This is especially important for `RngCore` and `SeedableRng`.) A few crate releases are thus compatibility shims, depending on the *next* lib version (e.g. `rand_core` versions `0.2.2` and `0.3.1`). This means, for example, that `rand_core_0_4_0::SeedableRng` and `rand_core_0_3_0::SeedableRng` are distinct, incompatible traits, which can cause build errors. Usually, running `cargo update` is enough to fix any issues. The Rand lib is not yet stable, however we are careful to limit breaking changes and warn via deprecation wherever possible. Patch versions never introduce breaking changes. The following minor versions are supported: - Version 0.7 was released in June 2019, moving most non-uniform distributions to an external crate, moving `from_entropy` to `SeedableRng`, and many small changes and fixes. - Version 0.6 was released in November 2018, redesigning the `seq` module, moving most PRNGs to external crates, and many small changes. - Version 0.5 was released in May 2018, as a major reorganisation (introducing `RngCore` and `rand_core`, and deprecating `Rand` and the previous distribution traits). - Version 0.4 was released in December 2017, but contained almost no breaking changes from the 0.3 series. A detailed [changelog](CHANGELOG.md) is available. When upgrading to the next minor series (especially 0.4 β†’ 0.5), we recommend reading the [Upgrade Guide](https://rust-random.github.io/book/update.html). ### Rust version requirements Since version 0.7, Rand requires **Rustc version 1.32 or greater**. Rand 0.5 requires Rustc 1.22 or greater while versions 0.4 and 0.3 (since approx. June 2017) require Rustc version 1.15 or greater. Subsets of the Rand code may work with older Rust versions, but this is not supported. Travis CI always has a build with a pinned version of Rustc matching the oldest supported Rust release. The current policy is that this can be updated in any Rand release if required, but the change must be noted in the changelog. ## Crate Features Rand is built with these features enabled by default: - `std` enables functionality dependent on the `std` lib - `alloc` (implied by `std`) enables functionality requiring an allocator (when using this feature in `no_std`, Rand requires Rustc version 1.36 or greater) - `getrandom` (implied by `std`) is an optional dependency providing the code behind `rngs::OsRng` Optionally, the following dependencies can be enabled: - `log` enables logging via the `log` crate - `stdweb` implies `getrandom/stdweb` to enable `getrandom` support on `wasm32-unknown-unknown` (will be removed in rand 0.8; activate via `getrandom` crate instead) - `wasm-bindgen` implies `getrandom/wasm-bindgen` to enable `getrandom` support on `wasm32-unknown-unknown` (will be removed in rand 0.8; activate via `getrandom` crate instead) Additionally, these features configure Rand: - `small_rng` enables inclusion of the `SmallRng` PRNG - `nightly` enables all experimental features - `simd_support` (experimental) enables sampling of SIMD values (uniformly random SIMD integers and floats) Rand supports limited functionality in `no_std` mode (enabled via `default-features = false`). In this case, `OsRng` and `from_entropy` are unavailable (unless `getrandom` is enabled), large parts of `seq` are unavailable (unless `alloc` is enabled), and `thread_rng` and `random` are unavailable. # License Rand is distributed under the terms of both the MIT license and the Apache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and [COPYRIGHT](COPYRIGHT) for details. rand-0.7.2/benches/generators.rs010064400017500001750000000214311352222772600150240ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(test)] #![allow(non_snake_case)] extern crate test; const RAND_BENCH_N: u64 = 1000; const BYTES_LEN: usize = 1024; use std::mem::size_of; use test::{black_box, Bencher}; use rand::prelude::*; use rand::rngs::adapter::ReseedingRng; use rand::rngs::{OsRng, mock::StepRng}; use rand_isaac::{IsaacRng, Isaac64Rng}; use rand_chacha::{ChaCha20Core, ChaCha8Rng, ChaCha12Rng, ChaCha20Rng}; use rand_hc::{Hc128Rng}; use rand_pcg::{Pcg32, Pcg64, Pcg64Mcg}; use rand_xorshift::XorShiftRng; use rand_xoshiro::{Xoshiro256StarStar, Xoshiro256Plus, Xoshiro128StarStar, Xoshiro128Plus, Xoroshiro128StarStar, Xoroshiro128Plus, SplitMix64, Xoroshiro64StarStar, Xoroshiro64Star}; macro_rules! gen_bytes { ($fnn:ident, $gen:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = $gen; let mut buf = [0u8; BYTES_LEN]; b.iter(|| { for _ in 0..RAND_BENCH_N { rng.fill_bytes(&mut buf); black_box(buf); } }); b.bytes = BYTES_LEN as u64 * RAND_BENCH_N; } } } gen_bytes!(gen_bytes_step, StepRng::new(0, 1)); gen_bytes!(gen_bytes_xorshift, XorShiftRng::from_entropy()); gen_bytes!(gen_bytes_xoshiro256starstar, Xoshiro256StarStar::from_entropy()); gen_bytes!(gen_bytes_xoshiro256plus, Xoshiro256Plus::from_entropy()); gen_bytes!(gen_bytes_xoshiro128starstar, Xoshiro128StarStar::from_entropy()); gen_bytes!(gen_bytes_xoshiro128plus, Xoshiro128Plus::from_entropy()); gen_bytes!(gen_bytes_xoroshiro128starstar, Xoroshiro128StarStar::from_entropy()); gen_bytes!(gen_bytes_xoroshiro128plus, Xoroshiro128Plus::from_entropy()); gen_bytes!(gen_bytes_xoroshiro64starstar, Xoroshiro64StarStar::from_entropy()); gen_bytes!(gen_bytes_xoroshiro64star, Xoroshiro64Star::from_entropy()); gen_bytes!(gen_bytes_splitmix64, SplitMix64::from_entropy()); gen_bytes!(gen_bytes_pcg32, Pcg32::from_entropy()); gen_bytes!(gen_bytes_pcg64, Pcg64::from_entropy()); gen_bytes!(gen_bytes_pcg64mcg, Pcg64Mcg::from_entropy()); gen_bytes!(gen_bytes_chacha8, ChaCha8Rng::from_entropy()); gen_bytes!(gen_bytes_chacha12, ChaCha12Rng::from_entropy()); gen_bytes!(gen_bytes_chacha20, ChaCha20Rng::from_entropy()); gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy()); gen_bytes!(gen_bytes_isaac, IsaacRng::from_entropy()); gen_bytes!(gen_bytes_isaac64, Isaac64Rng::from_entropy()); gen_bytes!(gen_bytes_std, StdRng::from_entropy()); #[cfg(feature="small_rng")] gen_bytes!(gen_bytes_small, SmallRng::from_entropy()); gen_bytes!(gen_bytes_os, OsRng); macro_rules! gen_uint { ($fnn:ident, $ty:ty, $gen:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = $gen; b.iter(|| { let mut accum: $ty = 0; for _ in 0..RAND_BENCH_N { accum = accum.wrapping_add(rng.gen::<$ty>()); } accum }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } } } gen_uint!(gen_u32_step, u32, StepRng::new(0, 1)); gen_uint!(gen_u32_xorshift, u32, XorShiftRng::from_entropy()); gen_uint!(gen_u32_xoshiro256starstar, u32, Xoshiro256StarStar::from_entropy()); gen_uint!(gen_u32_xoshiro256plus, u32, Xoshiro256Plus::from_entropy()); gen_uint!(gen_u32_xoshiro128starstar, u32, Xoshiro128StarStar::from_entropy()); gen_uint!(gen_u32_xoshiro128plus, u32, Xoshiro128Plus::from_entropy()); gen_uint!(gen_u32_xoroshiro128starstar, u32, Xoroshiro128StarStar::from_entropy()); gen_uint!(gen_u32_xoroshiro128plus, u32, Xoroshiro128Plus::from_entropy()); gen_uint!(gen_u32_xoroshiro64starstar, u32, Xoroshiro64StarStar::from_entropy()); gen_uint!(gen_u32_xoroshiro64star, u32, Xoroshiro64Star::from_entropy()); gen_uint!(gen_u32_splitmix64, u32, SplitMix64::from_entropy()); gen_uint!(gen_u32_pcg32, u32, Pcg32::from_entropy()); gen_uint!(gen_u32_pcg64, u32, Pcg64::from_entropy()); gen_uint!(gen_u32_pcg64mcg, u32, Pcg64Mcg::from_entropy()); gen_uint!(gen_u32_chacha8, u32, ChaCha8Rng::from_entropy()); gen_uint!(gen_u32_chacha12, u32, ChaCha12Rng::from_entropy()); gen_uint!(gen_u32_chacha20, u32, ChaCha20Rng::from_entropy()); gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy()); gen_uint!(gen_u32_isaac, u32, IsaacRng::from_entropy()); gen_uint!(gen_u32_isaac64, u32, Isaac64Rng::from_entropy()); gen_uint!(gen_u32_std, u32, StdRng::from_entropy()); #[cfg(feature="small_rng")] gen_uint!(gen_u32_small, u32, SmallRng::from_entropy()); gen_uint!(gen_u32_os, u32, OsRng); gen_uint!(gen_u64_step, u64, StepRng::new(0, 1)); gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy()); gen_uint!(gen_u64_xoshiro256starstar, u64, Xoshiro256StarStar::from_entropy()); gen_uint!(gen_u64_xoshiro256plus, u64, Xoshiro256Plus::from_entropy()); gen_uint!(gen_u64_xoshiro128starstar, u64, Xoshiro128StarStar::from_entropy()); gen_uint!(gen_u64_xoshiro128plus, u64, Xoshiro128Plus::from_entropy()); gen_uint!(gen_u64_xoroshiro128starstar, u64, Xoroshiro128StarStar::from_entropy()); gen_uint!(gen_u64_xoroshiro128plus, u64, Xoroshiro128Plus::from_entropy()); gen_uint!(gen_u64_xoroshiro64starstar, u64, Xoroshiro64StarStar::from_entropy()); gen_uint!(gen_u64_xoroshiro64star, u64, Xoroshiro64Star::from_entropy()); gen_uint!(gen_u64_splitmix64, u64, SplitMix64::from_entropy()); gen_uint!(gen_u64_pcg32, u64, Pcg32::from_entropy()); gen_uint!(gen_u64_pcg64, u64, Pcg64::from_entropy()); gen_uint!(gen_u64_pcg64mcg, u64, Pcg64Mcg::from_entropy()); gen_uint!(gen_u64_chacha8, u64, ChaCha8Rng::from_entropy()); gen_uint!(gen_u64_chacha12, u64, ChaCha12Rng::from_entropy()); gen_uint!(gen_u64_chacha20, u64, ChaCha20Rng::from_entropy()); gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy()); gen_uint!(gen_u64_isaac, u64, IsaacRng::from_entropy()); gen_uint!(gen_u64_isaac64, u64, Isaac64Rng::from_entropy()); gen_uint!(gen_u64_std, u64, StdRng::from_entropy()); #[cfg(feature="small_rng")] gen_uint!(gen_u64_small, u64, SmallRng::from_entropy()); gen_uint!(gen_u64_os, u64, OsRng); macro_rules! init_gen { ($fnn:ident, $gen:ident) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = XorShiftRng::from_entropy(); b.iter(|| { let r2 = $gen::from_rng(&mut rng).unwrap(); r2 }); } } } init_gen!(init_xorshift, XorShiftRng); init_gen!(init_xoshiro256starstar, Xoshiro256StarStar); init_gen!(init_xoshiro256plus, Xoshiro256Plus); init_gen!(init_xoshiro128starstar, Xoshiro128StarStar); init_gen!(init_xoshiro128plus, Xoshiro128Plus); init_gen!(init_xoroshiro128starstar, Xoroshiro128StarStar); init_gen!(init_xoroshiro128plus, Xoroshiro128Plus); init_gen!(init_xoroshiro64starstar, Xoroshiro64StarStar); init_gen!(init_xoroshiro64star, Xoroshiro64Star); init_gen!(init_splitmix64, SplitMix64); init_gen!(init_pcg32, Pcg32); init_gen!(init_pcg64, Pcg64); init_gen!(init_pcg64mcg, Pcg64Mcg); init_gen!(init_hc128, Hc128Rng); init_gen!(init_isaac, IsaacRng); init_gen!(init_isaac64, Isaac64Rng); init_gen!(init_chacha, ChaCha20Rng); const RESEEDING_BYTES_LEN: usize = 1024 * 1024; const RESEEDING_BENCH_N: u64 = 16; macro_rules! reseeding_bytes { ($fnn:ident, $thresh:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = ReseedingRng::new(ChaCha20Core::from_entropy(), $thresh * 1024, OsRng); let mut buf = [0u8; RESEEDING_BYTES_LEN]; b.iter(|| { for _ in 0..RESEEDING_BENCH_N { rng.fill_bytes(&mut buf); black_box(&buf); } }); b.bytes = RESEEDING_BYTES_LEN as u64 * RESEEDING_BENCH_N; } } } reseeding_bytes!(reseeding_chacha20_4k, 4); reseeding_bytes!(reseeding_chacha20_16k, 16); reseeding_bytes!(reseeding_chacha20_32k, 32); reseeding_bytes!(reseeding_chacha20_64k, 64); reseeding_bytes!(reseeding_chacha20_256k, 256); reseeding_bytes!(reseeding_chacha20_1M, 1024); macro_rules! threadrng_uint { ($fnn:ident, $ty:ty) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = thread_rng(); b.iter(|| { let mut accum: $ty = 0; for _ in 0..RAND_BENCH_N { accum = accum.wrapping_add(rng.gen::<$ty>()); } accum }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } } } threadrng_uint!(thread_rng_u32, u32); threadrng_uint!(thread_rng_u64, u64); rand-0.7.2/benches/misc.rs010064400017500001750000000066121352222772600136120ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(test)] extern crate test; const RAND_BENCH_N: u64 = 1000; use test::Bencher; use rand::prelude::*; use rand::distributions::{Distribution, Standard, Bernoulli}; use rand_pcg::{Pcg32, Pcg64Mcg}; #[bench] fn misc_gen_bool_const(b: &mut Bencher) { let mut rng = Pcg32::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; for _ in 0..crate::RAND_BENCH_N { accum ^= rng.gen_bool(0.18); } accum }) } #[bench] fn misc_gen_bool_var(b: &mut Bencher) { let mut rng = Pcg32::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; let mut p = 0.18; for _ in 0..crate::RAND_BENCH_N { accum ^= rng.gen_bool(p); p += 0.0001; } accum }) } #[bench] fn misc_gen_ratio_const(b: &mut Bencher) { let mut rng = Pcg32::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; for _ in 0..crate::RAND_BENCH_N { accum ^= rng.gen_ratio(2, 3); } accum }) } #[bench] fn misc_gen_ratio_var(b: &mut Bencher) { let mut rng = Pcg32::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; for i in 2..(crate::RAND_BENCH_N as u32 + 2) { accum ^= rng.gen_ratio(i, i + 1); } accum }) } #[bench] fn misc_bernoulli_const(b: &mut Bencher) { let mut rng = Pcg32::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let d = rand::distributions::Bernoulli::new(0.18).unwrap(); let mut accum = true; for _ in 0..crate::RAND_BENCH_N { accum ^= rng.sample(d); } accum }) } #[bench] fn misc_bernoulli_var(b: &mut Bencher) { let mut rng = Pcg32::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; let mut p = 0.18; for _ in 0..crate::RAND_BENCH_N { let d = Bernoulli::new(p).unwrap(); accum ^= rng.sample(d); p += 0.0001; } accum }) } #[bench] fn gen_1k_iter_repeat(b: &mut Bencher) { use std::iter; let mut rng = Pcg64Mcg::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let v: Vec = iter::repeat(()).map(|()| rng.gen()).take(128).collect(); v }); b.bytes = 1024; } #[bench] fn gen_1k_sample_iter(b: &mut Bencher) { let mut rng = Pcg64Mcg::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let v: Vec = Standard.sample_iter(&mut rng).take(128).collect(); v }); b.bytes = 1024; } #[bench] fn gen_1k_gen_array(b: &mut Bencher) { let mut rng = Pcg64Mcg::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { // max supported array length is 32! let v: [[u64; 32]; 4] = rng.gen(); v }); b.bytes = 1024; } #[bench] fn gen_1k_fill(b: &mut Bencher) { let mut rng = Pcg64Mcg::from_rng(&mut thread_rng()).unwrap(); let mut buf = [0u64; 128]; b.iter(|| { rng.fill(&mut buf[..]); buf }); b.bytes = 1024; } rand-0.7.2/benches/seq.rs010064400017500001750000000124641352222772600134510ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(test)] #![allow(non_snake_case)] extern crate test; use test::Bencher; use rand::prelude::*; use rand::seq::*; use std::mem::size_of; // We force use of 32-bit RNG since seq code is optimised for use with 32-bit // generators on all platforms. use rand_pcg::Pcg32 as SmallRng; const RAND_BENCH_N: u64 = 1000; #[bench] fn seq_shuffle_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &mut [usize] = &mut [1; 100]; b.iter(|| { x.shuffle(&mut rng); x[0] }) } #[bench] fn seq_slice_choose_1_of_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &mut [usize] = &mut [1; 1000]; for i in 0..1000 { x[i] = i; } b.iter(|| { let mut s = 0; for _ in 0..RAND_BENCH_N { s += x.choose(&mut rng).unwrap(); } s }); b.bytes = size_of::() as u64 * crate::RAND_BENCH_N; } macro_rules! seq_slice_choose_multiple { ($name:ident, $amount:expr, $length:expr) => { #[bench] fn $name(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[i32] = &[$amount; $length]; let mut result = [0i32; $amount]; b.iter(|| { // Collect full result to prevent unwanted shortcuts getting // first element (in case sample_indices returns an iterator). for (slot, sample) in result.iter_mut().zip( x.choose_multiple(&mut rng, $amount)) { *slot = *sample; } result[$amount-1] }) } } } seq_slice_choose_multiple!(seq_slice_choose_multiple_1_of_1000, 1, 1000); seq_slice_choose_multiple!(seq_slice_choose_multiple_950_of_1000, 950, 1000); seq_slice_choose_multiple!(seq_slice_choose_multiple_10_of_100, 10, 100); seq_slice_choose_multiple!(seq_slice_choose_multiple_90_of_100, 90, 100); #[bench] fn seq_iter_choose_from_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &mut [usize] = &mut [1; 1000]; for i in 0..1000 { x[i] = i; } b.iter(|| { let mut s = 0; for _ in 0..RAND_BENCH_N { s += x.iter().choose(&mut rng).unwrap(); } s }); b.bytes = size_of::() as u64 * crate::RAND_BENCH_N; } #[derive(Clone)] struct UnhintedIterator { iter: I, } impl Iterator for UnhintedIterator { type Item = I::Item; fn next(&mut self) -> Option { self.iter.next() } } #[derive(Clone)] struct WindowHintedIterator { iter: I, window_size: usize, } impl Iterator for WindowHintedIterator { type Item = I::Item; fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { (std::cmp::min(self.iter.len(), self.window_size), None) } } #[bench] fn seq_iter_unhinted_choose_from_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 1000]; b.iter(|| { UnhintedIterator { iter: x.iter() }.choose(&mut rng).unwrap() }) } #[bench] fn seq_iter_window_hinted_choose_from_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 1000]; b.iter(|| { WindowHintedIterator { iter: x.iter(), window_size: 7 }.choose(&mut rng) }) } #[bench] fn seq_iter_choose_multiple_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { x.iter().cloned().choose_multiple(&mut rng, 10) }) } #[bench] fn seq_iter_choose_multiple_fill_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; let mut buf = [0; 10]; b.iter(|| { x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf) }) } macro_rules! sample_indices { ($name:ident, $fn:ident, $amount:expr, $length:expr) => { #[bench] fn $name(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); b.iter(|| { index::$fn(&mut rng, $length, $amount) }) } } } sample_indices!(misc_sample_indices_1_of_1k, sample, 1, 1000); sample_indices!(misc_sample_indices_10_of_1k, sample, 10, 1000); sample_indices!(misc_sample_indices_100_of_1k, sample, 100, 1000); sample_indices!(misc_sample_indices_100_of_1M, sample, 100, 1000_000); sample_indices!(misc_sample_indices_100_of_1G, sample, 100, 1000_000_000); sample_indices!(misc_sample_indices_200_of_1G, sample, 200, 1000_000_000); sample_indices!(misc_sample_indices_400_of_1G, sample, 400, 1000_000_000); sample_indices!(misc_sample_indices_600_of_1G, sample, 600, 1000_000_000); rand-0.7.2/benches/weighted.rs010064400017500001750000000021001353146424500144420ustar0000000000000000// Copyright 2019 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(test)] extern crate test; use test::Bencher; use rand::Rng; use rand::distributions::WeightedIndex; #[bench] fn weighted_index_creation(b: &mut Bencher) { let mut rng = rand::thread_rng(); let weights = [1u32, 2, 4, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 7]; b.iter(|| { let distr = WeightedIndex::new(weights.to_vec()).unwrap(); rng.sample(distr) }) } #[bench] fn weighted_index_modification(b: &mut Bencher) { let mut rng = rand::thread_rng(); let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; let mut distr = WeightedIndex::new(weights.to_vec()).unwrap(); b.iter(|| { distr.update_weights(&[(2, &4), (5, &1)]).unwrap(); rng.sample(&distr) }) } rand-0.7.2/examples/monte-carlo.rs010064400017500001750000000030611352222772600153010ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013-2018 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! # Monte Carlo estimation of Ο€ //! //! Imagine that we have a square with sides of length 2 and a unit circle //! (radius = 1), both centered at the origin. The areas are: //! //! ```text //! area of circle = Ο€rΒ² = Ο€ * r * r = Ο€ //! area of square = 2Β² = 4 //! ``` //! //! The circle is entirely within the square, so if we sample many points //! randomly from the square, roughly Ο€ / 4 of them should be inside the circle. //! //! We can use the above fact to estimate the value of Ο€: pick many points in //! the square at random, calculate the fraction that fall within the circle, //! and multiply this fraction by 4. #![cfg(feature = "std")] use rand::distributions::{Distribution, Uniform}; fn main() { let range = Uniform::new(-1.0f64, 1.0); let mut rng = rand::thread_rng(); let total = 1_000_000; let mut in_circle = 0; for _ in 0..total { let a = range.sample(&mut rng); let b = range.sample(&mut rng); if a*a + b*b <= 1.0 { in_circle += 1; } } // prints something close to 3.14159... println!("Ο€ is approximately {}", 4. * (in_circle as f64) / (total as f64)); } rand-0.7.2/examples/monty-hall.rs010064400017500001750000000075531352222772600151570ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013-2018 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! ## Monty Hall Problem //! //! This is a simulation of the [Monty Hall Problem][]: //! //! > Suppose you're on a game show, and you're given the choice of three doors: //! > Behind one door is a car; behind the others, goats. You pick a door, say //! > No. 1, and the host, who knows what's behind the doors, opens another //! > door, say No. 3, which has a goat. He then says to you, "Do you want to //! > pick door No. 2?" Is it to your advantage to switch your choice? //! //! The rather unintuitive answer is that you will have a 2/3 chance of winning //! if you switch and a 1/3 chance of winning if you don't, so it's better to //! switch. //! //! This program will simulate the game show and with large enough simulation //! steps it will indeed confirm that it is better to switch. //! //! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem #![cfg(feature = "std")] use rand::distributions::{Distribution, Uniform}; use rand::Rng; struct SimulationResult { win: bool, switch: bool, } // Run a single simulation of the Monty Hall problem. fn simulate(random_door: &Uniform, rng: &mut R) -> SimulationResult { let car = random_door.sample(rng); // This is our initial choice let mut choice = random_door.sample(rng); // The game host opens a door let open = game_host_open(car, choice, rng); // Shall we switch? let switch = rng.gen(); if switch { choice = switch_door(choice, open); } SimulationResult { win: choice == car, switch } } // Returns the door the game host opens given our choice and knowledge of // where the car is. The game host will never open the door with the car. fn game_host_open(car: u32, choice: u32, rng: &mut R) -> u32 { use rand::seq::SliceRandom; *free_doors(&[car, choice]).choose(rng).unwrap() } // Returns the door we switch to, given our current choice and // the open door. There will only be one valid door. fn switch_door(choice: u32, open: u32) -> u32 { free_doors(&[choice, open])[0] } fn free_doors(blocked: &[u32]) -> Vec { (0..3).filter(|x| !blocked.contains(x)).collect() } fn main() { // The estimation will be more accurate with more simulations let num_simulations = 10000; let mut rng = rand::thread_rng(); let random_door = Uniform::new(0u32, 3); let (mut switch_wins, mut switch_losses) = (0, 0); let (mut keep_wins, mut keep_losses) = (0, 0); println!("Running {} simulations...", num_simulations); for _ in 0..num_simulations { let result = simulate(&random_door, &mut rng); match (result.win, result.switch) { (true, true) => switch_wins += 1, (true, false) => keep_wins += 1, (false, true) => switch_losses += 1, (false, false) => keep_losses += 1, } } let total_switches = switch_wins + switch_losses; let total_keeps = keep_wins + keep_losses; println!("Switched door {} times with {} wins and {} losses", total_switches, switch_wins, switch_losses); println!("Kept our choice {} times with {} wins and {} losses", total_keeps, keep_wins, keep_losses); // With a large number of simulations, the values should converge to // 0.667 and 0.333 respectively. println!("Estimated chance to win if we switch: {}", switch_wins as f32 / total_switches as f32); println!("Estimated chance to win if we don't: {}", keep_wins as f32 / total_keeps as f32); } rand-0.7.2/rustfmt.toml010064400017500001750000000013601352222772600132760ustar0000000000000000# This rustfmt file is added for configuration, but in practice much of our # code is hand-formatted, frequently with more readable results. # Comments: normalize_comments = true wrap_comments = false format_doc_comments = true comment_width = 90 # small excess is okay but prefer 80 # Arguments: use_small_heuristics = "max" fn_args_density = "compressed" fn_single_line = false overflow_delimited_expr = true where_single_line = true # enum_discrim_align_threshold = 20 # struct_field_align_threshold = 20 # Compatibility: edition = "2018" # we require compatibility back to 1.32.0 # Misc: blank_lines_upper_bound = 2 reorder_impl_items = true # report_todo = "Unnumbered" # report_fixme = "Unnumbered" # Ignored files: ignore = [] rand-0.7.2/src/distributions/bernoulli.rs010064400017500001750000000142061353740112600167240ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The Bernoulli distribution. use crate::Rng; use crate::distributions::Distribution; /// The Bernoulli distribution. /// /// This is a special case of the Binomial distribution where `n = 1`. /// /// # Example /// /// ```rust /// use rand::distributions::{Bernoulli, Distribution}; /// /// let d = Bernoulli::new(0.3).unwrap(); /// let v = d.sample(&mut rand::thread_rng()); /// println!("{} is from a Bernoulli distribution", v); /// ``` /// /// # Precision /// /// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`), /// so only probabilities that are multiples of 2-64 can be /// represented. #[derive(Clone, Copy, Debug)] pub struct Bernoulli { /// Probability of success, relative to the maximal integer. p_int: u64, } // To sample from the Bernoulli distribution we use a method that compares a // random `u64` value `v < (p * 2^64)`. // // If `p == 1.0`, the integer `v` to compare against can not represented as a // `u64`. We manually set it to `u64::MAX` instead (2^64 - 1 instead of 2^64). // Note that value of `p < 1.0` can never result in `u64::MAX`, because an // `f64` only has 53 bits of precision, and the next largest value of `p` will // result in `2^64 - 2048`. // // Also there is a 100% theoretical concern: if someone consistenly wants to // generate `true` using the Bernoulli distribution (i.e. by using a probability // of `1.0`), just using `u64::MAX` is not enough. On average it would return // false once every 2^64 iterations. Some people apparently care about this // case. // // That is why we special-case `u64::MAX` to always return `true`, without using // the RNG, and pay the performance price for all uses that *are* reasonable. // Luckily, if `new()` and `sample` are close, the compiler can optimize out the // extra check. const ALWAYS_TRUE: u64 = ::core::u64::MAX; // This is just `2.0.powi(64)`, but written this way because it is not available // in `no_std` mode. const SCALE: f64 = 2.0 * (1u64 << 63) as f64; /// Error type returned from `Bernoulli::new`. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum BernoulliError { /// `p < 0` or `p > 1`. InvalidProbability, } impl Bernoulli { /// Construct a new `Bernoulli` with the given probability of success `p`. /// /// # Precision /// /// For `p = 1.0`, the resulting distribution will always generate true. /// For `p = 0.0`, the resulting distribution will always generate false. /// /// This method is accurate for any input `p` in the range `[0, 1]` which is /// a multiple of 2-64. (Note that not all multiples of /// 2-64 in `[0, 1]` can be represented as a `f64`.) #[inline] pub fn new(p: f64) -> Result { if p < 0.0 || p >= 1.0 { if p == 1.0 { return Ok(Bernoulli { p_int: ALWAYS_TRUE }) } return Err(BernoulliError::InvalidProbability); } Ok(Bernoulli { p_int: (p * SCALE) as u64 }) } /// Construct a new `Bernoulli` with the probability of success of /// `numerator`-in-`denominator`. I.e. `new_ratio(2, 3)` will return /// a `Bernoulli` with a 2-in-3 chance, or about 67%, of returning `true`. /// /// If `numerator == denominator` then the returned `Bernoulli` will always /// return `true`. If `numerator == 0` it will always return `false`. #[inline] pub fn from_ratio(numerator: u32, denominator: u32) -> Result { if numerator > denominator { return Err(BernoulliError::InvalidProbability); } if numerator == denominator { return Ok(Bernoulli { p_int: ALWAYS_TRUE }) } let p_int = ((f64::from(numerator) / f64::from(denominator)) * SCALE) as u64; Ok(Bernoulli { p_int }) } } impl Distribution for Bernoulli { #[inline] fn sample(&self, rng: &mut R) -> bool { // Make sure to always return true for p = 1.0. if self.p_int == ALWAYS_TRUE { return true; } let v: u64 = rng.gen(); v < self.p_int } } #[cfg(test)] mod test { use crate::Rng; use crate::distributions::Distribution; use super::Bernoulli; #[test] fn test_trivial() { let mut r = crate::test::rng(1); let always_false = Bernoulli::new(0.0).unwrap(); let always_true = Bernoulli::new(1.0).unwrap(); for _ in 0..5 { assert_eq!(r.sample::(&always_false), false); assert_eq!(r.sample::(&always_true), true); assert_eq!(Distribution::::sample(&always_false, &mut r), false); assert_eq!(Distribution::::sample(&always_true, &mut r), true); } } #[test] #[cfg(not(miri))] // Miri is too slow fn test_average() { const P: f64 = 0.3; const NUM: u32 = 3; const DENOM: u32 = 10; let d1 = Bernoulli::new(P).unwrap(); let d2 = Bernoulli::from_ratio(NUM, DENOM).unwrap(); const N: u32 = 100_000; let mut sum1: u32 = 0; let mut sum2: u32 = 0; let mut rng = crate::test::rng(2); for _ in 0..N { if d1.sample(&mut rng) { sum1 += 1; } if d2.sample(&mut rng) { sum2 += 1; } } let avg1 = (sum1 as f64) / (N as f64); assert!((avg1 - P).abs() < 5e-3); let avg2 = (sum2 as f64) / (N as f64); assert!((avg2 - (NUM as f64)/(DENOM as f64)).abs() < 5e-3); } #[test] fn value_stability() { let mut rng = crate::test::rng(3); let distr = Bernoulli::new(0.4532).unwrap(); let mut buf = [false; 10]; for x in &mut buf { *x = rng.sample(&distr); } assert_eq!(buf, [true, false, false, true, false, false, true, true, true, true]); } } rand-0.7.2/src/distributions/binomial.rs010064400017500001750000000256651352222772600165440ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2016-2017 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The binomial distribution. #![allow(deprecated)] #![allow(clippy::all)] use crate::Rng; use crate::distributions::{Distribution, Uniform}; /// The binomial distribution `Binomial(n, p)`. /// /// This distribution has density function: /// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Binomial { /// Number of trials. n: u64, /// Probability of success. p: f64, } impl Binomial { /// Construct a new `Binomial` with the given shape parameters `n` (number /// of trials) and `p` (probability of success). /// /// Panics if `p < 0` or `p > 1`. pub fn new(n: u64, p: f64) -> Binomial { assert!(p >= 0.0, "Binomial::new called with p < 0"); assert!(p <= 1.0, "Binomial::new called with p > 1"); Binomial { n, p } } } /// Convert a `f64` to an `i64`, panicing on overflow. // In the future (Rust 1.34), this might be replaced with `TryFrom`. fn f64_to_i64(x: f64) -> i64 { assert!(x < (::std::i64::MAX as f64)); x as i64 } impl Distribution for Binomial { fn sample(&self, rng: &mut R) -> u64 { // Handle these values directly. if self.p == 0.0 { return 0; } else if self.p == 1.0 { return self.n; } // The binomial distribution is symmetrical with respect to p -> 1-p, // k -> n-k switch p so that it is less than 0.5 - this allows for lower // expected values we will just invert the result at the end let p = if self.p <= 0.5 { self.p } else { 1.0 - self.p }; let result; let q = 1. - p; // For small n * min(p, 1 - p), the BINV algorithm based on the inverse // transformation of the binomial distribution is efficient. Otherwise, // the BTPE algorithm is used. // // Voratas Kachitvichyanukul and Bruce W. Schmeiser. 1988. Binomial // random variate generation. Commun. ACM 31, 2 (February 1988), // 216-222. http://dx.doi.org/10.1145/42372.42381 // Threshold for prefering the BINV algorithm. The paper suggests 10, // Ranlib uses 30, and GSL uses 14. const BINV_THRESHOLD: f64 = 10.; if (self.n as f64) * p < BINV_THRESHOLD && self.n <= (::std::i32::MAX as u64) { // Use the BINV algorithm. let s = p / q; let a = ((self.n + 1) as f64) * s; let mut r = q.powi(self.n as i32); let mut u: f64 = rng.gen(); let mut x = 0; while u > r as f64 { u -= r; x += 1; r *= a / (x as f64) - s; } result = x; } else { // Use the BTPE algorithm. // Threshold for using the squeeze algorithm. This can be freely // chosen based on performance. Ranlib and GSL use 20. const SQUEEZE_THRESHOLD: i64 = 20; // Step 0: Calculate constants as functions of `n` and `p`. let n = self.n as f64; let np = n * p; let npq = np * q; let f_m = np + p; let m = f64_to_i64(f_m); // radius of triangle region, since height=1 also area of region let p1 = (2.195 * npq.sqrt() - 4.6 * q).floor() + 0.5; // tip of triangle let x_m = (m as f64) + 0.5; // left edge of triangle let x_l = x_m - p1; // right edge of triangle let x_r = x_m + p1; let c = 0.134 + 20.5 / (15.3 + (m as f64)); // p1 + area of parallelogram region let p2 = p1 * (1. + 2. * c); fn lambda(a: f64) -> f64 { a * (1. + 0.5 * a) } let lambda_l = lambda((f_m - x_l) / (f_m - x_l * p)); let lambda_r = lambda((x_r - f_m) / (x_r * q)); // p1 + area of left tail let p3 = p2 + c / lambda_l; // p1 + area of right tail let p4 = p3 + c / lambda_r; // return value let mut y: i64; let gen_u = Uniform::new(0., p4); let gen_v = Uniform::new(0., 1.); loop { // Step 1: Generate `u` for selecting the region. If region 1 is // selected, generate a triangularly distributed variate. let u = gen_u.sample(rng); let mut v = gen_v.sample(rng); if !(u > p1) { y = f64_to_i64(x_m - p1 * v + u); break; } if !(u > p2) { // Step 2: Region 2, parallelograms. Check if region 2 is // used. If so, generate `y`. let x = x_l + (u - p1) / c; v = v * c + 1.0 - (x - x_m).abs() / p1; if v > 1. { continue; } else { y = f64_to_i64(x); } } else if !(u > p3) { // Step 3: Region 3, left exponential tail. y = f64_to_i64(x_l + v.ln() / lambda_l); if y < 0 { continue; } else { v *= (u - p2) * lambda_l; } } else { // Step 4: Region 4, right exponential tail. y = f64_to_i64(x_r - v.ln() / lambda_r); if y > 0 && (y as u64) > self.n { continue; } else { v *= (u - p3) * lambda_r; } } // Step 5: Acceptance/rejection comparison. // Step 5.0: Test for appropriate method of evaluating f(y). let k = (y - m).abs(); if !(k > SQUEEZE_THRESHOLD && (k as f64) < 0.5 * npq - 1.) { // Step 5.1: Evaluate f(y) via the recursive relationship. Start the // search from the mode. let s = p / q; let a = s * (n + 1.); let mut f = 1.0; if m < y { let mut i = m; loop { i += 1; f *= a / (i as f64) - s; if i == y { break; } } } else if m > y { let mut i = y; loop { i += 1; f /= a / (i as f64) - s; if i == m { break; } } } if v > f { continue; } else { break; } } // Step 5.2: Squeezing. Check the value of ln(v) againts upper and // lower bound of ln(f(y)). let k = k as f64; let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1./6.) / npq + 0.5); let t = -0.5 * k*k / npq; let alpha = v.ln(); if alpha < t - rho { break; } if alpha > t + rho { continue; } // Step 5.3: Final acceptance/rejection test. let x1 = (y + 1) as f64; let f1 = (m + 1) as f64; let z = (f64_to_i64(n) + 1 - m) as f64; let w = (f64_to_i64(n) - y + 1) as f64; fn stirling(a: f64) -> f64 { let a2 = a * a; (13860. - (462. - (132. - (99. - 140. / a2) / a2) / a2) / a2) / a / 166320. } if alpha > x_m * (f1 / x1).ln() + (n - (m as f64) + 0.5) * (z / w).ln() + ((y - m) as f64) * (w * p / (x1 * q)).ln() // We use the signs from the GSL implementation, which are // different than the ones in the reference. According to // the GSL authors, the new signs were verified to be // correct by one of the original designers of the // algorithm. + stirling(f1) + stirling(z) - stirling(x1) - stirling(w) { continue; } break; } assert!(y >= 0); result = y as u64; } // Invert the result for p < 0.5. if p != self.p { self.n - result } else { result } } } #[cfg(test)] mod test { use crate::Rng; use crate::distributions::Distribution; use super::Binomial; fn test_binomial_mean_and_variance(n: u64, p: f64, rng: &mut R) { let binomial = Binomial::new(n, p); let expected_mean = n as f64 * p; let expected_variance = n as f64 * p * (1.0 - p); let mut results = [0.0; 1000]; for i in results.iter_mut() { *i = binomial.sample(rng) as f64; } let mean = results.iter().sum::() / results.len() as f64; assert!((mean as f64 - expected_mean).abs() < expected_mean / 50.0, "mean: {}, expected_mean: {}", mean, expected_mean); let variance = results.iter().map(|x| (x - mean) * (x - mean)).sum::() / results.len() as f64; assert!((variance - expected_variance).abs() < expected_variance / 10.0, "variance: {}, expected_variance: {}", variance, expected_variance); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_binomial() { let mut rng = crate::test::rng(351); test_binomial_mean_and_variance(150, 0.1, &mut rng); test_binomial_mean_and_variance(70, 0.6, &mut rng); test_binomial_mean_and_variance(40, 0.5, &mut rng); test_binomial_mean_and_variance(20, 0.7, &mut rng); test_binomial_mean_and_variance(20, 0.5, &mut rng); } #[test] fn test_binomial_end_points() { let mut rng = crate::test::rng(352); assert_eq!(rng.sample(Binomial::new(20, 0.0)), 0); assert_eq!(rng.sample(Binomial::new(20, 1.0)), 20); } #[test] #[should_panic] fn test_binomial_invalid_lambda_neg() { Binomial::new(20, -10.0); } } rand-0.7.2/src/distributions/cauchy.rs010064400017500001750000000062401352222772600162120ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2016-2017 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The Cauchy distribution. #![allow(deprecated)] #![allow(clippy::all)] use crate::Rng; use crate::distributions::Distribution; use std::f64::consts::PI; /// The Cauchy distribution `Cauchy(median, scale)`. /// /// This distribution has a density function: /// `f(x) = 1 / (pi * scale * (1 + ((x - median) / scale)^2))` #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Cauchy { median: f64, scale: f64 } impl Cauchy { /// Construct a new `Cauchy` with the given shape parameters /// `median` the peak location and `scale` the scale factor. /// Panics if `scale <= 0`. pub fn new(median: f64, scale: f64) -> Cauchy { assert!(scale > 0.0, "Cauchy::new called with scale factor <= 0"); Cauchy { median, scale } } } impl Distribution for Cauchy { fn sample(&self, rng: &mut R) -> f64 { // sample from [0, 1) let x = rng.gen::(); // get standard cauchy random number // note that Ο€/2 is not exactly representable, even if x=0.5 the result is finite let comp_dev = (PI * x).tan(); // shift and scale according to parameters let result = self.median + self.scale * comp_dev; result } } #[cfg(test)] mod test { use crate::distributions::Distribution; use super::Cauchy; fn median(mut numbers: &mut [f64]) -> f64 { sort(&mut numbers); let mid = numbers.len() / 2; numbers[mid] } fn sort(numbers: &mut [f64]) { numbers.sort_by(|a, b| a.partial_cmp(b).unwrap()); } #[test] #[cfg(not(miri))] // Miri doesn't support transcendental functions fn test_cauchy_averages() { // NOTE: given that the variance and mean are undefined, // this test does not have any rigorous statistical meaning. let cauchy = Cauchy::new(10.0, 5.0); let mut rng = crate::test::rng(123); let mut numbers: [f64; 1000] = [0.0; 1000]; let mut sum = 0.0; for i in 0..1000 { numbers[i] = cauchy.sample(&mut rng); sum += numbers[i]; } let median = median(&mut numbers); println!("Cauchy median: {}", median); assert!((median - 10.0).abs() < 0.4); // not 100% certain, but probable enough let mean = sum / 1000.0; println!("Cauchy mean: {}", mean); // for a Cauchy distribution the mean should not converge assert!((mean - 10.0).abs() > 0.4); // not 100% certain, but probable enough } #[test] #[should_panic] fn test_cauchy_invalid_scale_zero() { Cauchy::new(0.0, 0.0); } #[test] #[should_panic] fn test_cauchy_invalid_scale_neg() { Cauchy::new(0.0, -10.0); } } rand-0.7.2/src/distributions/dirichlet.rs010064400017500001750000000065601352222772600167120ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The dirichlet distribution. #![allow(deprecated)] #![allow(clippy::all)] use crate::Rng; use crate::distributions::Distribution; use crate::distributions::gamma::Gamma; /// The dirichelet distribution `Dirichlet(alpha)`. /// /// The Dirichlet distribution is a family of continuous multivariate /// probability distributions parameterized by a vector alpha of positive reals. /// It is a multivariate generalization of the beta distribution. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Debug)] pub struct Dirichlet { /// Concentration parameters (alpha) alpha: Vec, } impl Dirichlet { /// Construct a new `Dirichlet` with the given alpha parameter `alpha`. /// /// # Panics /// - if `alpha.len() < 2` /// #[inline] pub fn new>>(alpha: V) -> Dirichlet { let a = alpha.into(); assert!(a.len() > 1); for i in 0..a.len() { assert!(a[i] > 0.0); } Dirichlet { alpha: a } } /// Construct a new `Dirichlet` with the given shape parameter `alpha` and `size`. /// /// # Panics /// - if `alpha <= 0.0` /// - if `size < 2` /// #[inline] pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet { assert!(alpha > 0.0); assert!(size > 1); Dirichlet { alpha: vec![alpha; size], } } } impl Distribution> for Dirichlet { fn sample(&self, rng: &mut R) -> Vec { let n = self.alpha.len(); let mut samples = vec![0.0f64; n]; let mut sum = 0.0f64; for i in 0..n { let g = Gamma::new(self.alpha[i], 1.0); samples[i] = g.sample(rng); sum += samples[i]; } let invacc = 1.0 / sum; for i in 0..n { samples[i] *= invacc; } samples } } #[cfg(test)] mod test { use super::Dirichlet; use crate::distributions::Distribution; #[test] fn test_dirichlet() { let d = Dirichlet::new(vec![1.0, 2.0, 3.0]); let mut rng = crate::test::rng(221); let samples = d.sample(&mut rng); let _: Vec = samples .into_iter() .map(|x| { assert!(x > 0.0); x }) .collect(); } #[test] fn test_dirichlet_with_param() { let alpha = 0.5f64; let size = 2; let d = Dirichlet::new_with_param(alpha, size); let mut rng = crate::test::rng(221); let samples = d.sample(&mut rng); let _: Vec = samples .into_iter() .map(|x| { assert!(x > 0.0); x }) .collect(); } #[test] #[should_panic] fn test_dirichlet_invalid_length() { Dirichlet::new_with_param(0.5f64, 1); } #[test] #[should_panic] fn test_dirichlet_invalid_alpha() { Dirichlet::new_with_param(0.0f64, 2); } } rand-0.7.2/src/distributions/exponential.rs010064400017500001750000000064541352222772600172730ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The exponential distribution. #![allow(deprecated)] use crate::{Rng}; use crate::distributions::{ziggurat_tables, Distribution}; use crate::distributions::utils::ziggurat; /// Samples floating-point numbers according to the exponential distribution, /// with rate parameter `Ξ» = 1`. This is equivalent to `Exp::new(1.0)` or /// sampling with `-rng.gen::().ln()`, but faster. /// /// See `Exp` for the general exponential distribution. /// /// Implemented via the ZIGNOR variant[^1] of the Ziggurat method. The exact /// description in the paper was adjusted to use tables for the exponential /// distribution rather than normal. /// /// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to /// Generate Normal Random Samples*]( /// https://www.doornik.com/research/ziggurat.pdf). /// Nuffield College, Oxford #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Exp1; // This could be done via `-rng.gen::().ln()` but that is slower. impl Distribution for Exp1 { #[inline] fn sample(&self, rng: &mut R) -> f64 { #[inline] fn pdf(x: f64) -> f64 { (-x).exp() } #[inline] fn zero_case(rng: &mut R, _u: f64) -> f64 { ziggurat_tables::ZIG_EXP_R - rng.gen::().ln() } ziggurat(rng, false, &ziggurat_tables::ZIG_EXP_X, &ziggurat_tables::ZIG_EXP_F, pdf, zero_case) } } /// The exponential distribution `Exp(lambda)`. /// /// This distribution has density function: `f(x) = lambda * exp(-lambda * x)` /// for `x > 0`. /// /// Note that [`Exp1`](crate::distributions::Exp1) is an optimised implementation for `lambda = 1`. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Exp { /// `lambda` stored as `1/lambda`, since this is what we scale by. lambda_inverse: f64 } impl Exp { /// Construct a new `Exp` with the given shape parameter /// `lambda`. Panics if `lambda <= 0`. #[inline] pub fn new(lambda: f64) -> Exp { assert!(lambda > 0.0, "Exp::new called with `lambda` <= 0"); Exp { lambda_inverse: 1.0 / lambda } } } impl Distribution for Exp { fn sample(&self, rng: &mut R) -> f64 { let n: f64 = rng.sample(Exp1); n * self.lambda_inverse } } #[cfg(test)] mod test { use crate::distributions::Distribution; use super::Exp; #[test] fn test_exp() { let exp = Exp::new(10.0); let mut rng = crate::test::rng(221); for _ in 0..1000 { assert!(exp.sample(&mut rng) >= 0.0); } } #[test] #[should_panic] fn test_exp_invalid_lambda_zero() { Exp::new(0.0); } #[test] #[should_panic] fn test_exp_invalid_lambda_neg() { Exp::new(-10.0); } } rand-0.7.2/src/distributions/float.rs010064400017500001750000000301141353741144700160410ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Basic floating-point number distributions use core::mem; use crate::Rng; use crate::distributions::{Distribution, Standard}; use crate::distributions::utils::FloatSIMDUtils; #[cfg(feature="simd_support")] use packed_simd::*; /// A distribution to sample floating point numbers uniformly in the half-open /// interval `(0, 1]`, i.e. including 1 but not 0. /// /// All values that can be generated are of the form `n * Ξ΅/2`. For `f32` /// the 23 most significant random bits of a `u32` are used and for `f64` the /// 53 most significant bits of a `u64` are used. The conversion uses the /// multiplicative method. /// /// See also: [`Standard`] which samples from `[0, 1)`, [`Open01`] /// which samples from `(0, 1)` and [`Uniform`] which samples from arbitrary /// ranges. /// /// # Example /// ``` /// use rand::{thread_rng, Rng}; /// use rand::distributions::OpenClosed01; /// /// let val: f32 = thread_rng().sample(OpenClosed01); /// println!("f32 from (0, 1): {}", val); /// ``` /// /// [`Standard`]: crate::distributions::Standard /// [`Open01`]: crate::distributions::Open01 /// [`Uniform`]: crate::distributions::uniform::Uniform #[derive(Clone, Copy, Debug)] pub struct OpenClosed01; /// A distribution to sample floating point numbers uniformly in the open /// interval `(0, 1)`, i.e. not including either endpoint. /// /// All values that can be generated are of the form `n * Ξ΅ + Ξ΅/2`. For `f32` /// the 22 most significant random bits of an `u32` are used, for `f64` 52 from /// an `u64`. The conversion uses a transmute-based method. /// /// See also: [`Standard`] which samples from `[0, 1)`, [`OpenClosed01`] /// which samples from `(0, 1]` and [`Uniform`] which samples from arbitrary /// ranges. /// /// # Example /// ``` /// use rand::{thread_rng, Rng}; /// use rand::distributions::Open01; /// /// let val: f32 = thread_rng().sample(Open01); /// println!("f32 from (0, 1): {}", val); /// ``` /// /// [`Standard`]: crate::distributions::Standard /// [`OpenClosed01`]: crate::distributions::OpenClosed01 /// [`Uniform`]: crate::distributions::uniform::Uniform #[derive(Clone, Copy, Debug)] pub struct Open01; // This trait is needed by both this lib and rand_distr hence is a hidden export #[doc(hidden)] pub trait IntoFloat { type F; /// Helper method to combine the fraction and a contant exponent into a /// float. /// /// Only the least significant bits of `self` may be set, 23 for `f32` and /// 52 for `f64`. /// The resulting value will fall in a range that depends on the exponent. /// As an example the range with exponent 0 will be /// [20..21), which is [1..2). fn into_float_with_exponent(self, exponent: i32) -> Self::F; } macro_rules! float_impls { ($ty:ident, $uty:ident, $f_scalar:ident, $u_scalar:ty, $fraction_bits:expr, $exponent_bias:expr) => { impl IntoFloat for $uty { type F = $ty; #[inline(always)] fn into_float_with_exponent(self, exponent: i32) -> $ty { // The exponent is encoded using an offset-binary representation let exponent_bits: $u_scalar = (($exponent_bias + exponent) as $u_scalar) << $fraction_bits; $ty::from_bits(self | exponent_bits) } } impl Distribution<$ty> for Standard { fn sample(&self, rng: &mut R) -> $ty { // Multiply-based method; 24/53 random bits; [0, 1) interval. // We use the most significant bits because for simple RNGs // those are usually more random. let float_size = mem::size_of::<$f_scalar>() as u32 * 8; let precision = $fraction_bits + 1; let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar); let value: $uty = rng.gen(); let value = value >> (float_size - precision); scale * $ty::cast_from_int(value) } } impl Distribution<$ty> for OpenClosed01 { fn sample(&self, rng: &mut R) -> $ty { // Multiply-based method; 24/53 random bits; (0, 1] interval. // We use the most significant bits because for simple RNGs // those are usually more random. let float_size = mem::size_of::<$f_scalar>() as u32 * 8; let precision = $fraction_bits + 1; let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar); let value: $uty = rng.gen(); let value = value >> (float_size - precision); // Add 1 to shift up; will not overflow because of right-shift: scale * $ty::cast_from_int(value + 1) } } impl Distribution<$ty> for Open01 { fn sample(&self, rng: &mut R) -> $ty { // Transmute-based method; 23/52 random bits; (0, 1) interval. // We use the most significant bits because for simple RNGs // those are usually more random. use core::$f_scalar::EPSILON; let float_size = mem::size_of::<$f_scalar>() as u32 * 8; let value: $uty = rng.gen(); let fraction = value >> (float_size - $fraction_bits); fraction.into_float_with_exponent(0) - (1.0 - EPSILON / 2.0) } } } } float_impls! { f32, u32, f32, u32, 23, 127 } float_impls! { f64, u64, f64, u64, 52, 1023 } #[cfg(feature="simd_support")] float_impls! { f32x2, u32x2, f32, u32, 23, 127 } #[cfg(feature="simd_support")] float_impls! { f32x4, u32x4, f32, u32, 23, 127 } #[cfg(feature="simd_support")] float_impls! { f32x8, u32x8, f32, u32, 23, 127 } #[cfg(feature="simd_support")] float_impls! { f32x16, u32x16, f32, u32, 23, 127 } #[cfg(feature="simd_support")] float_impls! { f64x2, u64x2, f64, u64, 52, 1023 } #[cfg(feature="simd_support")] float_impls! { f64x4, u64x4, f64, u64, 52, 1023 } #[cfg(feature="simd_support")] float_impls! { f64x8, u64x8, f64, u64, 52, 1023 } #[cfg(test)] mod tests { use super::*; use crate::rngs::mock::StepRng; const EPSILON32: f32 = ::core::f32::EPSILON; const EPSILON64: f64 = ::core::f64::EPSILON; macro_rules! test_f32 { ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => { #[test] fn $fnn() { // Standard let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.gen::<$ty>(), $ZERO); let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0); assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0); let mut max = StepRng::new(!0, 0); assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0); // OpenClosed01 let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0); let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0); assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0); // Open01 let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0); let mut one = StepRng::new(1 << 9 | 1 << (9 + 32), 0); assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0); let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0); } } } test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 } #[cfg(feature="simd_support")] test_f32! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32) } #[cfg(feature="simd_support")] test_f32! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32) } #[cfg(feature="simd_support")] test_f32! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32) } #[cfg(feature="simd_support")] test_f32! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32) } macro_rules! test_f64 { ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => { #[test] fn $fnn() { // Standard let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.gen::<$ty>(), $ZERO); let mut one = StepRng::new(1 << 11, 0); assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0); let mut max = StepRng::new(!0, 0); assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0); // OpenClosed01 let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0); let mut one = StepRng::new(1 << 11, 0); assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0); // Open01 let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0); let mut one = StepRng::new(1 << 12, 0); assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0); let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0); } } } test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 } #[cfg(feature="simd_support")] test_f64! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64) } #[cfg(feature="simd_support")] test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) } #[cfg(feature="simd_support")] test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) } #[test] fn value_stability() { fn test_samples>( distr: &D, zero: T, expected: &[T] ) { let mut rng = crate::test::rng(0x6f44f5646c2a7334); let mut buf = [zero; 3]; for x in &mut buf { *x = rng.sample(&distr); } assert_eq!(&buf, expected); } test_samples(&Standard, 0f32, &[0.0035963655, 0.7346052, 0.09778172]); test_samples(&Standard, 0f64, &[0.7346051961657583, 0.20298547462974248, 0.8166436635290655]); test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]); test_samples(&OpenClosed01, 0f64, &[0.7346051961657584, 0.2029854746297426, 0.8166436635290656]); test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]); test_samples(&Open01, 0f64, &[0.7346051961657584, 0.20298547462974248, 0.8166436635290656]); #[cfg(feature="simd_support")] { // We only test a sub-set of types here. Values are identical to // non-SIMD types; we assume this pattern continues across all // SIMD types. test_samples(&Standard, f32x2::new(0.0, 0.0), &[ f32x2::new(0.0035963655, 0.7346052), f32x2::new(0.09778172, 0.20298547), f32x2::new(0.34296435, 0.81664366)]); test_samples(&Standard, f64x2::new(0.0, 0.0), &[ f64x2::new(0.7346051961657583, 0.20298547462974248), f64x2::new(0.8166436635290655, 0.7423708925400552), f64x2::new(0.16387782224016323, 0.9087068770169618)]); } } } rand-0.7.2/src/distributions/gamma.rs010064400017500001750000000246101352222772600160210ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The Gamma and derived distributions. #![allow(deprecated)] use self::GammaRepr::*; use self::ChiSquaredRepr::*; use crate::Rng; use crate::distributions::normal::StandardNormal; use crate::distributions::{Distribution, Exp, Open01}; /// The Gamma distribution `Gamma(shape, scale)` distribution. /// /// The density function of this distribution is /// /// ```text /// f(x) = x^(k - 1) * exp(-x / ΞΈ) / (Ξ“(k) * ΞΈ^k) /// ``` /// /// where `Ξ“` is the Gamma function, `k` is the shape and `ΞΈ` is the /// scale and both `k` and `ΞΈ` are strictly positive. /// /// The algorithm used is that described by Marsaglia & Tsang 2000[^1], /// falling back to directly sampling from an Exponential for `shape /// == 1`, and using the boosting technique described in that paper for /// `shape < 1`. /// /// [^1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method for /// Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3 /// (September 2000), 363-372. /// DOI:[10.1145/358407.358414](https://doi.acm.org/10.1145/358407.358414) #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Gamma { repr: GammaRepr, } #[derive(Clone, Copy, Debug)] enum GammaRepr { Large(GammaLargeShape), One(Exp), Small(GammaSmallShape) } // These two helpers could be made public, but saving the // match-on-Gamma-enum branch from using them directly (e.g. if one // knows that the shape is always > 1) doesn't appear to be much // faster. /// Gamma distribution where the shape parameter is less than 1. /// /// Note, samples from this require a compulsory floating-point `pow` /// call, which makes it significantly slower than sampling from a /// gamma distribution where the shape parameter is greater than or /// equal to 1. /// /// See `Gamma` for sampling from a Gamma distribution with general /// shape parameters. #[derive(Clone, Copy, Debug)] struct GammaSmallShape { inv_shape: f64, large_shape: GammaLargeShape } /// Gamma distribution where the shape parameter is larger than 1. /// /// See `Gamma` for sampling from a Gamma distribution with general /// shape parameters. #[derive(Clone, Copy, Debug)] struct GammaLargeShape { scale: f64, c: f64, d: f64 } impl Gamma { /// Construct an object representing the `Gamma(shape, scale)` /// distribution. /// /// Panics if `shape <= 0` or `scale <= 0`. #[inline] pub fn new(shape: f64, scale: f64) -> Gamma { assert!(shape > 0.0, "Gamma::new called with shape <= 0"); assert!(scale > 0.0, "Gamma::new called with scale <= 0"); let repr = if shape == 1.0 { One(Exp::new(1.0 / scale)) } else if shape < 1.0 { Small(GammaSmallShape::new_raw(shape, scale)) } else { Large(GammaLargeShape::new_raw(shape, scale)) }; Gamma { repr } } } impl GammaSmallShape { fn new_raw(shape: f64, scale: f64) -> GammaSmallShape { GammaSmallShape { inv_shape: 1. / shape, large_shape: GammaLargeShape::new_raw(shape + 1.0, scale) } } } impl GammaLargeShape { fn new_raw(shape: f64, scale: f64) -> GammaLargeShape { let d = shape - 1. / 3.; GammaLargeShape { scale, c: 1. / (9. * d).sqrt(), d } } } impl Distribution for Gamma { fn sample(&self, rng: &mut R) -> f64 { match self.repr { Small(ref g) => g.sample(rng), One(ref g) => g.sample(rng), Large(ref g) => g.sample(rng), } } } impl Distribution for GammaSmallShape { fn sample(&self, rng: &mut R) -> f64 { let u: f64 = rng.sample(Open01); self.large_shape.sample(rng) * u.powf(self.inv_shape) } } impl Distribution for GammaLargeShape { fn sample(&self, rng: &mut R) -> f64 { loop { let x = rng.sample(StandardNormal); let v_cbrt = 1.0 + self.c * x; if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0 continue } let v = v_cbrt * v_cbrt * v_cbrt; let u: f64 = rng.sample(Open01); let x_sqr = x * x; if u < 1.0 - 0.0331 * x_sqr * x_sqr || u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) { return self.d * v * self.scale } } } } /// The chi-squared distribution `χ²(k)`, where `k` is the degrees of /// freedom. /// /// For `k > 0` integral, this distribution is the sum of the squares /// of `k` independent standard normal random variables. For other /// `k`, this uses the equivalent characterisation /// `χ²(k) = Gamma(k/2, 2)`. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct ChiSquared { repr: ChiSquaredRepr, } #[derive(Clone, Copy, Debug)] enum ChiSquaredRepr { // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1, // e.g. when alpha = 1/2 as it would be for this case, so special- // casing and using the definition of N(0,1)^2 is faster. DoFExactlyOne, DoFAnythingElse(Gamma), } impl ChiSquared { /// Create a new chi-squared distribution with degrees-of-freedom /// `k`. Panics if `k < 0`. pub fn new(k: f64) -> ChiSquared { let repr = if k == 1.0 { DoFExactlyOne } else { assert!(k > 0.0, "ChiSquared::new called with `k` < 0"); DoFAnythingElse(Gamma::new(0.5 * k, 2.0)) }; ChiSquared { repr } } } impl Distribution for ChiSquared { fn sample(&self, rng: &mut R) -> f64 { match self.repr { DoFExactlyOne => { // k == 1 => N(0,1)^2 let norm = rng.sample(StandardNormal); norm * norm } DoFAnythingElse(ref g) => g.sample(rng) } } } /// The Fisher F distribution `F(m, n)`. /// /// This distribution is equivalent to the ratio of two normalised /// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) / /// (χ²(n)/n)`. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct FisherF { numer: ChiSquared, denom: ChiSquared, // denom_dof / numer_dof so that this can just be a straight // multiplication, rather than a division. dof_ratio: f64, } impl FisherF { /// Create a new `FisherF` distribution, with the given /// parameter. Panics if either `m` or `n` are not positive. pub fn new(m: f64, n: f64) -> FisherF { assert!(m > 0.0, "FisherF::new called with `m < 0`"); assert!(n > 0.0, "FisherF::new called with `n < 0`"); FisherF { numer: ChiSquared::new(m), denom: ChiSquared::new(n), dof_ratio: n / m } } } impl Distribution for FisherF { fn sample(&self, rng: &mut R) -> f64 { self.numer.sample(rng) / self.denom.sample(rng) * self.dof_ratio } } /// The Student t distribution, `t(nu)`, where `nu` is the degrees of /// freedom. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct StudentT { chi: ChiSquared, dof: f64 } impl StudentT { /// Create a new Student t distribution with `n` degrees of /// freedom. Panics if `n <= 0`. pub fn new(n: f64) -> StudentT { assert!(n > 0.0, "StudentT::new called with `n <= 0`"); StudentT { chi: ChiSquared::new(n), dof: n } } } impl Distribution for StudentT { fn sample(&self, rng: &mut R) -> f64 { let norm = rng.sample(StandardNormal); norm * (self.dof / self.chi.sample(rng)).sqrt() } } /// The Beta distribution with shape parameters `alpha` and `beta`. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Beta { gamma_a: Gamma, gamma_b: Gamma, } impl Beta { /// Construct an object representing the `Beta(alpha, beta)` /// distribution. /// /// Panics if `shape <= 0` or `scale <= 0`. pub fn new(alpha: f64, beta: f64) -> Beta { assert!((alpha > 0.) & (beta > 0.)); Beta { gamma_a: Gamma::new(alpha, 1.), gamma_b: Gamma::new(beta, 1.), } } } impl Distribution for Beta { fn sample(&self, rng: &mut R) -> f64 { let x = self.gamma_a.sample(rng); let y = self.gamma_b.sample(rng); x / (x + y) } } #[cfg(test)] mod test { use crate::distributions::Distribution; use super::{Beta, ChiSquared, StudentT, FisherF}; const N: u32 = 100; #[test] fn test_chi_squared_one() { let chi = ChiSquared::new(1.0); let mut rng = crate::test::rng(201); for _ in 0..N { chi.sample(&mut rng); } } #[test] fn test_chi_squared_small() { let chi = ChiSquared::new(0.5); let mut rng = crate::test::rng(202); for _ in 0..N { chi.sample(&mut rng); } } #[test] fn test_chi_squared_large() { let chi = ChiSquared::new(30.0); let mut rng = crate::test::rng(203); for _ in 0..N { chi.sample(&mut rng); } } #[test] #[should_panic] fn test_chi_squared_invalid_dof() { ChiSquared::new(-1.0); } #[test] fn test_f() { let f = FisherF::new(2.0, 32.0); let mut rng = crate::test::rng(204); for _ in 0..N { f.sample(&mut rng); } } #[test] fn test_t() { let t = StudentT::new(11.0); let mut rng = crate::test::rng(205); for _ in 0..N { t.sample(&mut rng); } } #[test] fn test_beta() { let beta = Beta::new(1.0, 2.0); let mut rng = crate::test::rng(201); for _ in 0..N { beta.sample(&mut rng); } } #[test] #[should_panic] fn test_beta_invalid_dof() { Beta::new(0., 0.); } } rand-0.7.2/src/distributions/integer.rs010064400017500001750000000206351353741145500163770ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The implementations of the `Standard` distribution for integer types. use crate::{Rng}; use crate::distributions::{Distribution, Standard}; use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; #[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128; #[cfg(feature="simd_support")] use packed_simd::*; #[cfg(all(target_arch = "x86", feature="nightly"))] use core::arch::x86::*; #[cfg(all(target_arch = "x86_64", feature="nightly"))] use core::arch::x86_64::*; impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> u8 { rng.next_u32() as u8 } } impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> u16 { rng.next_u32() as u16 } } impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> u32 { rng.next_u32() } } impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> u64 { rng.next_u64() } } #[cfg(not(target_os = "emscripten"))] impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> u128 { // Use LE; we explicitly generate one value before the next. let x = u128::from(rng.next_u64()); let y = u128::from(rng.next_u64()); (y << 64) | x } } impl Distribution for Standard { #[inline] #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] fn sample(&self, rng: &mut R) -> usize { rng.next_u32() as usize } #[inline] #[cfg(target_pointer_width = "64")] fn sample(&self, rng: &mut R) -> usize { rng.next_u64() as usize } } macro_rules! impl_int_from_uint { ($ty:ty, $uty:ty) => { impl Distribution<$ty> for Standard { #[inline] fn sample(&self, rng: &mut R) -> $ty { rng.gen::<$uty>() as $ty } } } } impl_int_from_uint! { i8, u8 } impl_int_from_uint! { i16, u16 } impl_int_from_uint! { i32, u32 } impl_int_from_uint! { i64, u64 } #[cfg(not(target_os = "emscripten"))] impl_int_from_uint! { i128, u128 } impl_int_from_uint! { isize, usize } macro_rules! impl_nzint { ($ty:ty, $new:path) => { impl Distribution<$ty> for Standard { fn sample(&self, rng: &mut R) -> $ty { loop { if let Some(nz) = $new(rng.gen()) { break nz; } } } } } } impl_nzint!(NonZeroU8, NonZeroU8::new); impl_nzint!(NonZeroU16, NonZeroU16::new); impl_nzint!(NonZeroU32, NonZeroU32::new); impl_nzint!(NonZeroU64, NonZeroU64::new); #[cfg(not(target_os = "emscripten"))] impl_nzint!(NonZeroU128, NonZeroU128::new); impl_nzint!(NonZeroUsize, NonZeroUsize::new); #[cfg(feature="simd_support")] macro_rules! simd_impl { ($(($intrinsic:ident, $vec:ty),)+) => {$( impl Distribution<$intrinsic> for Standard { #[inline] fn sample(&self, rng: &mut R) -> $intrinsic { $intrinsic::from_bits(rng.gen::<$vec>()) } } )+}; ($bits:expr,) => {}; ($bits:expr, $ty:ty, $($ty_more:ty,)*) => { simd_impl!($bits, $($ty_more,)*); impl Distribution<$ty> for Standard { #[inline] fn sample(&self, rng: &mut R) -> $ty { let mut vec: $ty = Default::default(); unsafe { let ptr = &mut vec; let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]); rng.fill_bytes(b_ptr); } vec.to_le() } } }; } #[cfg(feature="simd_support")] simd_impl!(16, u8x2, i8x2,); #[cfg(feature="simd_support")] simd_impl!(32, u8x4, i8x4, u16x2, i16x2,); #[cfg(feature="simd_support")] simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,); #[cfg(feature="simd_support")] simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,); #[cfg(feature="simd_support")] simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,); #[cfg(feature="simd_support")] simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,); #[cfg(all(feature="simd_support", feature="nightly", any(target_arch="x86", target_arch="x86_64")))] simd_impl!((__m64, u8x8), (__m128i, u8x16), (__m256i, u8x32),); #[cfg(test)] mod tests { use super::*; #[test] fn test_integers() { let mut rng = crate::test::rng(806); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); #[cfg(not(target_os = "emscripten"))] rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); #[cfg(not(target_os = "emscripten"))] rng.sample::(Standard); } #[test] fn value_stability() { fn test_samples( zero: T, expected: &[T] ) where Standard: Distribution { let mut rng = crate::test::rng(807); let mut buf = [zero; 3]; for x in &mut buf { *x = rng.sample(Standard); } assert_eq!(&buf, expected); } test_samples(0u8, &[9, 247, 111]); test_samples(0u16, &[32265, 42999, 38255]); test_samples(0u32, &[2220326409, 2575017975, 2018088303]); test_samples(0u64, &[11059617991457472009, 16096616328739788143, 1487364411147516184]); test_samples(0u128, &[296930161868957086625409848350820761097, 145644820879247630242265036535529306392, 111087889832015897993126088499035356354]); #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] test_samples(0usize, &[2220326409, 2575017975, 2018088303]); #[cfg(target_pointer_width = "64")] test_samples(0usize, &[11059617991457472009, 16096616328739788143, 1487364411147516184]); test_samples(0i8, &[9, -9, 111]); // Skip further i* types: they are simple reinterpretation of u* samples #[cfg(feature="simd_support")] { // We only test a sub-set of types here and make assumptions about the rest. test_samples(u8x2::default(), &[u8x2::new(9, 126), u8x2::new(247, 167), u8x2::new(111, 149)]); test_samples(u8x4::default(), &[u8x4::new(9, 126, 87, 132), u8x4::new(247, 167, 123, 153), u8x4::new(111, 149, 73, 120)]); test_samples(u8x8::default(), &[ u8x8::new(9, 126, 87, 132, 247, 167, 123, 153), u8x8::new(111, 149, 73, 120, 68, 171, 98, 223), u8x8::new(24, 121, 1, 50, 13, 46, 164, 20)]); test_samples(i64x8::default(), &[ i64x8::new(-7387126082252079607, -2350127744969763473, 1487364411147516184, 7895421560427121838, 602190064936008898, 6022086574635100741, -5080089175222015595, -4066367846667249123), i64x8::new(9180885022207963908, 3095981199532211089, 6586075293021332726, 419343203796414657, 3186951873057035255, 5287129228749947252, 444726432079249540, -1587028029513790706), i64x8::new(6075236523189346388, 1351763722368165432, -6192309979959753740, -7697775502176768592, -4482022114172078123, 7522501477800909500, -1837258847956201231, -586926753024886735)]); } } } rand-0.7.2/src/distributions/mod.rs010064400017500001750000000352551353741322400155210ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013-2017 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Generating random samples from probability distributions //! //! This module is the home of the [`Distribution`] trait and several of its //! implementations. It is the workhorse behind some of the convenient //! functionality of the [`Rng`] trait, e.g. [`Rng::gen`], [`Rng::gen_range`] and //! of course [`Rng::sample`]. //! //! Abstractly, a [probability distribution] describes the probability of //! occurance of each value in its sample space. //! //! More concretely, an implementation of `Distribution` for type `X` is an //! algorithm for choosing values from the sample space (a subset of `T`) //! according to the distribution `X` represents, using an external source of //! randomness (an RNG supplied to the `sample` function). //! //! A type `X` may implement `Distribution` for multiple types `T`. //! Any type implementing [`Distribution`] is stateless (i.e. immutable), //! but it may have internal parameters set at construction time (for example, //! [`Uniform`] allows specification of its sample space as a range within `T`). //! //! //! # The `Standard` distribution //! //! The [`Standard`] distribution is important to mention. This is the //! distribution used by [`Rng::gen()`] and represents the "default" way to //! produce a random value for many different types, including most primitive //! types, tuples, arrays, and a few derived types. See the documentation of //! [`Standard`] for more details. //! //! Implementing `Distribution` for [`Standard`] for user types `T` makes it //! possible to generate type `T` with [`Rng::gen()`], and by extension also //! with the [`random()`] function. //! //! ## Random characters //! //! [`Alphanumeric`] is a simple distribution to sample random letters and //! numbers of the `char` type; in contrast [`Standard`] may sample any valid //! `char`. //! //! //! # Uniform numeric ranges //! //! The [`Uniform`] distribution is more flexible than [`Standard`], but also //! more specialised: it supports fewer target types, but allows the sample //! space to be specified as an arbitrary range within its target type `T`. //! Both [`Standard`] and [`Uniform`] are in some sense uniform distributions. //! //! Values may be sampled from this distribution using [`Rng::gen_range`] or //! by creating a distribution object with [`Uniform::new`], //! [`Uniform::new_inclusive`] or `From`. When the range limits are not //! known at compile time it is typically faster to reuse an existing //! distribution object than to call [`Rng::gen_range`]. //! //! User types `T` may also implement `Distribution` for [`Uniform`], //! although this is less straightforward than for [`Standard`] (see the //! documentation in the [`uniform`] module. Doing so enables generation of //! values of type `T` with [`Rng::gen_range`]. //! //! ## Open and half-open ranges //! //! There are surprisingly many ways to uniformly generate random floats. A //! range between 0 and 1 is standard, but the exact bounds (open vs closed) //! and accuracy differ. In addition to the [`Standard`] distribution Rand offers //! [`Open01`] and [`OpenClosed01`]. See "Floating point implementation" section of //! [`Standard`] documentation for more details. //! //! # Non-uniform sampling //! //! Sampling a simple true/false outcome with a given probability has a name: //! the [`Bernoulli`] distribution (this is used by [`Rng::gen_bool`]). //! //! For weighted sampling from a sequence of discrete values, use the //! [`weighted`] module. //! //! This crate no longer includes other non-uniform distributions; instead //! it is recommended that you use either [`rand_distr`] or [`statrs`]. //! //! //! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution //! [`rand_distr`]: https://crates.io/crates/rand_distr //! [`statrs`]: https://crates.io/crates/statrs //! [`Alphanumeric`]: distributions::Alphanumeric //! [`Bernoulli`]: distributions::Bernoulli //! [`Open01`]: distributions::Open01 //! [`OpenClosed01`]: distributions::OpenClosed01 //! [`Standard`]: distributions::Standard //! [`Uniform`]: distributions::Uniform //! [`Uniform::new`]: distributions::Uniform::new //! [`Uniform::new_inclusive`]: distributions::Uniform::new_inclusive //! [`weighted`]: distributions::weighted //! [`rand_distr`]: https://crates.io/crates/rand_distr //! [`statrs`]: https://crates.io/crates/statrs use core::iter; use crate::Rng; pub use self::other::Alphanumeric; #[doc(inline)] pub use self::uniform::Uniform; pub use self::float::{OpenClosed01, Open01}; pub use self::bernoulli::{Bernoulli, BernoulliError}; #[cfg(feature="alloc")] pub use self::weighted::{WeightedIndex, WeightedError}; // The following are all deprecated after being moved to rand_distr #[allow(deprecated)] #[cfg(feature="std")] pub use self::unit_sphere::UnitSphereSurface; #[allow(deprecated)] #[cfg(feature="std")] pub use self::unit_circle::UnitCircle; #[allow(deprecated)] #[cfg(feature="std")] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT, Beta}; #[allow(deprecated)] #[cfg(feature="std")] pub use self::normal::{Normal, LogNormal, StandardNormal}; #[allow(deprecated)] #[cfg(feature="std")] pub use self::exponential::{Exp, Exp1}; #[allow(deprecated)] #[cfg(feature="std")] pub use self::pareto::Pareto; #[allow(deprecated)] #[cfg(feature="std")] pub use self::poisson::Poisson; #[allow(deprecated)] #[cfg(feature="std")] pub use self::binomial::Binomial; #[allow(deprecated)] #[cfg(feature="std")] pub use self::cauchy::Cauchy; #[allow(deprecated)] #[cfg(feature="std")] pub use self::dirichlet::Dirichlet; #[allow(deprecated)] #[cfg(feature="std")] pub use self::triangular::Triangular; #[allow(deprecated)] #[cfg(feature="std")] pub use self::weibull::Weibull; pub mod uniform; mod bernoulli; #[cfg(feature="alloc")] pub mod weighted; #[cfg(feature="std")] mod unit_sphere; #[cfg(feature="std")] mod unit_circle; #[cfg(feature="std")] mod gamma; #[cfg(feature="std")] mod normal; #[cfg(feature="std")] mod exponential; #[cfg(feature="std")] mod pareto; #[cfg(feature="std")] mod poisson; #[cfg(feature="std")] mod binomial; #[cfg(feature="std")] mod cauchy; #[cfg(feature="std")] mod dirichlet; #[cfg(feature="std")] mod triangular; #[cfg(feature="std")] mod weibull; mod float; #[doc(hidden)] pub mod hidden_export { pub use super::float::IntoFloat; // used by rand_distr } mod integer; mod other; mod utils; #[cfg(feature="std")] mod ziggurat_tables; /// Types (distributions) that can be used to create a random instance of `T`. /// /// It is possible to sample from a distribution through both the /// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and /// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which /// produces an iterator that samples from the distribution. /// /// All implementations are expected to be immutable; this has the significant /// advantage of not needing to consider thread safety, and for most /// distributions efficient state-less sampling algorithms are available. /// /// Implementations are typically expected to be portable with reproducible /// results when used with a PRNG with fixed seed; see the /// [portability chapter](https://rust-random.github.io/book/portability.html) /// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize` /// type requires different sampling on 32-bit and 64-bit machines. /// /// [`sample_iter`]: Distribution::method.sample_iter pub trait Distribution { /// Generate a random value of `T`, using `rng` as the source of randomness. fn sample(&self, rng: &mut R) -> T; /// Create an iterator that generates random values of `T`, using `rng` as /// the source of randomness. /// /// Note that this function takes `self` by value. This works since /// `Distribution` is impl'd for `&D` where `D: Distribution`, /// however borrowing is not automatic hence `distr.sample_iter(...)` may /// need to be replaced with `(&distr).sample_iter(...)` to borrow or /// `(&*distr).sample_iter(...)` to reborrow an existing reference. /// /// # Example /// /// ``` /// use rand::thread_rng; /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard}; /// /// let rng = thread_rng(); /// /// // Vec of 16 x f32: /// let v: Vec = Standard.sample_iter(rng).take(16).collect(); /// /// // String: /// let s: String = Alphanumeric.sample_iter(rng).take(7).collect(); /// /// // Dice-rolling: /// let die_range = Uniform::new_inclusive(1, 6); /// let mut roll_die = die_range.sample_iter(rng); /// while roll_die.next().unwrap() != 6 { /// println!("Not a 6; rolling again!"); /// } /// ``` fn sample_iter(self, rng: R) -> DistIter where R: Rng, Self: Sized { DistIter { distr: self, rng, phantom: ::core::marker::PhantomData, } } } impl<'a, T, D: Distribution> Distribution for &'a D { fn sample(&self, rng: &mut R) -> T { (*self).sample(rng) } } /// An iterator that generates random values of `T` with distribution `D`, /// using `R` as the source of randomness. /// /// This `struct` is created by the [`sample_iter`] method on [`Distribution`]. /// See its documentation for more. /// /// [`sample_iter`]: Distribution::sample_iter #[derive(Debug)] pub struct DistIter { distr: D, rng: R, phantom: ::core::marker::PhantomData, } impl Iterator for DistIter where D: Distribution, R: Rng { type Item = T; #[inline(always)] fn next(&mut self) -> Option { // Here, self.rng may be a reference, but we must take &mut anyway. // Even if sample could take an R: Rng by value, we would need to do this // since Rng is not copyable and we cannot enforce that this is "reborrowable". Some(self.distr.sample(&mut self.rng)) } fn size_hint(&self) -> (usize, Option) { (usize::max_value(), None) } } impl iter::FusedIterator for DistIter where D: Distribution, R: Rng {} #[cfg(features = "nightly")] impl iter::TrustedLen for DistIter where D: Distribution, R: Rng {} /// A generic random value distribution, implemented for many primitive types. /// Usually generates values with a numerically uniform distribution, and with a /// range appropriate to the type. /// /// ## Provided implementations /// /// Assuming the provided `Rng` is well-behaved, these implementations /// generate values with the following ranges and distributions: /// /// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed /// over all values of the type. /// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all /// code points in the range `0...0x10_FFFF`, except for the range /// `0xD800...0xDFFF` (the surrogate code points). This includes /// unassigned/reserved code points. /// * `bool`: Generates `false` or `true`, each with probability 0.5. /// * Floating point types (`f32` and `f64`): Uniformly distributed in the /// half-open range `[0, 1)`. See notes below. /// * Wrapping integers (`Wrapping`), besides the type identical to their /// normal integer variants. /// /// The `Standard` distribution also supports generation of the following /// compound types where all component types are supported: /// /// * Tuples (up to 12 elements): each element is generated sequentially. /// * Arrays (up to 32 elements): each element is generated sequentially; /// see also [`Rng::fill`] which supports arbitrary array length for integer /// types and tends to be faster for `u32` and smaller types. /// * `Option` first generates a `bool`, and if true generates and returns /// `Some(value)` where `value: T`, otherwise returning `None`. /// /// ## Custom implementations /// /// The [`Standard`] distribution may be implemented for user types as follows: /// /// ``` /// # #![allow(dead_code)] /// use rand::Rng; /// use rand::distributions::{Distribution, Standard}; /// /// struct MyF32 { /// x: f32, /// } /// /// impl Distribution for Standard { /// fn sample(&self, rng: &mut R) -> MyF32 { /// MyF32 { x: rng.gen() } /// } /// } /// ``` /// /// ## Example usage /// ``` /// use rand::prelude::*; /// use rand::distributions::Standard; /// /// let val: f32 = StdRng::from_entropy().sample(Standard); /// println!("f32 from [0, 1): {}", val); /// ``` /// /// # Floating point implementation /// The floating point implementations for `Standard` generate a random value in /// the half-open interval `[0, 1)`, i.e. including 0 but not 1. /// /// All values that can be generated are of the form `n * Ξ΅/2`. For `f32` /// the 23 most significant random bits of a `u32` are used and for `f64` the /// 53 most significant bits of a `u64` are used. The conversion uses the /// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (Ξ΅/2)`. /// /// See also: [`Open01`] which samples from `(0, 1)`, [`OpenClosed01`] which /// samples from `(0, 1]` and `Rng::gen_range(0, 1)` which also samples from /// `[0, 1)`. Note that `Open01` and `gen_range` (which uses [`Uniform`]) use /// transmute-based methods which yield 1 bit less precision but may perform /// faster on some architectures (on modern Intel CPUs all methods have /// approximately equal performance). /// /// [`Uniform`]: uniform::Uniform #[derive(Clone, Copy, Debug)] pub struct Standard; #[cfg(all(test, feature = "std"))] mod tests { use crate::Rng; use super::{Distribution, Uniform}; #[test] fn test_distributions_iter() { use crate::distributions::Open01; let mut rng = crate::test::rng(210); let distr = Open01; let results: Vec = distr.sample_iter(&mut rng).take(100).collect(); println!("{:?}", results); } #[test] fn test_make_an_iter() { fn ten_dice_rolls_other_than_five<'a, R: Rng>(rng: &'a mut R) -> impl Iterator + 'a { Uniform::new_inclusive(1, 6) .sample_iter(rng) .filter(|x| *x != 5) .take(10) } let mut rng = crate::test::rng(211); let mut count = 0; for val in ten_dice_rolls_other_than_five(&mut rng) { assert!(val >= 1 && val <= 6 && val != 5); count += 1; } assert_eq!(count, 10); } } rand-0.7.2/src/distributions/normal.rs010064400017500001750000000116611352222772600162310ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The normal and derived distributions. #![allow(deprecated)] use crate::Rng; use crate::distributions::{ziggurat_tables, Distribution, Open01}; use crate::distributions::utils::ziggurat; /// Samples floating-point numbers according to the normal distribution /// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to /// `Normal::new(0.0, 1.0)` but faster. /// /// See `Normal` for the general normal distribution. /// /// Implemented via the ZIGNOR variant[^1] of the Ziggurat method. /// /// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to /// Generate Normal Random Samples*]( /// https://www.doornik.com/research/ziggurat.pdf). /// Nuffield College, Oxford #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct StandardNormal; impl Distribution for StandardNormal { fn sample(&self, rng: &mut R) -> f64 { #[inline] fn pdf(x: f64) -> f64 { (-x*x/2.0).exp() } #[inline] fn zero_case(rng: &mut R, u: f64) -> f64 { // compute a random number in the tail by hand // strange initial conditions, because the loop is not // do-while, so the condition should be true on the first // run, they get overwritten anyway (0 < 1, so these are // good). let mut x = 1.0f64; let mut y = 0.0f64; while -2.0 * y < x * x { let x_: f64 = rng.sample(Open01); let y_: f64 = rng.sample(Open01); x = x_.ln() / ziggurat_tables::ZIG_NORM_R; y = y_.ln(); } if u < 0.0 { x - ziggurat_tables::ZIG_NORM_R } else { ziggurat_tables::ZIG_NORM_R - x } } ziggurat(rng, true, // this is symmetric &ziggurat_tables::ZIG_NORM_X, &ziggurat_tables::ZIG_NORM_F, pdf, zero_case) } } /// The normal distribution `N(mean, std_dev**2)`. /// /// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`] /// for more details. /// /// Note that [`StandardNormal`] is an optimised implementation for mean 0, and /// standard deviation 1. /// /// [`StandardNormal`]: crate::distributions::StandardNormal #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Normal { mean: f64, std_dev: f64, } impl Normal { /// Construct a new `Normal` distribution with the given mean and /// standard deviation. /// /// # Panics /// /// Panics if `std_dev < 0`. #[inline] pub fn new(mean: f64, std_dev: f64) -> Normal { assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0"); Normal { mean, std_dev } } } impl Distribution for Normal { fn sample(&self, rng: &mut R) -> f64 { let n = rng.sample(StandardNormal); self.mean + self.std_dev * n } } /// The log-normal distribution `ln N(mean, std_dev**2)`. /// /// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)` /// distributed. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct LogNormal { norm: Normal } impl LogNormal { /// Construct a new `LogNormal` distribution with the given mean /// and standard deviation. /// /// # Panics /// /// Panics if `std_dev < 0`. #[inline] pub fn new(mean: f64, std_dev: f64) -> LogNormal { assert!(std_dev >= 0.0, "LogNormal::new called with `std_dev` < 0"); LogNormal { norm: Normal::new(mean, std_dev) } } } impl Distribution for LogNormal { fn sample(&self, rng: &mut R) -> f64 { self.norm.sample(rng).exp() } } #[cfg(test)] mod tests { use crate::distributions::Distribution; use super::{Normal, LogNormal}; #[test] fn test_normal() { let norm = Normal::new(10.0, 10.0); let mut rng = crate::test::rng(210); for _ in 0..1000 { norm.sample(&mut rng); } } #[test] #[should_panic] fn test_normal_invalid_sd() { Normal::new(10.0, -1.0); } #[test] fn test_log_normal() { let lnorm = LogNormal::new(10.0, 10.0); let mut rng = crate::test::rng(211); for _ in 0..1000 { lnorm.sample(&mut rng); } } #[test] #[should_panic] fn test_log_normal_invalid_sd() { LogNormal::new(10.0, -1.0); } } rand-0.7.2/src/distributions/other.rs010064400017500001750000000205571353743213700160660ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The implementations of the `Standard` distribution for other built-in types. use core::char; use core::num::Wrapping; use crate::Rng; use crate::distributions::{Distribution, Standard, Uniform}; // ----- Sampling distributions ----- /// Sample a `char`, uniformly distributed over ASCII letters and numbers: /// a-z, A-Z and 0-9. /// /// # Example /// /// ``` /// use std::iter; /// use rand::{Rng, thread_rng}; /// use rand::distributions::Alphanumeric; /// /// let mut rng = thread_rng(); /// let chars: String = iter::repeat(()) /// .map(|()| rng.sample(Alphanumeric)) /// .take(7) /// .collect(); /// println!("Random chars: {}", chars); /// ``` #[derive(Debug)] pub struct Alphanumeric; // ----- Implementations of distributions ----- impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> char { // A valid `char` is either in the interval `[0, 0xD800)` or // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is // reserved for surrogates. This is the size of that gap. const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1; // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it // seemed slower. let range = Uniform::new(GAP_SIZE, 0x11_0000); let mut n = range.sample(rng); if n <= 0xDFFF { n -= GAP_SIZE; } unsafe { char::from_u32_unchecked(n) } } } impl Distribution for Alphanumeric { fn sample(&self, rng: &mut R) -> char { const RANGE: u32 = 26 + 26 + 10; const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789"; // We can pick from 62 characters. This is so close to a power of 2, 64, // that we can do better than `Uniform`. Use a simple bitshift and // rejection sampling. We do not use a bitmask, because for small RNGs // the most significant bits are usually of higher quality. loop { let var = rng.next_u32() >> (32 - 6); if var < RANGE { return GEN_ASCII_STR_CHARSET[var as usize] as char } } } } impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> bool { // We can compare against an arbitrary bit of an u32 to get a bool. // Because the least significant bits of a lower quality RNG can have // simple patterns, we compare against the most significant bit. This is // easiest done using a sign test. (rng.next_u32() as i32) < 0 } } macro_rules! tuple_impl { // use variables to indicate the arity of the tuple ($($tyvar:ident),* ) => { // the trailing commas are for the 1 tuple impl< $( $tyvar ),* > Distribution<( $( $tyvar ),* , )> for Standard where $( Standard: Distribution<$tyvar> ),* { #[inline] fn sample(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) { ( // use the $tyvar's to get the appropriate number of // repeats (they're not actually needed) $( _rng.gen::<$tyvar>() ),* , ) } } } } impl Distribution<()> for Standard { #[allow(clippy::unused_unit)] #[inline] fn sample(&self, _: &mut R) -> () { () } } tuple_impl!{A} tuple_impl!{A, B} tuple_impl!{A, B, C} tuple_impl!{A, B, C, D} tuple_impl!{A, B, C, D, E} tuple_impl!{A, B, C, D, E, F} tuple_impl!{A, B, C, D, E, F, G} tuple_impl!{A, B, C, D, E, F, G, H} tuple_impl!{A, B, C, D, E, F, G, H, I} tuple_impl!{A, B, C, D, E, F, G, H, I, J} tuple_impl!{A, B, C, D, E, F, G, H, I, J, K} tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L} macro_rules! array_impl { // recursive, given at least one type parameter: {$n:expr, $t:ident, $($ts:ident,)*} => { array_impl!{($n - 1), $($ts,)*} impl Distribution<[T; $n]> for Standard where Standard: Distribution { #[inline] fn sample(&self, _rng: &mut R) -> [T; $n] { [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] } } }; // empty case: {$n:expr,} => { impl Distribution<[T; $n]> for Standard { fn sample(&self, _rng: &mut R) -> [T; $n] { [] } } }; } array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,} impl Distribution> for Standard where Standard: Distribution { #[inline] fn sample(&self, rng: &mut R) -> Option { // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066 if rng.gen::() { Some(rng.gen()) } else { None } } } impl Distribution> for Standard where Standard: Distribution { #[inline] fn sample(&self, rng: &mut R) -> Wrapping { Wrapping(rng.gen()) } } #[cfg(test)] mod tests { use super::*; use crate::RngCore; #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String; #[test] fn test_misc() { let rng: &mut dyn RngCore = &mut crate::test::rng(820); rng.sample::(Standard); rng.sample::(Standard); } #[cfg(feature="alloc")] #[test] fn test_chars() { use core::iter; let mut rng = crate::test::rng(805); // Test by generating a relatively large number of chars, so we also // take the rejection sampling path. let word: String = iter::repeat(()) .map(|()| rng.gen::()).take(1000).collect(); assert!(word.len() != 0); } #[test] fn test_alphanumeric() { let mut rng = crate::test::rng(806); // Test by generating a relatively large number of chars, so we also // take the rejection sampling path. let mut incorrect = false; for _ in 0..100 { let c = rng.sample(Alphanumeric); incorrect |= !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ); } assert!(incorrect == false); } #[test] fn value_stability() { fn test_samples>( distr: &D, zero: T, expected: &[T]) { let mut rng = crate::test::rng(807); let mut buf = [zero; 5]; for x in &mut buf { *x = rng.sample(&distr); } assert_eq!(&buf, expected); } test_samples(&Standard, 'a', &['\u{8cdac}', '\u{a346a}', '\u{80120}', '\u{ed692}', '\u{35888}']); test_samples(&Alphanumeric, 'a', &['h', 'm', 'e', '3', 'M']); test_samples(&Standard, false, &[true, true, false, true, false]); test_samples(&Standard, None as Option, &[Some(true), None, Some(false), None, Some(false)]); test_samples(&Standard, Wrapping(0i32), &[Wrapping(-2074640887), Wrapping(-1719949321), Wrapping(2018088303), Wrapping(-547181756), Wrapping(838957336)]); // We test only sub-sets of tuple and array impls test_samples(&Standard, (), &[(), (), (), (), ()]); test_samples(&Standard, (false,), &[(true,), (true,), (false,), (true,), (false,)]); test_samples(&Standard, (false,false), &[(true,true), (false,true), (false,false), (true,false), (false,false)]); test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]); test_samples(&Standard, [0u8; 3], &[[9, 247, 111], [68, 24, 13], [174, 19, 194], [172, 69, 213], [149, 207, 29]]); } } rand-0.7.2/src/distributions/pareto.rs010064400017500001750000000034671352222772600162400ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The Pareto distribution. #![allow(deprecated)] use crate::Rng; use crate::distributions::{Distribution, OpenClosed01}; /// Samples floating-point numbers according to the Pareto distribution #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Pareto { scale: f64, inv_neg_shape: f64, } impl Pareto { /// Construct a new Pareto distribution with given `scale` and `shape`. /// /// In the literature, `scale` is commonly written as xm or k and /// `shape` is often written as Ξ±. /// /// # Panics /// /// `scale` and `shape` have to be non-zero and positive. pub fn new(scale: f64, shape: f64) -> Pareto { assert!((scale > 0.) & (shape > 0.)); Pareto { scale, inv_neg_shape: -1.0 / shape } } } impl Distribution for Pareto { fn sample(&self, rng: &mut R) -> f64 { let u: f64 = rng.sample(OpenClosed01); self.scale * u.powf(self.inv_neg_shape) } } #[cfg(test)] mod tests { use crate::distributions::Distribution; use super::Pareto; #[test] #[should_panic] fn invalid() { Pareto::new(0., 0.); } #[test] fn sample() { let scale = 1.0; let shape = 2.0; let d = Pareto::new(scale, shape); let mut rng = crate::test::rng(1); for _ in 0..1000 { let r = d.sample(&mut rng); assert!(r >= scale); } } } rand-0.7.2/src/distributions/poisson.rs010064400017500001750000000120161352222772600164260ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2016-2017 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The Poisson distribution. #![allow(deprecated)] use crate::Rng; use crate::distributions::{Distribution, Cauchy}; use crate::distributions::utils::log_gamma; /// The Poisson distribution `Poisson(lambda)`. /// /// This distribution has a density function: /// `f(k) = lambda^k * exp(-lambda) / k!` for `k >= 0`. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Poisson { lambda: f64, // precalculated values exp_lambda: f64, log_lambda: f64, sqrt_2lambda: f64, magic_val: f64, } impl Poisson { /// Construct a new `Poisson` with the given shape parameter /// `lambda`. Panics if `lambda <= 0`. pub fn new(lambda: f64) -> Poisson { assert!(lambda > 0.0, "Poisson::new called with lambda <= 0"); let log_lambda = lambda.ln(); Poisson { lambda, exp_lambda: (-lambda).exp(), log_lambda, sqrt_2lambda: (2.0 * lambda).sqrt(), magic_val: lambda * log_lambda - log_gamma(1.0 + lambda), } } } impl Distribution for Poisson { fn sample(&self, rng: &mut R) -> u64 { // using the algorithm from Numerical Recipes in C // for low expected values use the Knuth method if self.lambda < 12.0 { let mut result = 0; let mut p = 1.0; while p > self.exp_lambda { p *= rng.gen::(); result += 1; } result - 1 } // high expected values - rejection method else { let mut int_result: u64; // we use the Cauchy distribution as the comparison distribution // f(x) ~ 1/(1+x^2) let cauchy = Cauchy::new(0.0, 1.0); loop { let mut result; let mut comp_dev; loop { // draw from the Cauchy distribution comp_dev = rng.sample(cauchy); // shift the peak of the comparison ditribution result = self.sqrt_2lambda * comp_dev + self.lambda; // repeat the drawing until we are in the range of possible values if result >= 0.0 { break; } } // now the result is a random variable greater than 0 with Cauchy distribution // the result should be an integer value result = result.floor(); int_result = result as u64; // this is the ratio of the Poisson distribution to the comparison distribution // the magic value scales the distribution function to a range of approximately 0-1 // since it is not exact, we multiply the ratio by 0.9 to avoid ratios greater than 1 // this doesn't change the resulting distribution, only increases the rate of failed drawings let check = 0.9 * (1.0 + comp_dev * comp_dev) * (result * self.log_lambda - log_gamma(1.0 + result) - self.magic_val).exp(); // check with uniform random value - if below the threshold, we are within the target distribution if rng.gen::() <= check { break; } } int_result } } } #[cfg(test)] mod test { use crate::distributions::Distribution; use super::Poisson; #[test] #[cfg(not(miri))] // Miri is too slow fn test_poisson_10() { let poisson = Poisson::new(10.0); let mut rng = crate::test::rng(123); let mut sum = 0; for _ in 0..1000 { sum += poisson.sample(&mut rng); } let avg = (sum as f64) / 1000.0; println!("Poisson average: {}", avg); assert!((avg - 10.0).abs() < 0.5); // not 100% certain, but probable enough } #[test] #[cfg(not(miri))] // Miri doesn't support transcendental functions fn test_poisson_15() { // Take the 'high expected values' path let poisson = Poisson::new(15.0); let mut rng = crate::test::rng(123); let mut sum = 0; for _ in 0..1000 { sum += poisson.sample(&mut rng); } let avg = (sum as f64) / 1000.0; println!("Poisson average: {}", avg); assert!((avg - 15.0).abs() < 0.5); // not 100% certain, but probable enough } #[test] #[should_panic] fn test_poisson_invalid_lambda_zero() { Poisson::new(0.0); } #[test] #[should_panic] fn test_poisson_invalid_lambda_neg() { Poisson::new(-10.0); } } rand-0.7.2/src/distributions/triangular.rs010064400017500001750000000042651352222772600171130ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The triangular distribution. #![allow(deprecated)] use crate::Rng; use crate::distributions::{Distribution, Standard}; /// The triangular distribution. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Triangular { min: f64, max: f64, mode: f64, } impl Triangular { /// Construct a new `Triangular` with minimum `min`, maximum `max` and mode /// `mode`. /// /// # Panics /// /// If `max < mode`, `mode < max` or `max == min`. /// #[inline] pub fn new(min: f64, max: f64, mode: f64) -> Triangular { assert!(max >= mode); assert!(mode >= min); assert!(max != min); Triangular { min, max, mode } } } impl Distribution for Triangular { #[inline] fn sample(&self, rng: &mut R) -> f64 { let f: f64 = rng.sample(Standard); let diff_mode_min = self.mode - self.min; let diff_max_min = self.max - self.min; if f * diff_max_min < diff_mode_min { self.min + (f * diff_max_min * diff_mode_min).sqrt() } else { self.max - ((1. - f) * diff_max_min * (self.max - self.mode)).sqrt() } } } #[cfg(test)] mod test { use crate::distributions::Distribution; use super::Triangular; #[test] fn test_new() { for &(min, max, mode) in &[ (-1., 1., 0.), (1., 2., 1.), (5., 25., 25.), (1e-5, 1e5, 1e-3), (0., 1., 0.9), (-4., -0.5, -2.), (-13.039, 8.41, 1.17), ] { println!("{} {} {}", min, max, mode); let _ = Triangular::new(min, max, mode); } } #[test] fn test_sample() { let norm = Triangular::new(0., 1., 0.5); let mut rng = crate::test::rng(1); for _ in 0..1000 { norm.sample(&mut rng); } } } rand-0.7.2/src/distributions/uniform.rs010064400017500001750000001454561353742023100164220ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2017 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A distribution uniformly sampling numbers within a given range. //! //! [`Uniform`] is the standard distribution to sample uniformly from a range; //! e.g. `Uniform::new_inclusive(1, 6)` can sample integers from 1 to 6, like a //! standard die. [`Rng::gen_range`] supports any type supported by //! [`Uniform`]. //! //! This distribution is provided with support for several primitive types //! (all integer and floating-point types) as well as [`std::time::Duration`], //! and supports extension to user-defined types via a type-specific *back-end* //! implementation. //! //! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the //! back-ends supporting sampling from primitive integer and floating-point //! ranges as well as from [`std::time::Duration`]; these types do not normally //! need to be used directly (unless implementing a derived back-end). //! //! # Example usage //! //! ``` //! use rand::{Rng, thread_rng}; //! use rand::distributions::Uniform; //! //! let mut rng = thread_rng(); //! let side = Uniform::new(-10.0, 10.0); //! //! // sample between 1 and 10 points //! for _ in 0..rng.gen_range(1, 11) { //! // sample a point from the square with sides -10 - 10 in two dimensions //! let (x, y) = (rng.sample(side), rng.sample(side)); //! println!("Point: {}, {}", x, y); //! } //! ``` //! //! # Extending `Uniform` to support a custom type //! //! To extend [`Uniform`] to support your own types, write a back-end which //! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`] //! helper trait to "register" your back-end. See the `MyF32` example below. //! //! At a minimum, the back-end needs to store any parameters needed for sampling //! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`. //! Those methods should include an assert to check the range is valid (i.e. //! `low < high`). The example below merely wraps another back-end. //! //! The `new`, `new_inclusive` and `sample_single` functions use arguments of //! type SampleBorrow in order to support passing in values by reference or //! by value. In the implementation of these functions, you can choose to //! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose //! to copy or clone the value, whatever is appropriate for your type. //! //! ``` //! use rand::prelude::*; //! use rand::distributions::uniform::{Uniform, SampleUniform, //! UniformSampler, UniformFloat, SampleBorrow}; //! //! struct MyF32(f32); //! //! #[derive(Clone, Copy, Debug)] //! struct UniformMyF32(UniformFloat); //! //! impl UniformSampler for UniformMyF32 { //! type X = MyF32; //! fn new(low: B1, high: B2) -> Self //! where B1: SampleBorrow + Sized, //! B2: SampleBorrow + Sized //! { //! UniformMyF32(UniformFloat::::new(low.borrow().0, high.borrow().0)) //! } //! fn new_inclusive(low: B1, high: B2) -> Self //! where B1: SampleBorrow + Sized, //! B2: SampleBorrow + Sized //! { //! UniformSampler::new(low, high) //! } //! fn sample(&self, rng: &mut R) -> Self::X { //! MyF32(self.0.sample(rng)) //! } //! } //! //! impl SampleUniform for MyF32 { //! type Sampler = UniformMyF32; //! } //! //! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32)); //! let uniform = Uniform::new(low, high); //! let x = uniform.sample(&mut thread_rng()); //! ``` //! //! [`SampleUniform`]: crate::distributions::uniform::SampleUniform //! [`UniformSampler`]: crate::distributions::uniform::UniformSampler //! [`UniformInt`]: crate::distributions::uniform::UniformInt //! [`UniformFloat`]: crate::distributions::uniform::UniformFloat //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow #[cfg(feature = "std")] use std::time::Duration; #[cfg(not(feature = "std"))] use core::time::Duration; use crate::Rng; use crate::distributions::Distribution; use crate::distributions::float::IntoFloat; use crate::distributions::utils::{WideningMultiply, FloatSIMDUtils, FloatAsSIMD, BoolAsSIMD}; #[cfg(not(feature = "std"))] #[allow(unused_imports)] // rustc doesn't detect that this is actually used use crate::distributions::utils::Float; #[cfg(feature="simd_support")] use packed_simd::*; /// Sample values uniformly between two bounds. /// /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform /// distribution sampling from the given range; these functions may do extra /// work up front to make sampling of multiple values faster. /// /// When sampling from a constant range, many calculations can happen at /// compile-time and all methods should be fast; for floating-point ranges and /// the full range of integer types this should have comparable performance to /// the `Standard` distribution. /// /// Steps are taken to avoid bias which might be present in naive /// implementations; for example `rng.gen::() % 170` samples from the range /// `[0, 169]` but is twice as likely to select numbers less than 85 than other /// values. Further, the implementations here give more weight to the high-bits /// generated by the RNG than the low bits, since with some RNGs the low-bits /// are of lower quality than the high bits. /// /// Implementations must sample in `[low, high)` range for /// `Uniform::new(low, high)`, i.e., excluding `high`. In particular care must /// be taken to ensure that rounding never results values `< low` or `>= high`. /// /// # Example /// /// ``` /// use rand::distributions::{Distribution, Uniform}; /// /// fn main() { /// let between = Uniform::from(10..10000); /// let mut rng = rand::thread_rng(); /// let mut sum = 0; /// for _ in 0..1000 { /// sum += between.sample(&mut rng); /// } /// println!("{}", sum); /// } /// ``` /// /// [`new`]: Uniform::new /// [`new_inclusive`]: Uniform::new_inclusive #[derive(Clone, Copy, Debug)] pub struct Uniform(X::Sampler); impl Uniform { /// Create a new `Uniform` instance which samples uniformly from the half /// open range `[low, high)` (excluding `high`). Panics if `low >= high`. pub fn new(low: B1, high: B2) -> Uniform where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { Uniform(X::Sampler::new(low, high)) } /// Create a new `Uniform` instance which samples uniformly from the closed /// range `[low, high]` (inclusive). Panics if `low > high`. pub fn new_inclusive(low: B1, high: B2) -> Uniform where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { Uniform(X::Sampler::new_inclusive(low, high)) } } impl Distribution for Uniform { fn sample(&self, rng: &mut R) -> X { self.0.sample(rng) } } /// Helper trait for creating objects using the correct implementation of /// [`UniformSampler`] for the sampling type. /// /// See the [module documentation] on how to implement [`Uniform`] range /// sampling for a custom type. /// /// [module documentation]: crate::distributions::uniform pub trait SampleUniform: Sized { /// The `UniformSampler` implementation supporting type `X`. type Sampler: UniformSampler; } /// Helper trait handling actual uniform sampling. /// /// See the [module documentation] on how to implement [`Uniform`] range /// sampling for a custom type. /// /// Implementation of [`sample_single`] is optional, and is only useful when /// the implementation can be faster than `Self::new(low, high).sample(rng)`. /// /// [module documentation]: crate::distributions::uniform /// [`sample_single`]: UniformSampler::sample_single pub trait UniformSampler: Sized { /// The type sampled by this implementation. type X; /// Construct self, with inclusive lower bound and exclusive upper bound /// `[low, high)`. /// /// Usually users should not call this directly but instead use /// `Uniform::new`, which asserts that `low < high` before calling this. fn new(low: B1, high: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized; /// Construct self, with inclusive bounds `[low, high]`. /// /// Usually users should not call this directly but instead use /// `Uniform::new_inclusive`, which asserts that `low <= high` before /// calling this. fn new_inclusive(low: B1, high: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized; /// Sample a value. fn sample(&self, rng: &mut R) -> Self::X; /// Sample a single value uniformly from a range with inclusive lower bound /// and exclusive upper bound `[low, high)`. /// /// By default this is implemented using /// `UniformSampler::new(low, high).sample(rng)`. However, for some types /// more optimal implementations for single usage may be provided via this /// method (which is the case for integers and floats). /// Results may not be identical. /// /// Note that to use this method in a generic context, the type needs to be /// retrieved via `SampleUniform::Sampler` as follows: /// ``` /// use rand::{thread_rng, distributions::uniform::{SampleUniform, UniformSampler}}; /// # #[allow(unused)] /// fn sample_from_range(lb: T, ub: T) -> T { /// let mut rng = thread_rng(); /// ::Sampler::sample_single(lb, ub, &mut rng) /// } /// ``` fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let uniform: Self = UniformSampler::new(low, high); uniform.sample(rng) } } impl From<::core::ops::Range> for Uniform { fn from(r: ::core::ops::Range) -> Uniform { Uniform::new(r.start, r.end) } } impl From<::core::ops::RangeInclusive> for Uniform { fn from(r: ::core::ops::RangeInclusive) -> Uniform { Uniform::new_inclusive(r.start(), r.end()) } } /// Helper trait similar to [`Borrow`] but implemented /// only for SampleUniform and references to SampleUniform in /// order to resolve ambiguity issues. /// /// [`Borrow`]: std::borrow::Borrow pub trait SampleBorrow { /// Immutably borrows from an owned value. See [`Borrow::borrow`] /// /// [`Borrow::borrow`]: std::borrow::Borrow::borrow fn borrow(&self) -> &Borrowed; } impl SampleBorrow for Borrowed where Borrowed: SampleUniform { #[inline(always)] fn borrow(&self) -> &Borrowed { self } } impl<'a, Borrowed> SampleBorrow for &'a Borrowed where Borrowed: SampleUniform { #[inline(always)] fn borrow(&self) -> &Borrowed { *self } } //////////////////////////////////////////////////////////////////////////////// // What follows are all back-ends. /// The back-end implementing [`UniformSampler`] for integer types. /// /// Unless you are implementing [`UniformSampler`] for your own type, this type /// should not be used directly, use [`Uniform`] instead. /// /// # Implementation notes /// /// For simplicity, we use the same generic struct `UniformInt` for all /// integer types `X`. This gives us only one field type, `X`; to store unsigned /// values of this size, we take use the fact that these conversions are no-ops. /// /// For a closed range, the number of possible numbers we should generate is /// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of /// our sample space, `zone`, is a multiple of `range`; other values must be /// rejected (by replacing with a new random sample). /// /// As a special case, we use `range = 0` to represent the full range of the /// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`). /// /// The optimum `zone` is the largest product of `range` which fits in our /// (unsigned) target type. We calculate this by calculating how many numbers we /// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large) /// product of `range` will suffice, thus in `sample_single` we multiply by a /// power of 2 via bit-shifting (faster but may cause more rejections). /// /// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we /// use `u32` for our `zone` and samples (because it's not slower and because /// it reduces the chance of having to reject a sample). In this case we cannot /// store `zone` in the target type since it is too large, however we know /// `ints_to_reject < range <= $unsigned::MAX`. /// /// An alternative to using a modulus is widening multiply: After a widening /// multiply by `range`, the result is in the high word. Then comparing the low /// word against `zone` makes sure our distribution is uniform. #[derive(Clone, Copy, Debug)] pub struct UniformInt { low: X, range: X, z: X, // either ints_to_reject or zone depending on implementation } macro_rules! uniform_int_impl { ($ty:ty, $unsigned:ident, $u_large:ident) => { impl SampleUniform for $ty { type Sampler = UniformInt<$ty>; } impl UniformSampler for UniformInt<$ty> { // We play free and fast with unsigned vs signed here // (when $ty is signed), but that's fine, since the // contract of this macro is for $ty and $unsigned to be // "bit-equal", so casting between them is a no-op. type X = $ty; #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low < high, "Uniform::new called with `low >= high`"); UniformSampler::new_inclusive(low, high - 1) } #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new_inclusive(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); let unsigned_max = ::core::$u_large::MAX; let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned; let ints_to_reject = if range > 0 { let range = $u_large::from(range); (unsigned_max - range + 1) % range } else { 0 }; UniformInt { low: low, // These are really $unsigned values, but store as $ty: range: range as $ty, z: ints_to_reject as $unsigned as $ty } } fn sample(&self, rng: &mut R) -> Self::X { let range = self.range as $unsigned as $u_large; if range > 0 { let unsigned_max = ::core::$u_large::MAX; let zone = unsigned_max - (self.z as $unsigned as $u_large); loop { let v: $u_large = rng.gen(); let (hi, lo) = v.wmul(range); if lo <= zone { return self.low.wrapping_add(hi as $ty); } } } else { // Sample from the entire integer range. rng.gen() } } fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Self::X where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low < high, "UniformSampler::sample_single: low >= high"); let range = high.wrapping_sub(low) as $unsigned as $u_large; let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned { // Using a modulus is faster than the approximation for // i8 and i16. I suppose we trade the cost of one // modulus for near-perfect branch prediction. let unsigned_max: $u_large = ::core::$u_large::MAX; let ints_to_reject = (unsigned_max - range + 1) % range; unsigned_max - ints_to_reject } else { // conservative but fast approximation. `- 1` is necessary to allow the // same comparison without bias. (range << range.leading_zeros()).wrapping_sub(1) }; loop { let v: $u_large = rng.gen(); let (hi, lo) = v.wmul(range); if lo <= zone { return low.wrapping_add(hi as $ty); } } } } } } uniform_int_impl! { i8, u8, u32 } uniform_int_impl! { i16, u16, u32 } uniform_int_impl! { i32, u32, u32 } uniform_int_impl! { i64, u64, u64 } #[cfg(not(target_os = "emscripten"))] uniform_int_impl! { i128, u128, u128 } uniform_int_impl! { isize, usize, usize } uniform_int_impl! { u8, u8, u32 } uniform_int_impl! { u16, u16, u32 } uniform_int_impl! { u32, u32, u32 } uniform_int_impl! { u64, u64, u64 } uniform_int_impl! { usize, usize, usize } #[cfg(not(target_os = "emscripten"))] uniform_int_impl! { u128, u128, u128 } #[cfg(all(feature = "simd_support", feature = "nightly"))] macro_rules! uniform_simd_int_impl { ($ty:ident, $unsigned:ident, $u_scalar:ident) => { // The "pick the largest zone that can fit in an `u32`" optimization // is less useful here. Multiple lanes complicate things, we don't // know the PRNG's minimal output size, and casting to a larger vector // is generally a bad idea for SIMD performance. The user can still // implement it manually. // TODO: look into `Uniform::::new(0u32, 100)` functionality // perhaps `impl SampleUniform for $u_scalar`? impl SampleUniform for $ty { type Sampler = UniformInt<$ty>; } impl UniformSampler for UniformInt<$ty> { type X = $ty; #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low.lt(high).all(), "Uniform::new called with `low >= high`"); UniformSampler::new_inclusive(low, high - 1) } #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new_inclusive(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low.le(high).all(), "Uniform::new_inclusive called with `low > high`"); let unsigned_max = ::core::$u_scalar::MAX; // NOTE: these may need to be replaced with explicitly // wrapping operations if `packed_simd` changes let range: $unsigned = ((high - low) + 1).cast(); // `% 0` will panic at runtime. let not_full_range = range.gt($unsigned::splat(0)); // replacing 0 with `unsigned_max` allows a faster `select` // with bitwise OR let modulo = not_full_range.select(range, $unsigned::splat(unsigned_max)); // wrapping addition let ints_to_reject = (unsigned_max - range + 1) % modulo; // When `range` is 0, `lo` of `v.wmul(range)` will always be // zero which means only one sample is needed. let zone = unsigned_max - ints_to_reject; UniformInt { low: low, // These are really $unsigned values, but store as $ty: range: range.cast(), z: zone.cast(), } } fn sample(&self, rng: &mut R) -> Self::X { let range: $unsigned = self.range.cast(); let zone: $unsigned = self.z.cast(); // This might seem very slow, generating a whole new // SIMD vector for every sample rejection. For most uses // though, the chance of rejection is small and provides good // general performance. With multiple lanes, that chance is // multiplied. To mitigate this, we replace only the lanes of // the vector which fail, iteratively reducing the chance of // rejection. The replacement method does however add a little // overhead. Benchmarking or calculating probabilities might // reveal contexts where this replacement method is slower. let mut v: $unsigned = rng.gen(); loop { let (hi, lo) = v.wmul(range); let mask = lo.le(zone); if mask.all() { let hi: $ty = hi.cast(); // wrapping addition let result = self.low + hi; // `select` here compiles to a blend operation // When `range.eq(0).none()` the compare and blend // operations are avoided. let v: $ty = v.cast(); return range.gt($unsigned::splat(0)).select(result, v); } // Replace only the failing lanes v = mask.select(v, rng.gen()); } } } }; // bulk implementation ($(($unsigned:ident, $signed:ident),)+ $u_scalar:ident) => { $( uniform_simd_int_impl!($unsigned, $unsigned, $u_scalar); uniform_simd_int_impl!($signed, $unsigned, $u_scalar); )+ }; } #[cfg(all(feature = "simd_support", feature = "nightly"))] uniform_simd_int_impl! { (u64x2, i64x2), (u64x4, i64x4), (u64x8, i64x8), u64 } #[cfg(all(feature = "simd_support", feature = "nightly"))] uniform_simd_int_impl! { (u32x2, i32x2), (u32x4, i32x4), (u32x8, i32x8), (u32x16, i32x16), u32 } #[cfg(all(feature = "simd_support", feature = "nightly"))] uniform_simd_int_impl! { (u16x2, i16x2), (u16x4, i16x4), (u16x8, i16x8), (u16x16, i16x16), (u16x32, i16x32), u16 } #[cfg(all(feature = "simd_support", feature = "nightly"))] uniform_simd_int_impl! { (u8x2, i8x2), (u8x4, i8x4), (u8x8, i8x8), (u8x16, i8x16), (u8x32, i8x32), (u8x64, i8x64), u8 } /// The back-end implementing [`UniformSampler`] for floating-point types. /// /// Unless you are implementing [`UniformSampler`] for your own type, this type /// should not be used directly, use [`Uniform`] instead. /// /// # Implementation notes /// /// Instead of generating a float in the `[0, 1)` range using [`Standard`], the /// `UniformFloat` implementation converts the output of an PRNG itself. This /// way one or two steps can be optimized out. /// /// The floats are first converted to a value in the `[1, 2)` interval using a /// transmute-based method, and then mapped to the expected range with a /// multiply and addition. Values produced this way have what equals 22 bits of /// random digits for an `f32`, and 52 for an `f64`. /// /// [`new`]: UniformSampler::new /// [`new_inclusive`]: UniformSampler::new_inclusive /// [`Standard`]: crate::distributions::Standard #[derive(Clone, Copy, Debug)] pub struct UniformFloat { low: X, scale: X, } macro_rules! uniform_float_impl { ($ty:ty, $uty:ident, $f_scalar:ident, $u_scalar:ident, $bits_to_discard:expr) => { impl SampleUniform for $ty { type Sampler = UniformFloat<$ty>; } impl UniformSampler for UniformFloat<$ty> { type X = $ty; fn new(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low.all_lt(high), "Uniform::new called with `low >= high`"); assert!(low.all_finite() && high.all_finite(), "Uniform::new called with non-finite boundaries"); let max_rand = <$ty>::splat((::core::$u_scalar::MAX >> $bits_to_discard) .into_float_with_exponent(0) - 1.0); let mut scale = high - low; loop { let mask = (scale * max_rand + low).ge_mask(high); if mask.none() { break; } scale = scale.decrease_masked(mask); } debug_assert!(<$ty>::splat(0.0).all_le(scale)); UniformFloat { low, scale } } fn new_inclusive(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low.all_le(high), "Uniform::new_inclusive called with `low > high`"); assert!(low.all_finite() && high.all_finite(), "Uniform::new_inclusive called with non-finite boundaries"); let max_rand = <$ty>::splat((::core::$u_scalar::MAX >> $bits_to_discard) .into_float_with_exponent(0) - 1.0); let mut scale = (high - low) / max_rand; loop { let mask = (scale * max_rand + low).gt_mask(high); if mask.none() { break; } scale = scale.decrease_masked(mask); } debug_assert!(<$ty>::splat(0.0).all_le(scale)); UniformFloat { low, scale } } fn sample(&self, rng: &mut R) -> Self::X { // Generate a value in the range [1, 2) let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard) .into_float_with_exponent(0); // Get a value in the range [0, 1) in order to avoid // overflowing into infinity when multiplying with scale let value0_1 = value1_2 - 1.0; // We don't use `f64::mul_add`, because it is not available with // `no_std`. Furthermore, it is slower for some targets (but // faster for others). However, the order of multiplication and // addition is important, because on some platforms (e.g. ARM) // it will be optimized to a single (non-FMA) instruction. value0_1 * self.scale + self.low } #[inline] fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Self::X where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low.all_lt(high), "UniformSampler::sample_single: low >= high"); let mut scale = high - low; loop { // Generate a value in the range [1, 2) let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard) .into_float_with_exponent(0); // Get a value in the range [0, 1) in order to avoid // overflowing into infinity when multiplying with scale let value0_1 = value1_2 - 1.0; // Doing multiply before addition allows some architectures // to use a single instruction. let res = value0_1 * scale + low; debug_assert!(low.all_le(res) || !scale.all_finite()); if res.all_lt(high) { return res; } // This handles a number of edge cases. // * `low` or `high` is NaN. In this case `scale` and // `res` are going to end up as NaN. // * `low` is negative infinity and `high` is finite. // `scale` is going to be infinite and `res` will be // NaN. // * `high` is positive infinity and `low` is finite. // `scale` is going to be infinite and `res` will // be infinite or NaN (if value0_1 is 0). // * `low` is negative infinity and `high` is positive // infinity. `scale` will be infinite and `res` will // be NaN. // * `low` and `high` are finite, but `high - low` // overflows to infinite. `scale` will be infinite // and `res` will be infinite or NaN (if value0_1 is 0). // So if `high` or `low` are non-finite, we are guaranteed // to fail the `res < high` check above and end up here. // // While we technically should check for non-finite `low` // and `high` before entering the loop, by doing the checks // here instead, we allow the common case to avoid these // checks. But we are still guaranteed that if `low` or // `high` are non-finite we'll end up here and can do the // appropriate checks. // // Likewise `high - low` overflowing to infinity is also // rare, so handle it here after the common case. let mask = !scale.finite_mask(); if mask.any() { assert!(low.all_finite() && high.all_finite(), "Uniform::sample_single: low and high must be finite"); scale = scale.decrease_masked(mask); } } } } } } uniform_float_impl! { f32, u32, f32, u32, 32 - 23 } uniform_float_impl! { f64, u64, f64, u64, 64 - 52 } #[cfg(feature="simd_support")] uniform_float_impl! { f32x2, u32x2, f32, u32, 32 - 23 } #[cfg(feature="simd_support")] uniform_float_impl! { f32x4, u32x4, f32, u32, 32 - 23 } #[cfg(feature="simd_support")] uniform_float_impl! { f32x8, u32x8, f32, u32, 32 - 23 } #[cfg(feature="simd_support")] uniform_float_impl! { f32x16, u32x16, f32, u32, 32 - 23 } #[cfg(feature="simd_support")] uniform_float_impl! { f64x2, u64x2, f64, u64, 64 - 52 } #[cfg(feature="simd_support")] uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } #[cfg(feature="simd_support")] uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } /// The back-end implementing [`UniformSampler`] for `Duration`. /// /// Unless you are implementing [`UniformSampler`] for your own types, this type /// should not be used directly, use [`Uniform`] instead. #[derive(Clone, Copy, Debug)] pub struct UniformDuration { mode: UniformDurationMode, offset: u32, } #[derive(Debug, Copy, Clone)] enum UniformDurationMode { Small { secs: u64, nanos: Uniform, }, Medium { nanos: Uniform, }, Large { max_secs: u64, max_nanos: u32, secs: Uniform, } } impl SampleUniform for Duration { type Sampler = UniformDuration; } impl UniformSampler for UniformDuration { type X = Duration; #[inline] fn new(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low < high, "Uniform::new called with `low >= high`"); UniformDuration::new_inclusive(low, high - Duration::new(0, 1)) } #[inline] fn new_inclusive(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { let low = *low_b.borrow(); let high = *high_b.borrow(); assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); let low_s = low.as_secs(); let low_n = low.subsec_nanos(); let mut high_s = high.as_secs(); let mut high_n = high.subsec_nanos(); if high_n < low_n { high_s -= 1; high_n += 1_000_000_000; } let mode = if low_s == high_s { UniformDurationMode::Small { secs: low_s, nanos: Uniform::new_inclusive(low_n, high_n), } } else { let max = high_s .checked_mul(1_000_000_000) .and_then(|n| n.checked_add(u64::from(high_n))); if let Some(higher_bound) = max { let lower_bound = low_s * 1_000_000_000 + u64::from(low_n); UniformDurationMode::Medium { nanos: Uniform::new_inclusive(lower_bound, higher_bound), } } else { // An offset is applied to simplify generation of nanoseconds let max_nanos = high_n - low_n; UniformDurationMode::Large { max_secs: high_s, max_nanos, secs: Uniform::new_inclusive(low_s, high_s), } } }; UniformDuration { mode, offset: low_n, } } #[inline] fn sample(&self, rng: &mut R) -> Duration { match self.mode { UniformDurationMode::Small { secs, nanos } => { let n = nanos.sample(rng); Duration::new(secs, n) } UniformDurationMode::Medium { nanos } => { let nanos = nanos.sample(rng); Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) } UniformDurationMode::Large { max_secs, max_nanos, secs } => { // constant folding means this is at least as fast as `gen_range` let nano_range = Uniform::new(0, 1_000_000_000); loop { let s = secs.sample(rng); let n = nano_range.sample(rng); if !(s == max_secs && n > max_nanos) { let sum = n + self.offset; break Duration::new(s, sum); } } } } } } #[cfg(test)] mod tests { use super::*; use crate::rngs::mock::StepRng; #[should_panic] #[test] fn test_uniform_bad_limits_equal_int() { Uniform::new(10, 10); } #[test] fn test_uniform_good_limits_equal_int() { let mut rng = crate::test::rng(804); let dist = Uniform::new_inclusive(10, 10); for _ in 0..20 { assert_eq!(rng.sample(dist), 10); } } #[should_panic] #[test] fn test_uniform_bad_limits_flipped_int() { Uniform::new(10, 5); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_integers() { use core::{i8, i16, i32, i64, isize}; use core::{u8, u16, u32, u64, usize}; #[cfg(not(target_os = "emscripten"))] use core::{i128, u128}; let mut rng = crate::test::rng(251); macro_rules! t { ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{ for &(low, high) in $v.iter() { let my_uniform = Uniform::new(low, high); for _ in 0..1000 { let v: $ty = rng.sample(my_uniform); assert!($le(low, v) && $lt(v, high)); } let my_uniform = Uniform::new_inclusive(low, high); for _ in 0..1000 { let v: $ty = rng.sample(my_uniform); assert!($le(low, v) && $le(v, high)); } let my_uniform = Uniform::new(&low, high); for _ in 0..1000 { let v: $ty = rng.sample(my_uniform); assert!($le(low, v) && $lt(v, high)); } let my_uniform = Uniform::new_inclusive(&low, &high); for _ in 0..1000 { let v: $ty = rng.sample(my_uniform); assert!($le(low, v) && $le(v, high)); } for _ in 0..1000 { let v: $ty = rng.gen_range(low, high); assert!($le(low, v) && $lt(v, high)); } } }}; // scalar bulk ($($ty:ident),*) => {{ $(t!( $ty, [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)], |x, y| x <= y, |x, y| x < y );)* }}; // simd bulk ($($ty:ident),* => $scalar:ident) => {{ $(t!( $ty, [ ($ty::splat(0), $ty::splat(10)), ($ty::splat(10), $ty::splat(127)), ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)), ], |x: $ty, y| x.le(y).all(), |x: $ty, y| x.lt(y).all() );)* }}; } t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); #[cfg(not(target_os = "emscripten"))] t!(i128, u128); #[cfg(all(feature = "simd_support", feature = "nightly"))] { t!(u8x2, u8x4, u8x8, u8x16, u8x32, u8x64 => u8); t!(i8x2, i8x4, i8x8, i8x16, i8x32, i8x64 => i8); t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16); t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16); t!(u32x2, u32x4, u32x8, u32x16 => u32); t!(i32x2, i32x4, i32x8, i32x16 => i32); t!(u64x2, u64x4, u64x8 => u64); t!(i64x2, i64x4, i64x8 => i64); } } #[test] #[cfg(not(miri))] // Miri is too slow fn test_floats() { let mut rng = crate::test::rng(252); let mut zero_rng = StepRng::new(0, 0); let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0); macro_rules! t { ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{ let v: &[($f_scalar, $f_scalar)]= &[(0.0, 100.0), (-1e35, -1e25), (1e-35, 1e-25), (-1e35, 1e35), (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), (-<$f_scalar>::from_bits(5), 0.0), (-<$f_scalar>::from_bits(7), -0.0), (10.0, ::core::$f_scalar::MAX), (-100.0, ::core::$f_scalar::MAX), (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX), (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0), (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7), (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX), ]; for &(low_scalar, high_scalar) in v.iter() { for lane in 0..<$ty>::lanes() { let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); let my_uniform = Uniform::new(low, high); let my_incl_uniform = Uniform::new_inclusive(low, high); for _ in 0..100 { let v = rng.sample(my_uniform).extract(lane); assert!(low_scalar <= v && v < high_scalar); let v = rng.sample(my_incl_uniform).extract(lane); assert!(low_scalar <= v && v <= high_scalar); let v = rng.gen_range(low, high).extract(lane); assert!(low_scalar <= v && v < high_scalar); } assert_eq!(rng.sample(Uniform::new_inclusive(low, low)).extract(lane), low_scalar); assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar); assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar); assert_eq!(zero_rng.gen_range(low, high).extract(lane), low_scalar); assert!(max_rng.sample(my_uniform).extract(lane) < high_scalar); assert!(max_rng.sample(my_incl_uniform).extract(lane) <= high_scalar); // Don't run this test for really tiny differences between high and low // since for those rounding might result in selecting high for a very // long time. if (high_scalar - low_scalar) > 0.0001 { let mut lowering_max_rng = StepRng::new(0xffff_ffff_ffff_ffff, (-1i64 << $bits_shifted) as u64); assert!(lowering_max_rng.gen_range(low, high).extract(lane) < high_scalar); } } } assert_eq!(rng.sample(Uniform::new_inclusive(::core::$f_scalar::MAX, ::core::$f_scalar::MAX)), ::core::$f_scalar::MAX); assert_eq!(rng.sample(Uniform::new_inclusive(-::core::$f_scalar::MAX, -::core::$f_scalar::MAX)), -::core::$f_scalar::MAX); }} } t!(f32, f32, 32 - 23); t!(f64, f64, 64 - 52); #[cfg(feature="simd_support")] { t!(f32x2, f32, 32 - 23); t!(f32x4, f32, 32 - 23); t!(f32x8, f32, 32 - 23); t!(f32x16, f32, 32 - 23); t!(f64x2, f64, 64 - 52); t!(f64x4, f64, 64 - 52); t!(f64x8, f64, 64 - 52); } } #[test] #[cfg(all(feature="std", not(target_arch = "wasm32"), not(target_arch = "asmjs")))] #[cfg(not(miri))] // Miri does not support catching panics fn test_float_assertions() { use std::panic::catch_unwind; use super::SampleUniform; fn range(low: T, high: T) { let mut rng = crate::test::rng(253); rng.gen_range(low, high); } macro_rules! t { ($ty:ident, $f_scalar:ident) => {{ let v: &[($f_scalar, $f_scalar)] = &[(::std::$f_scalar::NAN, 0.0), (1.0, ::std::$f_scalar::NAN), (::std::$f_scalar::NAN, ::std::$f_scalar::NAN), (1.0, 0.5), (::std::$f_scalar::MAX, -::std::$f_scalar::MAX), (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY), (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NEG_INFINITY), (::std::$f_scalar::NEG_INFINITY, 5.0), (5.0, ::std::$f_scalar::INFINITY), (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY), (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN), (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY), ]; for &(low_scalar, high_scalar) in v.iter() { for lane in 0..<$ty>::lanes() { let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); assert!(catch_unwind(|| range(low, high)).is_err()); assert!(catch_unwind(|| Uniform::new(low, high)).is_err()); assert!(catch_unwind(|| Uniform::new_inclusive(low, high)).is_err()); assert!(catch_unwind(|| range(low, low)).is_err()); assert!(catch_unwind(|| Uniform::new(low, low)).is_err()); } } }} } t!(f32, f32); t!(f64, f64); #[cfg(feature="simd_support")] { t!(f32x2, f32); t!(f32x4, f32); t!(f32x8, f32); t!(f32x16, f32); t!(f64x2, f64); t!(f64x4, f64); t!(f64x8, f64); } } #[test] #[cfg(not(miri))] // Miri is too slow fn test_durations() { #[cfg(feature = "std")] use std::time::Duration; #[cfg(not(feature = "std"))] use core::time::Duration; let mut rng = crate::test::rng(253); let v = &[(Duration::new(10, 50000), Duration::new(100, 1234)), (Duration::new(0, 100), Duration::new(1, 50)), (Duration::new(0, 0), Duration::new(u64::max_value(), 999_999_999))]; for &(low, high) in v.iter() { let my_uniform = Uniform::new(low, high); for _ in 0..1000 { let v = rng.sample(my_uniform); assert!(low <= v && v < high); } } } #[test] fn test_custom_uniform() { use crate::distributions::uniform::{UniformSampler, UniformFloat, SampleUniform, SampleBorrow}; #[derive(Clone, Copy, PartialEq, PartialOrd)] struct MyF32 { x: f32, } #[derive(Clone, Copy, Debug)] struct UniformMyF32(UniformFloat); impl UniformSampler for UniformMyF32 { type X = MyF32; fn new(low: B1, high: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { UniformMyF32(UniformFloat::::new(low.borrow().x, high.borrow().x)) } fn new_inclusive(low: B1, high: B2) -> Self where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized { UniformSampler::new(low, high) } fn sample(&self, rng: &mut R) -> Self::X { MyF32 { x: self.0.sample(rng) } } } impl SampleUniform for MyF32 { type Sampler = UniformMyF32; } let (low, high) = (MyF32{ x: 17.0f32 }, MyF32{ x: 22.0f32 }); let uniform = Uniform::new(low, high); let mut rng = crate::test::rng(804); for _ in 0..100 { let x: MyF32 = rng.sample(uniform); assert!(low <= x && x < high); } } #[test] fn test_uniform_from_std_range() { let r = Uniform::from(2u32..7); assert_eq!(r.0.low, 2); assert_eq!(r.0.range, 5); let r = Uniform::from(2.0f64..7.0); assert_eq!(r.0.low, 2.0); assert_eq!(r.0.scale, 5.0); } #[test] fn test_uniform_from_std_range_inclusive() { let r = Uniform::from(2u32..=6); assert_eq!(r.0.low, 2); assert_eq!(r.0.range, 5); let r = Uniform::from(2.0f64..=7.0); assert_eq!(r.0.low, 2.0); assert!(r.0.scale > 5.0); assert!(r.0.scale < 5.0 + 1e-14); } #[test] fn value_stability() { fn test_samples( lb: T, ub: T, expected_single: &[T], expected_multiple: &[T] ) where Uniform: Distribution { let mut rng = crate::test::rng(897); let mut buf = [lb; 3]; for x in &mut buf { *x = T::Sampler::sample_single(lb, ub, &mut rng); } assert_eq!(&buf, expected_single); let distr = Uniform::new(lb, ub); for x in &mut buf { *x = rng.sample(&distr); } assert_eq!(&buf, expected_multiple); } // We test on a sub-set of types; possibly we should do more. // TODO: SIMD types test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]); test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]); test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[0.008194133, 0.00398172, 0.007428536]); test_samples(-1e10f64, 1e10f64, &[-4673848682.871551, 6388267422.932352, 4857075081.198343], &[1173375212.1808167, 1917642852.109581, 2365076174.3153973]); test_samples(Duration::new(2, 0), Duration::new(4, 0), &[Duration::new(2,532615131), Duration::new(3,638826742), Duration::new(3,485707508)], &[Duration::new(3,117337521), Duration::new(3,191764285), Duration::new(3,236507617)]); } } rand-0.7.2/src/distributions/unit_circle.rs010064400017500001750000000060161352222772600172370ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(deprecated)] #![allow(clippy::all)] use crate::Rng; use crate::distributions::{Distribution, Uniform}; /// Samples uniformly from the edge of the unit circle in two dimensions. /// /// Implemented via a method by von Neumann[^1]. /// /// [^1]: von Neumann, J. (1951) [*Various Techniques Used in Connection with /// Random Digits.*](https://mcnp.lanl.gov/pdf_files/nbs_vonneumann.pdf) /// NBS Appl. Math. Ser., No. 12. Washington, DC: U.S. Government Printing /// Office, pp. 36-38. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct UnitCircle; impl UnitCircle { /// Construct a new `UnitCircle` distribution. #[inline] pub fn new() -> UnitCircle { UnitCircle } } impl Distribution<[f64; 2]> for UnitCircle { #[inline] fn sample(&self, rng: &mut R) -> [f64; 2] { let uniform = Uniform::new(-1., 1.); let mut x1; let mut x2; let mut sum; loop { x1 = uniform.sample(rng); x2 = uniform.sample(rng); sum = x1*x1 + x2*x2; if sum < 1. { break; } } let diff = x1*x1 - x2*x2; [diff / sum, 2.*x1*x2 / sum] } } #[cfg(test)] mod tests { use crate::distributions::Distribution; use super::UnitCircle; /// Assert that two numbers are almost equal to each other. /// /// On panic, this macro will print the values of the expressions with their /// debug representations. macro_rules! assert_almost_eq { ($a:expr, $b:expr, $prec:expr) => ( let diff = ($a - $b).abs(); if diff > $prec { panic!(format!( "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \ (left: `{}`, right: `{}`)", diff, $prec, $a, $b)); } ); } #[test] fn norm() { let mut rng = crate::test::rng(1); let dist = UnitCircle::new(); for _ in 0..1000 { let x = dist.sample(&mut rng); assert_almost_eq!(x[0]*x[0] + x[1]*x[1], 1., 1e-15); } } #[test] fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ [-0.9965658683520504, -0.08280380447614634], [-0.9790853270389644, -0.20345004884984505], [-0.8449189758898707, 0.5348943112253227], ]; let samples = [ UnitCircle.sample(&mut rng), UnitCircle.sample(&mut rng), UnitCircle.sample(&mut rng), ]; assert_eq!(samples, expected); } } rand-0.7.2/src/distributions/unit_sphere.rs010064400017500001750000000061111352222772600172600ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(deprecated)] #![allow(clippy::all)] use crate::Rng; use crate::distributions::{Distribution, Uniform}; /// Samples uniformly from the surface of the unit sphere in three dimensions. /// /// Implemented via a method by Marsaglia[^1]. /// /// [^1]: Marsaglia, George (1972). [*Choosing a Point from the Surface of a /// Sphere.*](https://doi.org/10.1214/aoms/1177692644) /// Ann. Math. Statist. 43, no. 2, 645--646. #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct UnitSphereSurface; impl UnitSphereSurface { /// Construct a new `UnitSphereSurface` distribution. #[inline] pub fn new() -> UnitSphereSurface { UnitSphereSurface } } impl Distribution<[f64; 3]> for UnitSphereSurface { #[inline] fn sample(&self, rng: &mut R) -> [f64; 3] { let uniform = Uniform::new(-1., 1.); loop { let (x1, x2) = (uniform.sample(rng), uniform.sample(rng)); let sum = x1*x1 + x2*x2; if sum >= 1. { continue; } let factor = 2. * (1.0_f64 - sum).sqrt(); return [x1 * factor, x2 * factor, 1. - 2.*sum]; } } } #[cfg(test)] mod tests { use crate::distributions::Distribution; use super::UnitSphereSurface; /// Assert that two numbers are almost equal to each other. /// /// On panic, this macro will print the values of the expressions with their /// debug representations. macro_rules! assert_almost_eq { ($a:expr, $b:expr, $prec:expr) => ( let diff = ($a - $b).abs(); if diff > $prec { panic!(format!( "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \ (left: `{}`, right: `{}`)", diff, $prec, $a, $b)); } ); } #[test] fn norm() { let mut rng = crate::test::rng(1); let dist = UnitSphereSurface::new(); for _ in 0..1000 { let x = dist.sample(&mut rng); assert_almost_eq!(x[0]*x[0] + x[1]*x[1] + x[2]*x[2], 1., 1e-15); } } #[test] fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ [0.03247542860231647, -0.7830477442152738, 0.6211131755296027], [-0.09978440840914075, 0.9706650829833128, -0.21875184231323952], [0.2735582468624679, 0.9435374242279655, -0.1868234852870203], ]; let samples = [ UnitSphereSurface.sample(&mut rng), UnitSphereSurface.sample(&mut rng), UnitSphereSurface.sample(&mut rng), ]; assert_eq!(samples, expected); } } rand-0.7.2/src/distributions/utils.rs010064400017500001750000000421771352222772600161070ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Math helper functions #[cfg(feature="simd_support")] use packed_simd::*; #[cfg(feature="std")] use crate::distributions::ziggurat_tables; #[cfg(feature="std")] use crate::Rng; pub trait WideningMultiply { type Output; fn wmul(self, x: RHS) -> Self::Output; } macro_rules! wmul_impl { ($ty:ty, $wide:ty, $shift:expr) => { impl WideningMultiply for $ty { type Output = ($ty, $ty); #[inline(always)] fn wmul(self, x: $ty) -> Self::Output { let tmp = (self as $wide) * (x as $wide); ((tmp >> $shift) as $ty, tmp as $ty) } } }; // simd bulk implementation ($(($ty:ident, $wide:ident),)+, $shift:expr) => { $( impl WideningMultiply for $ty { type Output = ($ty, $ty); #[inline(always)] fn wmul(self, x: $ty) -> Self::Output { // For supported vectors, this should compile to a couple // supported multiply & swizzle instructions (no actual // casting). // TODO: optimize let y: $wide = self.cast(); let x: $wide = x.cast(); let tmp = y * x; let hi: $ty = (tmp >> $shift).cast(); let lo: $ty = tmp.cast(); (hi, lo) } } )+ }; } wmul_impl! { u8, u16, 8 } wmul_impl! { u16, u32, 16 } wmul_impl! { u32, u64, 32 } #[cfg(not(target_os = "emscripten"))] wmul_impl! { u64, u128, 64 } // This code is a translation of the __mulddi3 function in LLVM's // compiler-rt. It is an optimised variant of the common method // `(a + b) * (c + d) = ac + ad + bc + bd`. // // For some reason LLVM can optimise the C version very well, but // keeps shuffling registers in this Rust translation. macro_rules! wmul_impl_large { ($ty:ty, $half:expr) => { impl WideningMultiply for $ty { type Output = ($ty, $ty); #[inline(always)] fn wmul(self, b: $ty) -> Self::Output { const LOWER_MASK: $ty = !0 >> $half; let mut low = (self & LOWER_MASK).wrapping_mul(b & LOWER_MASK); let mut t = low >> $half; low &= LOWER_MASK; t += (self >> $half).wrapping_mul(b & LOWER_MASK); low += (t & LOWER_MASK) << $half; let mut high = t >> $half; t = low >> $half; low &= LOWER_MASK; t += (b >> $half).wrapping_mul(self & LOWER_MASK); low += (t & LOWER_MASK) << $half; high += t >> $half; high += (self >> $half).wrapping_mul(b >> $half); (high, low) } } }; // simd bulk implementation (($($ty:ty,)+) $scalar:ty, $half:expr) => { $( impl WideningMultiply for $ty { type Output = ($ty, $ty); #[inline(always)] fn wmul(self, b: $ty) -> Self::Output { // needs wrapping multiplication const LOWER_MASK: $scalar = !0 >> $half; let mut low = (self & LOWER_MASK) * (b & LOWER_MASK); let mut t = low >> $half; low &= LOWER_MASK; t += (self >> $half) * (b & LOWER_MASK); low += (t & LOWER_MASK) << $half; let mut high = t >> $half; t = low >> $half; low &= LOWER_MASK; t += (b >> $half) * (self & LOWER_MASK); low += (t & LOWER_MASK) << $half; high += t >> $half; high += (self >> $half) * (b >> $half); (high, low) } } )+ }; } #[cfg(target_os = "emscripten")] wmul_impl_large! { u64, 32 } #[cfg(not(target_os = "emscripten"))] wmul_impl_large! { u128, 64 } macro_rules! wmul_impl_usize { ($ty:ty) => { impl WideningMultiply for usize { type Output = (usize, usize); #[inline(always)] fn wmul(self, x: usize) -> Self::Output { let (high, low) = (self as $ty).wmul(x as $ty); (high as usize, low as usize) } } } } #[cfg(target_pointer_width = "32")] wmul_impl_usize! { u32 } #[cfg(target_pointer_width = "64")] wmul_impl_usize! { u64 } #[cfg(all(feature = "simd_support", feature = "nightly"))] mod simd_wmul { #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; use super::*; wmul_impl! { (u8x2, u16x2), (u8x4, u16x4), (u8x8, u16x8), (u8x16, u16x16), (u8x32, u16x32),, 8 } wmul_impl! { (u16x2, u32x2),, 16 } #[cfg(not(target_feature = "sse2"))] wmul_impl! { (u16x4, u32x4),, 16 } #[cfg(not(target_feature = "sse4.2"))] wmul_impl! { (u16x8, u32x8),, 16 } #[cfg(not(target_feature = "avx2"))] wmul_impl! { (u16x16, u32x16),, 16 } // 16-bit lane widths allow use of the x86 `mulhi` instructions, which // means `wmul` can be implemented with only two instructions. #[allow(unused_macros)] macro_rules! wmul_impl_16 { ($ty:ident, $intrinsic:ident, $mulhi:ident, $mullo:ident) => { impl WideningMultiply for $ty { type Output = ($ty, $ty); #[inline(always)] fn wmul(self, x: $ty) -> Self::Output { let b = $intrinsic::from_bits(x); let a = $intrinsic::from_bits(self); let hi = $ty::from_bits(unsafe { $mulhi(a, b) }); let lo = $ty::from_bits(unsafe { $mullo(a, b) }); (hi, lo) } } }; } #[cfg(target_feature = "sse2")] wmul_impl_16! { u16x4, __m64, _mm_mulhi_pu16, _mm_mullo_pi16 } #[cfg(target_feature = "sse4.2")] wmul_impl_16! { u16x8, __m128i, _mm_mulhi_epu16, _mm_mullo_epi16 } #[cfg(target_feature = "avx2")] wmul_impl_16! { u16x16, __m256i, _mm256_mulhi_epu16, _mm256_mullo_epi16 } // FIXME: there are no `__m512i` types in stdsimd yet, so `wmul::` // cannot use the same implementation. wmul_impl! { (u32x2, u64x2), (u32x4, u64x4), (u32x8, u64x8),, 32 } // TODO: optimize, this seems to seriously slow things down wmul_impl_large! { (u8x64,) u8, 4 } wmul_impl_large! { (u16x32,) u16, 8 } wmul_impl_large! { (u32x16,) u32, 16 } wmul_impl_large! { (u64x2, u64x4, u64x8,) u64, 32 } } #[cfg(all(feature = "simd_support", feature = "nightly"))] pub use self::simd_wmul::*; /// Helper trait when dealing with scalar and SIMD floating point types. pub(crate) trait FloatSIMDUtils { // `PartialOrd` for vectors compares lexicographically. We want to compare all // the individual SIMD lanes instead, and get the combined result over all // lanes. This is possible using something like `a.lt(b).all()`, but we // implement it as a trait so we can write the same code for `f32` and `f64`. // Only the comparison functions we need are implemented. fn all_lt(self, other: Self) -> bool; fn all_le(self, other: Self) -> bool; fn all_finite(self) -> bool; type Mask; fn finite_mask(self) -> Self::Mask; fn gt_mask(self, other: Self) -> Self::Mask; fn ge_mask(self, other: Self) -> Self::Mask; // Decrease all lanes where the mask is `true` to the next lower value // representable by the floating-point type. At least one of the lanes // must be set. fn decrease_masked(self, mask: Self::Mask) -> Self; // Convert from int value. Conversion is done while retaining the numerical // value, not by retaining the binary representation. type UInt; fn cast_from_int(i: Self::UInt) -> Self; } /// Implement functions available in std builds but missing from core primitives #[cfg(not(std))] pub(crate) trait Float : Sized { fn is_nan(self) -> bool; fn is_infinite(self) -> bool; fn is_finite(self) -> bool; } /// Implement functions on f32/f64 to give them APIs similar to SIMD types pub(crate) trait FloatAsSIMD : Sized { #[inline(always)] fn lanes() -> usize { 1 } #[inline(always)] fn splat(scalar: Self) -> Self { scalar } #[inline(always)] fn extract(self, index: usize) -> Self { debug_assert_eq!(index, 0); self } #[inline(always)] fn replace(self, index: usize, new_value: Self) -> Self { debug_assert_eq!(index, 0); new_value } } pub(crate) trait BoolAsSIMD : Sized { fn any(self) -> bool; fn all(self) -> bool; fn none(self) -> bool; } impl BoolAsSIMD for bool { #[inline(always)] fn any(self) -> bool { self } #[inline(always)] fn all(self) -> bool { self } #[inline(always)] fn none(self) -> bool { !self } } macro_rules! scalar_float_impl { ($ty:ident, $uty:ident) => { #[cfg(not(std))] impl Float for $ty { #[inline] fn is_nan(self) -> bool { self != self } #[inline] fn is_infinite(self) -> bool { self == ::core::$ty::INFINITY || self == ::core::$ty::NEG_INFINITY } #[inline] fn is_finite(self) -> bool { !(self.is_nan() || self.is_infinite()) } } impl FloatSIMDUtils for $ty { type Mask = bool; #[inline(always)] fn all_lt(self, other: Self) -> bool { self < other } #[inline(always)] fn all_le(self, other: Self) -> bool { self <= other } #[inline(always)] fn all_finite(self) -> bool { self.is_finite() } #[inline(always)] fn finite_mask(self) -> Self::Mask { self.is_finite() } #[inline(always)] fn gt_mask(self, other: Self) -> Self::Mask { self > other } #[inline(always)] fn ge_mask(self, other: Self) -> Self::Mask { self >= other } #[inline(always)] fn decrease_masked(self, mask: Self::Mask) -> Self { debug_assert!(mask, "At least one lane must be set"); <$ty>::from_bits(self.to_bits() - 1) } type UInt = $uty; fn cast_from_int(i: Self::UInt) -> Self { i as $ty } } impl FloatAsSIMD for $ty {} } } scalar_float_impl!(f32, u32); scalar_float_impl!(f64, u64); #[cfg(feature="simd_support")] macro_rules! simd_impl { ($ty:ident, $f_scalar:ident, $mty:ident, $uty:ident) => { impl FloatSIMDUtils for $ty { type Mask = $mty; #[inline(always)] fn all_lt(self, other: Self) -> bool { self.lt(other).all() } #[inline(always)] fn all_le(self, other: Self) -> bool { self.le(other).all() } #[inline(always)] fn all_finite(self) -> bool { self.finite_mask().all() } #[inline(always)] fn finite_mask(self) -> Self::Mask { // This can possibly be done faster by checking bit patterns let neg_inf = $ty::splat(::core::$f_scalar::NEG_INFINITY); let pos_inf = $ty::splat(::core::$f_scalar::INFINITY); self.gt(neg_inf) & self.lt(pos_inf) } #[inline(always)] fn gt_mask(self, other: Self) -> Self::Mask { self.gt(other) } #[inline(always)] fn ge_mask(self, other: Self) -> Self::Mask { self.ge(other) } #[inline(always)] fn decrease_masked(self, mask: Self::Mask) -> Self { // Casting a mask into ints will produce all bits set for // true, and 0 for false. Adding that to the binary // representation of a float means subtracting one from // the binary representation, resulting in the next lower // value representable by $ty. This works even when the // current value is infinity. debug_assert!(mask.any(), "At least one lane must be set"); <$ty>::from_bits(<$uty>::from_bits(self) + <$uty>::from_bits(mask)) } type UInt = $uty; #[inline] fn cast_from_int(i: Self::UInt) -> Self { i.cast() } } } } #[cfg(feature="simd_support")] simd_impl! { f32x2, f32, m32x2, u32x2 } #[cfg(feature="simd_support")] simd_impl! { f32x4, f32, m32x4, u32x4 } #[cfg(feature="simd_support")] simd_impl! { f32x8, f32, m32x8, u32x8 } #[cfg(feature="simd_support")] simd_impl! { f32x16, f32, m32x16, u32x16 } #[cfg(feature="simd_support")] simd_impl! { f64x2, f64, m64x2, u64x2 } #[cfg(feature="simd_support")] simd_impl! { f64x4, f64, m64x4, u64x4 } #[cfg(feature="simd_support")] simd_impl! { f64x8, f64, m64x8, u64x8 } /// Calculates ln(gamma(x)) (natural logarithm of the gamma /// function) using the Lanczos approximation. /// /// The approximation expresses the gamma function as: /// `gamma(z+1) = sqrt(2*pi)*(z+g+0.5)^(z+0.5)*exp(-z-g-0.5)*Ag(z)` /// `g` is an arbitrary constant; we use the approximation with `g=5`. /// /// Noting that `gamma(z+1) = z*gamma(z)` and applying `ln` to both sides: /// `ln(gamma(z)) = (z+0.5)*ln(z+g+0.5)-(z+g+0.5) + ln(sqrt(2*pi)*Ag(z)/z)` /// /// `Ag(z)` is an infinite series with coefficients that can be calculated /// ahead of time - we use just the first 6 terms, which is good enough /// for most purposes. #[cfg(feature="std")] pub fn log_gamma(x: f64) -> f64 { // precalculated 6 coefficients for the first 6 terms of the series let coefficients: [f64; 6] = [ 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5, ]; // (x+0.5)*ln(x+g+0.5)-(x+g+0.5) let tmp = x + 5.5; let log = (x + 0.5) * tmp.ln() - tmp; // the first few terms of the series for Ag(x) let mut a = 1.000000000190015; let mut denom = x; for coeff in &coefficients { denom += 1.0; a += coeff / denom; } // get everything together // a is Ag(x) // 2.5066... is sqrt(2pi) log + (2.5066282746310005 * a / x).ln() } /// Sample a random number using the Ziggurat method (specifically the /// ZIGNOR variant from Doornik 2005). Most of the arguments are /// directly from the paper: /// /// * `rng`: source of randomness /// * `symmetric`: whether this is a symmetric distribution, or one-sided with P(x < 0) = 0. /// * `X`: the $x_i$ abscissae. /// * `F`: precomputed values of the PDF at the $x_i$, (i.e. $f(x_i)$) /// * `F_DIFF`: precomputed values of $f(x_i) - f(x_{i+1})$ /// * `pdf`: the probability density function /// * `zero_case`: manual sampling from the tail when we chose the /// bottom box (i.e. i == 0) // the perf improvement (25-50%) is definitely worth the extra code // size from force-inlining. #[cfg(feature="std")] #[inline(always)] pub fn ziggurat( rng: &mut R, symmetric: bool, x_tab: ziggurat_tables::ZigTable, f_tab: ziggurat_tables::ZigTable, mut pdf: P, mut zero_case: Z) -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 { use crate::distributions::float::IntoFloat; loop { // As an optimisation we re-implement the conversion to a f64. // From the remaining 12 most significant bits we use 8 to construct `i`. // This saves us generating a whole extra random number, while the added // precision of using 64 bits for f64 does not buy us much. let bits = rng.next_u64(); let i = bits as usize & 0xff; let u = if symmetric { // Convert to a value in the range [2,4) and substract to get [-1,1) // We can't convert to an open range directly, that would require // substracting `3.0 - EPSILON`, which is not representable. // It is possible with an extra step, but an open range does not // seem neccesary for the ziggurat algorithm anyway. (bits >> 12).into_float_with_exponent(1) - 3.0 } else { // Convert to a value in the range [1,2) and substract to get (0,1) (bits >> 12).into_float_with_exponent(0) - (1.0 - ::core::f64::EPSILON / 2.0) }; let x = u * x_tab[i]; let test_x = if symmetric { x.abs() } else {x}; // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i]) if test_x < x_tab[i + 1] { return x; } if i == 0 { return zero_case(rng, u); } // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1 if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen::() < pdf(x) { return x; } } } rand-0.7.2/src/distributions/weibull.rs010064400017500001750000000032701352222772600164010ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The Weibull distribution. #![allow(deprecated)] use crate::Rng; use crate::distributions::{Distribution, OpenClosed01}; /// Samples floating-point numbers according to the Weibull distribution #[deprecated(since="0.7.0", note="moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Weibull { inv_shape: f64, scale: f64, } impl Weibull { /// Construct a new `Weibull` distribution with given `scale` and `shape`. /// /// # Panics /// /// `scale` and `shape` have to be non-zero and positive. pub fn new(scale: f64, shape: f64) -> Weibull { assert!((scale > 0.) & (shape > 0.)); Weibull { inv_shape: 1./shape, scale } } } impl Distribution for Weibull { fn sample(&self, rng: &mut R) -> f64 { let x: f64 = rng.sample(OpenClosed01); self.scale * (-x.ln()).powf(self.inv_shape) } } #[cfg(test)] mod tests { use crate::distributions::Distribution; use super::Weibull; #[test] #[should_panic] fn invalid() { Weibull::new(0., 0.); } #[test] fn sample() { let scale = 1.0; let shape = 2.0; let d = Weibull::new(scale, shape); let mut rng = crate::test::rng(1); for _ in 0..1000 { let r = d.sample(&mut rng); assert!(r >= 0.); } } } rand-0.7.2/src/distributions/weighted/alias_method.rs010064400017500001750000000413721353737675000212040ustar0000000000000000//! This module contains an implementation of alias method for sampling random //! indices with probabilities proportional to a collection of weights. use super::WeightedError; #[cfg(not(feature = "std"))] use crate::alloc::vec::Vec; #[cfg(not(feature = "std"))] use crate::alloc::vec; use core::fmt; use core::iter::Sum; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; use crate::distributions::uniform::SampleUniform; use crate::distributions::Distribution; use crate::distributions::Uniform; use crate::Rng; /// A distribution using weighted sampling to pick a discretely selected item. /// /// Sampling a [`WeightedIndex`] distribution returns the index of a randomly /// selected element from the vector used to create the [`WeightedIndex`]. /// The chance of a given element being picked is proportional to the value of /// the element. The weights can have any type `W` for which a implementation of /// [`Weight`] exists. /// /// # Performance /// /// Given that `n` is the number of items in the vector used to create an /// [`WeightedIndex`], [`WeightedIndex`] will require `O(n)` amount of /// memory. More specifically it takes up some constant amount of memory plus /// the vector used to create it and a [`Vec`] with capacity `n`. /// /// Time complexity for the creation of a [`WeightedIndex`] is `O(n)`. /// Sampling is `O(1)`, it makes a call to [`Uniform::sample`] and a call /// to [`Uniform::sample`]. /// /// # Example /// /// ``` /// use rand::distributions::weighted::alias_method::WeightedIndex; /// use rand::prelude::*; /// /// let choices = vec!['a', 'b', 'c']; /// let weights = vec![2, 1, 1]; /// let dist = WeightedIndex::new(weights).unwrap(); /// let mut rng = thread_rng(); /// for _ in 0..100 { /// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c' /// println!("{}", choices[dist.sample(&mut rng)]); /// } /// /// let items = [('a', 0), ('b', 3), ('c', 7)]; /// let dist2 = WeightedIndex::new(items.iter().map(|item| item.1).collect()).unwrap(); /// for _ in 0..100 { /// // 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c' /// println!("{}", items[dist2.sample(&mut rng)].0); /// } /// ``` /// /// [`WeightedIndex`]: crate::distributions::weighted::alias_method::WeightedIndex /// [`Weight`]: crate::distributions::weighted::alias_method::Weight /// [`Vec`]: Vec /// [`Uniform::sample`]: Distribution::sample /// [`Uniform::sample`]: Distribution::sample pub struct WeightedIndex { aliases: Vec, no_alias_odds: Vec, uniform_index: Uniform, uniform_within_weight_sum: Uniform, } impl WeightedIndex { /// Creates a new [`WeightedIndex`]. /// /// Returns an error if: /// - The vector is empty. /// - The vector is longer than `u32::MAX`. /// - For any weight `w`: `w < 0` or `w > max` where `max = W::MAX / /// weights.len()`. /// - The sum of weights is zero. pub fn new(weights: Vec) -> Result { let n = weights.len(); if n == 0 { return Err(WeightedError::NoItem); } else if n > ::core::u32::MAX as usize { return Err(WeightedError::TooMany); } let n = n as u32; let max_weight_size = W::try_from_u32_lossy(n) .map(|n| W::MAX / n) .unwrap_or(W::ZERO); if !weights .iter() .all(|&w| W::ZERO <= w && w <= max_weight_size) { return Err(WeightedError::InvalidWeight); } // The sum of weights will represent 100% of no alias odds. let weight_sum = Weight::sum(weights.as_slice()); // Prevent floating point overflow due to rounding errors. let weight_sum = if weight_sum > W::MAX { W::MAX } else { weight_sum }; if weight_sum == W::ZERO { return Err(WeightedError::AllWeightsZero); } // `weight_sum` would have been zero if `try_from_lossy` causes an error here. let n_converted = W::try_from_u32_lossy(n).unwrap(); let mut no_alias_odds = weights; for odds in no_alias_odds.iter_mut() { *odds *= n_converted; // Prevent floating point overflow due to rounding errors. *odds = if *odds > W::MAX { W::MAX } else { *odds }; } /// This struct is designed to contain three data structures at once, /// sharing the same memory. More precisely it contains two linked lists /// and an alias map, which will be the output of this method. To keep /// the three data structures from getting in each other's way, it must /// be ensured that a single index is only ever in one of them at the /// same time. struct Aliases { aliases: Vec, smalls_head: u32, bigs_head: u32, } impl Aliases { fn new(size: u32) -> Self { Aliases { aliases: vec![0; size as usize], smalls_head: ::core::u32::MAX, bigs_head: ::core::u32::MAX, } } fn push_small(&mut self, idx: u32) { self.aliases[idx as usize] = self.smalls_head; self.smalls_head = idx; } fn push_big(&mut self, idx: u32) { self.aliases[idx as usize] = self.bigs_head; self.bigs_head = idx; } fn pop_small(&mut self) -> u32 { let popped = self.smalls_head; self.smalls_head = self.aliases[popped as usize]; popped } fn pop_big(&mut self) -> u32 { let popped = self.bigs_head; self.bigs_head = self.aliases[popped as usize]; popped } fn smalls_is_empty(&self) -> bool { self.smalls_head == ::core::u32::MAX } fn bigs_is_empty(&self) -> bool { self.bigs_head == ::core::u32::MAX } fn set_alias(&mut self, idx: u32, alias: u32) { self.aliases[idx as usize] = alias; } } let mut aliases = Aliases::new(n); // Split indices into those with small weights and those with big weights. for (index, &odds) in no_alias_odds.iter().enumerate() { if odds < weight_sum { aliases.push_small(index as u32); } else { aliases.push_big(index as u32); } } // Build the alias map by finding an alias with big weight for each index with // small weight. while !aliases.smalls_is_empty() && !aliases.bigs_is_empty() { let s = aliases.pop_small(); let b = aliases.pop_big(); aliases.set_alias(s, b); no_alias_odds[b as usize] = no_alias_odds[b as usize] - weight_sum + no_alias_odds[s as usize]; if no_alias_odds[b as usize] < weight_sum { aliases.push_small(b); } else { aliases.push_big(b); } } // The remaining indices should have no alias odds of about 100%. This is due to // numeric accuracy. Otherwise they would be exactly 100%. while !aliases.smalls_is_empty() { no_alias_odds[aliases.pop_small() as usize] = weight_sum; } while !aliases.bigs_is_empty() { no_alias_odds[aliases.pop_big() as usize] = weight_sum; } // Prepare distributions for sampling. Creating them beforehand improves // sampling performance. let uniform_index = Uniform::new(0, n); let uniform_within_weight_sum = Uniform::new(W::ZERO, weight_sum); Ok(Self { aliases: aliases.aliases, no_alias_odds, uniform_index, uniform_within_weight_sum, }) } } impl Distribution for WeightedIndex { fn sample(&self, rng: &mut R) -> usize { let candidate = rng.sample(self.uniform_index); if rng.sample(&self.uniform_within_weight_sum) < self.no_alias_odds[candidate as usize] { candidate as usize } else { self.aliases[candidate as usize] as usize } } } impl fmt::Debug for WeightedIndex where W: fmt::Debug, Uniform: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("WeightedIndex") .field("aliases", &self.aliases) .field("no_alias_odds", &self.no_alias_odds) .field("uniform_index", &self.uniform_index) .field("uniform_within_weight_sum", &self.uniform_within_weight_sum) .finish() } } impl Clone for WeightedIndex where Uniform: Clone, { fn clone(&self) -> Self { Self { aliases: self.aliases.clone(), no_alias_odds: self.no_alias_odds.clone(), uniform_index: self.uniform_index.clone(), uniform_within_weight_sum: self.uniform_within_weight_sum.clone(), } } } /// Trait that must be implemented for weights, that are used with /// [`WeightedIndex`]. Currently no guarantees on the correctness of /// [`WeightedIndex`] are given for custom implementations of this trait. pub trait Weight: Sized + Copy + SampleUniform + PartialOrd + Add + AddAssign + Sub + SubAssign + Mul + MulAssign + Div + DivAssign + Sum { /// Maximum number representable by `Self`. const MAX: Self; /// Element of `Self` equivalent to 0. const ZERO: Self; /// Produce an instance of `Self` from a `u32` value, or return `None` if /// out of range. Loss of precision (where `Self` is a floating point type) /// is acceptable. fn try_from_u32_lossy(n: u32) -> Option; /// Sums all values in slice `values`. fn sum(values: &[Self]) -> Self { values.iter().map(|x| *x).sum() } } macro_rules! impl_weight_for_float { ($T: ident) => { impl Weight for $T { const MAX: Self = ::core::$T::MAX; const ZERO: Self = 0.0; fn try_from_u32_lossy(n: u32) -> Option { Some(n as $T) } fn sum(values: &[Self]) -> Self { pairwise_sum(values) } } }; } /// In comparison to naive accumulation, the pairwise sum algorithm reduces /// rounding errors when there are many floating point values. fn pairwise_sum(values: &[T]) -> T { if values.len() <= 32 { values.iter().map(|x| *x).sum() } else { let mid = values.len() / 2; let (a, b) = values.split_at(mid); pairwise_sum(a) + pairwise_sum(b) } } macro_rules! impl_weight_for_int { ($T: ident) => { impl Weight for $T { const MAX: Self = ::core::$T::MAX; const ZERO: Self = 0; fn try_from_u32_lossy(n: u32) -> Option { let n_converted = n as Self; if n_converted >= Self::ZERO && n_converted as u32 == n { Some(n_converted) } else { None } } } }; } impl_weight_for_float!(f64); impl_weight_for_float!(f32); impl_weight_for_int!(usize); #[cfg(not(target_os = "emscripten"))] impl_weight_for_int!(u128); impl_weight_for_int!(u64); impl_weight_for_int!(u32); impl_weight_for_int!(u16); impl_weight_for_int!(u8); impl_weight_for_int!(isize); #[cfg(not(target_os = "emscripten"))] impl_weight_for_int!(i128); impl_weight_for_int!(i64); impl_weight_for_int!(i32); impl_weight_for_int!(i16); impl_weight_for_int!(i8); #[cfg(test)] mod test { use super::*; #[test] #[cfg(not(miri))] // Miri is too slow fn test_weighted_index_f32() { test_weighted_index(f32::into); // Floating point special cases assert_eq!( WeightedIndex::new(vec![::core::f32::INFINITY]).unwrap_err(), WeightedError::InvalidWeight ); assert_eq!( WeightedIndex::new(vec![-0_f32]).unwrap_err(), WeightedError::AllWeightsZero ); assert_eq!( WeightedIndex::new(vec![-1_f32]).unwrap_err(), WeightedError::InvalidWeight ); assert_eq!( WeightedIndex::new(vec![-::core::f32::INFINITY]).unwrap_err(), WeightedError::InvalidWeight ); assert_eq!( WeightedIndex::new(vec![::core::f32::NAN]).unwrap_err(), WeightedError::InvalidWeight ); } #[cfg(not(target_os = "emscripten"))] #[test] #[cfg(not(miri))] // Miri is too slow fn test_weighted_index_u128() { test_weighted_index(|x: u128| x as f64); } #[cfg(all(rustc_1_26, not(target_os = "emscripten")))] #[test] #[cfg(not(miri))] // Miri is too slow fn test_weighted_index_i128() { test_weighted_index(|x: i128| x as f64); // Signed integer special cases assert_eq!( WeightedIndex::new(vec![-1_i128]).unwrap_err(), WeightedError::InvalidWeight ); assert_eq!( WeightedIndex::new(vec![::core::i128::MIN]).unwrap_err(), WeightedError::InvalidWeight ); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_weighted_index_u8() { test_weighted_index(u8::into); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_weighted_index_i8() { test_weighted_index(i8::into); // Signed integer special cases assert_eq!( WeightedIndex::new(vec![-1_i8]).unwrap_err(), WeightedError::InvalidWeight ); assert_eq!( WeightedIndex::new(vec![::core::i8::MIN]).unwrap_err(), WeightedError::InvalidWeight ); } fn test_weighted_index f64>(w_to_f64: F) where WeightedIndex: fmt::Debug, { const NUM_WEIGHTS: u32 = 10; const ZERO_WEIGHT_INDEX: u32 = 3; const NUM_SAMPLES: u32 = 15000; let mut rng = crate::test::rng(0x9c9fa0b0580a7031); let weights = { let mut weights = Vec::with_capacity(NUM_WEIGHTS as usize); let random_weight_distribution = crate::distributions::Uniform::new_inclusive( W::ZERO, W::MAX / W::try_from_u32_lossy(NUM_WEIGHTS).unwrap(), ); for _ in 0..NUM_WEIGHTS { weights.push(rng.sample(&random_weight_distribution)); } weights[ZERO_WEIGHT_INDEX as usize] = W::ZERO; weights }; let weight_sum = weights.iter().map(|w| *w).sum::(); let expected_counts = weights .iter() .map(|&w| w_to_f64(w) / w_to_f64(weight_sum) * NUM_SAMPLES as f64) .collect::>(); let weight_distribution = WeightedIndex::new(weights).unwrap(); let mut counts = vec![0; NUM_WEIGHTS as usize]; for _ in 0..NUM_SAMPLES { counts[rng.sample(&weight_distribution)] += 1; } assert_eq!(counts[ZERO_WEIGHT_INDEX as usize], 0); for (count, expected_count) in counts.into_iter().zip(expected_counts) { let difference = (count as f64 - expected_count).abs(); let max_allowed_difference = NUM_SAMPLES as f64 / NUM_WEIGHTS as f64 * 0.1; assert!(difference <= max_allowed_difference); } assert_eq!( WeightedIndex::::new(vec![]).unwrap_err(), WeightedError::NoItem ); assert_eq!( WeightedIndex::new(vec![W::ZERO]).unwrap_err(), WeightedError::AllWeightsZero ); assert_eq!( WeightedIndex::new(vec![W::MAX, W::MAX]).unwrap_err(), WeightedError::InvalidWeight ); } #[test] fn value_stability() { fn test_samples(weights: Vec, buf: &mut [usize], expected: &[usize]) { assert_eq!(buf.len(), expected.len()); let distr = WeightedIndex::new(weights).unwrap(); let mut rng = crate::test::rng(0x9c9fa0b0580a7031); for r in buf.iter_mut() { *r = rng.sample(&distr); } assert_eq!(buf, expected); } let mut buf = [0; 10]; test_samples(vec![1i32,1,1,1,1,1,1,1,1], &mut buf, &[6, 5, 7, 5, 8, 7, 6, 2, 3, 7]); test_samples(vec![0.7f32, 0.1, 0.1, 0.1], &mut buf, &[2, 0, 0, 0, 0, 0, 0, 0, 1, 3]); test_samples(vec![1.0f64, 0.999, 0.998, 0.997], &mut buf, &[2, 1, 2, 3, 2, 1, 3, 2, 1, 1]); } } rand-0.7.2/src/distributions/weighted/mod.rs010064400017500001750000000342401353740054500173140ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Weighted index sampling //! //! This module provides two implementations for sampling indices: //! //! * [`WeightedIndex`] allows `O(log N)` sampling //! * [`alias_method::WeightedIndex`] allows `O(1)` sampling, but with //! much greater set-up cost //! //! [`alias_method::WeightedIndex`]: alias_method/struct.WeightedIndex.html pub mod alias_method; use crate::Rng; use crate::distributions::Distribution; use crate::distributions::uniform::{UniformSampler, SampleUniform, SampleBorrow}; use core::cmp::PartialOrd; use core::fmt; // Note that this whole module is only imported if feature="alloc" is enabled. #[cfg(not(feature="std"))] use crate::alloc::vec::Vec; /// A distribution using weighted sampling to pick a discretely selected /// item. /// /// Sampling a `WeightedIndex` distribution returns the index of a randomly /// selected element from the iterator used when the `WeightedIndex` was /// created. The chance of a given element being picked is proportional to the /// value of the element. The weights can use any type `X` for which an /// implementation of [`Uniform`] exists. /// /// # Performance /// /// A `WeightedIndex` contains a `Vec` and a [`Uniform`] and so its /// size is the sum of the size of those objects, possibly plus some alignment. /// /// Creating a `WeightedIndex` will allocate enough space to hold `N - 1` /// weights of type `X`, where `N` is the number of weights. However, since /// `Vec` doesn't guarantee a particular growth strategy, additional memory /// might be allocated but not used. Since the `WeightedIndex` object also /// contains, this might cause additional allocations, though for primitive /// types, ['Uniform`] doesn't allocate any memory. /// /// Time complexity of sampling from `WeightedIndex` is `O(log N)` where /// `N` is the number of weights. /// /// Sampling from `WeightedIndex` will result in a single call to /// `Uniform::sample` (method of the [`Distribution`] trait), which typically /// will request a single value from the underlying [`RngCore`], though the /// exact number depends on the implementaiton of `Uniform::sample`. /// /// # Example /// /// ``` /// use rand::prelude::*; /// use rand::distributions::WeightedIndex; /// /// let choices = ['a', 'b', 'c']; /// let weights = [2, 1, 1]; /// let dist = WeightedIndex::new(&weights).unwrap(); /// let mut rng = thread_rng(); /// for _ in 0..100 { /// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c' /// println!("{}", choices[dist.sample(&mut rng)]); /// } /// /// let items = [('a', 0), ('b', 3), ('c', 7)]; /// let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap(); /// for _ in 0..100 { /// // 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c' /// println!("{}", items[dist2.sample(&mut rng)].0); /// } /// ``` /// /// [`Uniform`]: crate::distributions::uniform::Uniform /// [`RngCore`]: crate::RngCore #[derive(Debug, Clone)] pub struct WeightedIndex { cumulative_weights: Vec, total_weight: X, weight_distribution: X::Sampler, } impl WeightedIndex { /// Creates a new a `WeightedIndex` [`Distribution`] using the values /// in `weights`. The weights can use any type `X` for which an /// implementation of [`Uniform`] exists. /// /// Returns an error if the iterator is empty, if any weight is `< 0`, or /// if its total value is 0. /// /// [`Uniform`]: crate::distributions::uniform::Uniform pub fn new(weights: I) -> Result, WeightedError> where I: IntoIterator, I::Item: SampleBorrow, X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default { let mut iter = weights.into_iter(); let mut total_weight: X = iter.next() .ok_or(WeightedError::NoItem)? .borrow() .clone(); let zero = ::default(); if total_weight < zero { return Err(WeightedError::InvalidWeight); } let mut weights = Vec::::with_capacity(iter.size_hint().0); for w in iter { if *w.borrow() < zero { return Err(WeightedError::InvalidWeight); } weights.push(total_weight.clone()); total_weight += w.borrow(); } if total_weight == zero { return Err(WeightedError::AllWeightsZero); } let distr = X::Sampler::new(zero, total_weight.clone()); Ok(WeightedIndex { cumulative_weights: weights, total_weight, weight_distribution: distr }) } /// Update a subset of weights, without changing the number of weights. /// /// `new_weights` must be sorted by the index. /// /// Using this method instead of `new` might be more efficient if only a small number of /// weights is modified. No allocations are performed, unless the weight type `X` uses /// allocation internally. /// /// In case of error, `self` is not modified. pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), WeightedError> where X: for<'a> ::core::ops::AddAssign<&'a X> + for<'a> ::core::ops::SubAssign<&'a X> + Clone + Default { if new_weights.is_empty() { return Ok(()); } let zero = ::default(); let mut total_weight = self.total_weight.clone(); // Check for errors first, so we don't modify `self` in case something // goes wrong. let mut prev_i = None; for &(i, w) in new_weights { if let Some(old_i) = prev_i { if old_i >= i { return Err(WeightedError::InvalidWeight); } } if *w < zero { return Err(WeightedError::InvalidWeight); } if i >= self.cumulative_weights.len() + 1 { return Err(WeightedError::TooMany); } let mut old_w = if i < self.cumulative_weights.len() { self.cumulative_weights[i].clone() } else { self.total_weight.clone() }; if i > 0 { old_w -= &self.cumulative_weights[i - 1]; } total_weight -= &old_w; total_weight += w; prev_i = Some(i); } if total_weight == zero { return Err(WeightedError::AllWeightsZero); } // Update the weights. Because we checked all the preconditions in the // previous loop, this should never panic. let mut iter = new_weights.iter(); let mut prev_weight = zero.clone(); let mut next_new_weight = iter.next(); let &(first_new_index, _) = next_new_weight.unwrap(); let mut cumulative_weight = if first_new_index > 0 { self.cumulative_weights[first_new_index - 1].clone() } else { zero.clone() }; for i in first_new_index..self.cumulative_weights.len() { match next_new_weight { Some(&(j, w)) if i == j => { cumulative_weight += w; next_new_weight = iter.next(); }, _ => { let mut tmp = self.cumulative_weights[i].clone(); tmp -= &prev_weight; // We know this is positive. cumulative_weight += &tmp; } } prev_weight = cumulative_weight.clone(); core::mem::swap(&mut prev_weight, &mut self.cumulative_weights[i]); } self.total_weight = total_weight; self.weight_distribution = X::Sampler::new(zero, self.total_weight.clone()); Ok(()) } } impl Distribution for WeightedIndex where X: SampleUniform + PartialOrd { fn sample(&self, rng: &mut R) -> usize { use ::core::cmp::Ordering; let chosen_weight = self.weight_distribution.sample(rng); // Find the first item which has a weight *higher* than the chosen weight. self.cumulative_weights.binary_search_by( |w| if *w <= chosen_weight { Ordering::Less } else { Ordering::Greater }).unwrap_err() } } #[cfg(test)] mod test { use super::*; #[test] #[cfg(not(miri))] // Miri is too slow fn test_weightedindex() { let mut r = crate::test::rng(700); const N_REPS: u32 = 5000; let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; let total_weight = weights.iter().sum::() as f32; let verify = |result: [i32; 14]| { for (i, count) in result.iter().enumerate() { let exp = (weights[i] * N_REPS) as f32 / total_weight; let mut err = (*count as f32 - exp).abs(); if err != 0.0 { err /= exp; } assert!(err <= 0.25); } }; // WeightedIndex from vec let mut chosen = [0i32; 14]; let distr = WeightedIndex::new(weights.to_vec()).unwrap(); for _ in 0..N_REPS { chosen[distr.sample(&mut r)] += 1; } verify(chosen); // WeightedIndex from slice chosen = [0i32; 14]; let distr = WeightedIndex::new(&weights[..]).unwrap(); for _ in 0..N_REPS { chosen[distr.sample(&mut r)] += 1; } verify(chosen); // WeightedIndex from iterator chosen = [0i32; 14]; let distr = WeightedIndex::new(weights.iter()).unwrap(); for _ in 0..N_REPS { chosen[distr.sample(&mut r)] += 1; } verify(chosen); for _ in 0..5 { assert_eq!(WeightedIndex::new(&[0, 1]).unwrap().sample(&mut r), 1); assert_eq!(WeightedIndex::new(&[1, 0]).unwrap().sample(&mut r), 0); assert_eq!(WeightedIndex::new(&[0, 0, 0, 0, 10, 0]).unwrap().sample(&mut r), 4); } assert_eq!(WeightedIndex::new(&[10][0..0]).unwrap_err(), WeightedError::NoItem); assert_eq!(WeightedIndex::new(&[0]).unwrap_err(), WeightedError::AllWeightsZero); assert_eq!(WeightedIndex::new(&[10, 20, -1, 30]).unwrap_err(), WeightedError::InvalidWeight); assert_eq!(WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(), WeightedError::InvalidWeight); assert_eq!(WeightedIndex::new(&[-10]).unwrap_err(), WeightedError::InvalidWeight); } #[test] fn test_update_weights() { let data = [ (&[10u32, 2, 3, 4][..], &[(1, &100), (2, &4)][..], // positive change &[10, 100, 4, 4][..]), (&[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], &[(2, &1), (5, &1), (13, &100)][..], // negative change and last element &[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..]), ]; for (weights, update, expected_weights) in data.into_iter() { let total_weight = weights.iter().sum::(); let mut distr = WeightedIndex::new(weights.to_vec()).unwrap(); assert_eq!(distr.total_weight, total_weight); distr.update_weights(update).unwrap(); let expected_total_weight = expected_weights.iter().sum::(); let expected_distr = WeightedIndex::new(expected_weights.to_vec()).unwrap(); assert_eq!(distr.total_weight, expected_total_weight); assert_eq!(distr.total_weight, expected_distr.total_weight); assert_eq!(distr.cumulative_weights, expected_distr.cumulative_weights); } } #[test] fn value_stability() { fn test_samples ( weights: I, buf: &mut [usize], expected: &[usize] ) where I: IntoIterator, I::Item: SampleBorrow, X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default { assert_eq!(buf.len(), expected.len()); let distr = WeightedIndex::new(weights).unwrap(); let mut rng = crate::test::rng(701); for r in buf.iter_mut() { *r = rng.sample(&distr); } assert_eq!(buf, expected); } let mut buf = [0; 10]; test_samples(&[1i32,1,1,1,1,1,1,1,1], &mut buf, &[0, 6, 2, 6, 3, 4, 7, 8, 2, 5]); test_samples(&[0.7f32, 0.1, 0.1, 0.1], &mut buf, &[0, 0, 0, 1, 0, 0, 2, 3, 0, 0]); test_samples(&[1.0f64, 0.999, 0.998, 0.997], &mut buf, &[2, 2, 1, 3, 2, 1, 3, 3, 2, 1]); } } /// Error type returned from `WeightedIndex::new`. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum WeightedError { /// The provided weight collection contains no items. NoItem, /// A weight is either less than zero, greater than the supported maximum or /// otherwise invalid. InvalidWeight, /// All items in the provided weight collection are zero. AllWeightsZero, /// Too many weights are provided (length greater than `u32::MAX`) TooMany, } impl WeightedError { fn msg(&self) -> &str { match *self { WeightedError::NoItem => "No weights provided.", WeightedError::InvalidWeight => "A weight is invalid.", WeightedError::AllWeightsZero => "All weights are zero.", WeightedError::TooMany => "Too many weights (hit u32::MAX)", } } } #[cfg(feature="std")] impl ::std::error::Error for WeightedError { fn description(&self) -> &str { self.msg() } fn cause(&self) -> Option<&dyn (::std::error::Error)> { None } } impl fmt::Display for WeightedError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.msg()) } } rand-0.7.2/src/distributions/ziggurat_tables.rs010064400017500001750000000602241347154030000201130ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Tables for distributions which are sampled using the ziggurat // algorithm. Autogenerated by `ziggurat_tables.py`. pub type ZigTable = &'static [f64; 257]; pub const ZIG_NORM_R: f64 = 3.654152885361008796; pub static ZIG_NORM_X: [f64; 257] = [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074, 3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434, 2.978603279880844834, 2.934366867207854224, 2.894121053612348060, 2.857138730872132548, 2.822877396825325125, 2.790921174000785765, 2.760944005278822555, 2.732685359042827056, 2.705933656121858100, 2.680514643284522158, 2.656283037575502437, 2.633116393630324570, 2.610910518487548515, 2.589575986706995181, 2.569035452680536569, 2.549221550323460761, 2.530075232158516929, 2.511544441625342294, 2.493583041269680667, 2.476149939669143318, 2.459208374333311298, 2.442725318198956774, 2.426670984935725972, 2.411018413899685520, 2.395743119780480601, 2.380822795170626005, 2.366237056715818632, 2.351967227377659952, 2.337996148795031370, 2.324308018869623016, 2.310888250599850036, 2.297723348901329565, 2.284800802722946056, 2.272108990226823888, 2.259637095172217780, 2.247375032945807760, 2.235313384928327984, 2.223443340090905718, 2.211756642882544366, 2.200245546609647995, 2.188902771624720689, 2.177721467738641614, 2.166695180352645966, 2.155817819875063268, 2.145083634046203613, 2.134487182844320152, 2.124023315687815661, 2.113687150684933957, 2.103474055713146829, 2.093379631137050279, 2.083399693996551783, 2.073530263516978778, 2.063767547809956415, 2.054107931648864849, 2.044547965215732788, 2.035084353727808715, 2.025713947862032960, 2.016433734904371722, 2.007240830558684852, 1.998132471356564244, 1.989106007615571325, 1.980158896898598364, 1.971288697931769640, 1.962493064942461896, 1.953769742382734043, 1.945116560006753925, 1.936531428273758904, 1.928012334050718257, 1.919557336591228847, 1.911164563769282232, 1.902832208548446369, 1.894558525668710081, 1.886341828534776388, 1.878180486290977669, 1.870072921069236838, 1.862017605397632281, 1.854013059758148119, 1.846057850283119750, 1.838150586580728607, 1.830289919680666566, 1.822474540091783224, 1.814703175964167636, 1.806974591348693426, 1.799287584547580199, 1.791640986550010028, 1.784033659547276329, 1.776464495522344977, 1.768932414909077933, 1.761436365316706665, 1.753975320315455111, 1.746548278279492994, 1.739154261283669012, 1.731792314050707216, 1.724461502945775715, 1.717160915015540690, 1.709889657069006086, 1.702646854797613907, 1.695431651932238548, 1.688243209434858727, 1.681080704722823338, 1.673943330923760353, 1.666830296159286684, 1.659740822855789499, 1.652674147080648526, 1.645629517902360339, 1.638606196773111146, 1.631603456932422036, 1.624620582830568427, 1.617656869570534228, 1.610711622367333673, 1.603784156023583041, 1.596873794420261339, 1.589979870021648534, 1.583101723393471438, 1.576238702733332886, 1.569390163412534456, 1.562555467528439657, 1.555733983466554893, 1.548925085471535512, 1.542128153226347553, 1.535342571438843118, 1.528567729435024614, 1.521803020758293101, 1.515047842773992404, 1.508301596278571965, 1.501563685112706548, 1.494833515777718391, 1.488110497054654369, 1.481394039625375747, 1.474683555695025516, 1.467978458615230908, 1.461278162507407830, 1.454582081885523293, 1.447889631277669675, 1.441200224845798017, 1.434513276002946425, 1.427828197027290358, 1.421144398672323117, 1.414461289772464658, 1.407778276843371534, 1.401094763676202559, 1.394410150925071257, 1.387723835686884621, 1.381035211072741964, 1.374343665770030531, 1.367648583594317957, 1.360949343030101844, 1.354245316759430606, 1.347535871177359290, 1.340820365893152122, 1.334098153216083604, 1.327368577624624679, 1.320630975217730096, 1.313884673146868964, 1.307128989027353860, 1.300363230327433728, 1.293586693733517645, 1.286798664489786415, 1.279998415710333237, 1.273185207661843732, 1.266358287014688333, 1.259516886060144225, 1.252660221891297887, 1.245787495544997903, 1.238897891102027415, 1.231990574742445110, 1.225064693752808020, 1.218119375481726552, 1.211153726239911244, 1.204166830140560140, 1.197157747875585931, 1.190125515422801650, 1.183069142678760732, 1.175987612011489825, 1.168879876726833800, 1.161744859441574240, 1.154581450355851802, 1.147388505416733873, 1.140164844363995789, 1.132909248648336975, 1.125620459211294389, 1.118297174115062909, 1.110938046009249502, 1.103541679420268151, 1.096106627847603487, 1.088631390649514197, 1.081114409698889389, 1.073554065787871714, 1.065948674757506653, 1.058296483326006454, 1.050595664586207123, 1.042844313139370538, 1.035040439828605274, 1.027181966030751292, 1.019266717460529215, 1.011292417434978441, 1.003256679539591412, 0.995156999629943084, 0.986990747093846266, 0.978755155288937750, 0.970447311058864615, 0.962064143217605250, 0.953602409875572654, 0.945058684462571130, 0.936429340280896860, 0.927710533396234771, 0.918898183643734989, 0.909987953490768997, 0.900975224455174528, 0.891855070726792376, 0.882622229578910122, 0.873271068082494550, 0.863795545546826915, 0.854189171001560554, 0.844444954902423661, 0.834555354079518752, 0.824512208745288633, 0.814306670128064347, 0.803929116982664893, 0.793369058833152785, 0.782615023299588763, 0.771654424216739354, 0.760473406422083165, 0.749056662009581653, 0.737387211425838629, 0.725446140901303549, 0.713212285182022732, 0.700661841097584448, 0.687767892786257717, 0.674499822827436479, 0.660822574234205984, 0.646695714884388928, 0.632072236375024632, 0.616896989996235545, 0.601104617743940417, 0.584616766093722262, 0.567338257040473026, 0.549151702313026790, 0.529909720646495108, 0.509423329585933393, 0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746, 0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806, 0.000000000000000000]; pub static ZIG_NORM_F: [f64; 257] = [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872, 0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100, 0.011842757857943104, 0.013497450601780807, 0.015177088307982072, 0.016880083152595839, 0.018605121275783350, 0.020351096230109354, 0.022117062707379922, 0.023902203305873237, 0.025705804008632656, 0.027527235669693315, 0.029365939758230111, 0.031221417192023690, 0.033093219458688698, 0.034980941461833073, 0.036884215688691151, 0.038802707404656918, 0.040736110656078753, 0.042684144916619378, 0.044646552251446536, 0.046623094902089664, 0.048613553216035145, 0.050617723861121788, 0.052635418276973649, 0.054666461325077916, 0.056710690106399467, 0.058767952921137984, 0.060838108349751806, 0.062921024437977854, 0.065016577971470438, 0.067124653828023989, 0.069245144397250269, 0.071377949059141965, 0.073522973714240991, 0.075680130359194964, 0.077849336702372207, 0.080030515814947509, 0.082223595813495684, 0.084428509570654661, 0.086645194450867782, 0.088873592068594229, 0.091113648066700734, 0.093365311913026619, 0.095628536713353335, 0.097903279039215627, 0.100189498769172020, 0.102487158942306270, 0.104796225622867056, 0.107116667775072880, 0.109448457147210021, 0.111791568164245583, 0.114145977828255210, 0.116511665626037014, 0.118888613443345698, 0.121276805485235437, 0.123676228202051403, 0.126086870220650349, 0.128508722280473636, 0.130941777174128166, 0.133386029692162844, 0.135841476571757352, 0.138308116449064322, 0.140785949814968309, 0.143274978974047118, 0.145775208006537926, 0.148286642733128721, 0.150809290682410169, 0.153343161060837674, 0.155888264725064563, 0.158444614156520225, 0.161012223438117663, 0.163591108232982951, 0.166181285765110071, 0.168782774801850333, 0.171395595638155623, 0.174019770082499359, 0.176655321444406654, 0.179302274523530397, 0.181960655600216487, 0.184630492427504539, 0.187311814224516926, 0.190004651671193070, 0.192709036904328807, 0.195425003514885592, 0.198152586546538112, 0.200891822495431333, 0.203642749311121501, 0.206405406398679298, 0.209179834621935651, 0.211966076307852941, 0.214764175252008499, 0.217574176725178370, 0.220396127481011589, 0.223230075764789593, 0.226076071323264877, 0.228934165415577484, 0.231804410825248525, 0.234686861873252689, 0.237581574432173676, 0.240488605941449107, 0.243408015423711988, 0.246339863502238771, 0.249284212419516704, 0.252241126056943765, 0.255210669955677150, 0.258192911338648023, 0.261187919133763713, 0.264195763998317568, 0.267216518344631837, 0.270250256366959984, 0.273297054069675804, 0.276356989296781264, 0.279430141762765316, 0.282516593084849388, 0.285616426816658109, 0.288729728483353931, 0.291856585618280984, 0.294997087801162572, 0.298151326697901342, 0.301319396102034120, 0.304501391977896274, 0.307697412505553769, 0.310907558127563710, 0.314131931597630143, 0.317370638031222396, 0.320623784958230129, 0.323891482377732021, 0.327173842814958593, 0.330470981380537099, 0.333783015832108509, 0.337110066638412809, 0.340452257045945450, 0.343809713148291340, 0.347182563958251478, 0.350570941482881204, 0.353974980801569250, 0.357394820147290515, 0.360830600991175754, 0.364282468130549597, 0.367750569780596226, 0.371235057669821344, 0.374736087139491414, 0.378253817247238111, 0.381788410875031348, 0.385340034841733958, 0.388908860020464597, 0.392495061461010764, 0.396098818517547080, 0.399720314981931668, 0.403359739222868885, 0.407017284331247953, 0.410693148271983222, 0.414387534042706784, 0.418100649839684591, 0.421832709231353298, 0.425583931339900579, 0.429354541031341519, 0.433144769114574058, 0.436954852549929273, 0.440785034667769915, 0.444635565397727750, 0.448506701509214067, 0.452398706863882505, 0.456311852680773566, 0.460246417814923481, 0.464202689050278838, 0.468180961407822172, 0.472181538469883255, 0.476204732721683788, 0.480250865911249714, 0.484320269428911598, 0.488413284707712059, 0.492530263646148658, 0.496671569054796314, 0.500837575128482149, 0.505028667945828791, 0.509245245998136142, 0.513487720749743026, 0.517756517232200619, 0.522052074674794864, 0.526374847174186700, 0.530725304406193921, 0.535103932383019565, 0.539511234259544614, 0.543947731192649941, 0.548413963257921133, 0.552910490428519918, 0.557437893621486324, 0.561996775817277916, 0.566587763258951771, 0.571211506738074970, 0.575868682975210544, 0.580559996103683473, 0.585286179266300333, 0.590047996335791969, 0.594846243770991268, 0.599681752622167719, 0.604555390700549533, 0.609468064928895381, 0.614420723892076803, 0.619414360609039205, 0.624450015550274240, 0.629528779928128279, 0.634651799290960050, 0.639820277456438991, 0.645035480824251883, 0.650298743114294586, 0.655611470583224665, 0.660975147780241357, 0.666391343912380640, 0.671861719900766374, 0.677388036222513090, 0.682972161648791376, 0.688616083008527058, 0.694321916130032579, 0.700091918140490099, 0.705928501336797409, 0.711834248882358467, 0.717811932634901395, 0.723864533472881599, 0.729995264565802437, 0.736207598131266683, 0.742505296344636245, 0.748892447223726720, 0.755373506511754500, 0.761953346841546475, 0.768637315803334831, 0.775431304986138326, 0.782341832659861902, 0.789376143571198563, 0.796542330428254619, 0.803849483176389490, 0.811307874318219935, 0.818929191609414797, 0.826726833952094231, 0.834716292992930375, 0.842915653118441077, 0.851346258465123684, 0.860033621203008636, 0.869008688043793165, 0.878309655816146839, 0.887984660763399880, 0.898095921906304051, 0.908726440060562912, 0.919991505048360247, 0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328, 1.000000000000000000]; pub const ZIG_EXP_R: f64 = 7.697117470131050077; pub static ZIG_EXP_X: [f64; 257] = [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696, 6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488, 5.323090505754398016, 5.181487281301500047, 5.054288489981304089, 4.938777085901250530, 4.832939741025112035, 4.735242996601741083, 4.644491885420085175, 4.559737061707351380, 4.480211746528421912, 4.405287693473573185, 4.334443680317273007, 4.267242480277365857, 4.203313713735184365, 4.142340865664051464, 4.084051310408297830, 4.028208544647936762, 3.974606066673788796, 3.923062500135489739, 3.873417670399509127, 3.825529418522336744, 3.779270992411667862, 3.734528894039797375, 3.691201090237418825, 3.649195515760853770, 3.608428813128909507, 3.568825265648337020, 3.530315889129343354, 3.492837654774059608, 3.456332821132760191, 3.420748357251119920, 3.386035442460300970, 3.352149030900109405, 3.319047470970748037, 3.286692171599068679, 3.255047308570449882, 3.224079565286264160, 3.193757903212240290, 3.164053358025972873, 3.134938858084440394, 3.106389062339824481, 3.078380215254090224, 3.050890016615455114, 3.023897504455676621, 2.997382949516130601, 2.971327759921089662, 2.945714394895045718, 2.920526286512740821, 2.895747768600141825, 2.871364012015536371, 2.847360965635188812, 2.823725302450035279, 2.800444370250737780, 2.777506146439756574, 2.754899196562344610, 2.732612636194700073, 2.710636095867928752, 2.688959688741803689, 2.667573980773266573, 2.646469963151809157, 2.625639026797788489, 2.605072938740835564, 2.584763820214140750, 2.564704126316905253, 2.544886627111869970, 2.525304390037828028, 2.505950763528594027, 2.486819361740209455, 2.467904050297364815, 2.449198932978249754, 2.430698339264419694, 2.412396812688870629, 2.394289099921457886, 2.376370140536140596, 2.358635057409337321, 2.341079147703034380, 2.323697874390196372, 2.306486858283579799, 2.289441870532269441, 2.272558825553154804, 2.255833774367219213, 2.239262898312909034, 2.222842503111036816, 2.206569013257663858, 2.190438966723220027, 2.174449009937774679, 2.158595893043885994, 2.142876465399842001, 2.127287671317368289, 2.111826546019042183, 2.096490211801715020, 2.081275874393225145, 2.066180819490575526, 2.051202409468584786, 2.036338080248769611, 2.021585338318926173, 2.006941757894518563, 1.992404978213576650, 1.977972700957360441, 1.963642687789548313, 1.949412758007184943, 1.935280786297051359, 1.921244700591528076, 1.907302480018387536, 1.893452152939308242, 1.879691795072211180, 1.866019527692827973, 1.852433515911175554, 1.838931967018879954, 1.825513128903519799, 1.812175288526390649, 1.798916770460290859, 1.785735935484126014, 1.772631179231305643, 1.759600930889074766, 1.746643651946074405, 1.733757834985571566, 1.720942002521935299, 1.708194705878057773, 1.695514524101537912, 1.682900062917553896, 1.670349953716452118, 1.657862852574172763, 1.645437439303723659, 1.633072416535991334, 1.620766508828257901, 1.608518461798858379, 1.596327041286483395, 1.584191032532688892, 1.572109239386229707, 1.560080483527888084, 1.548103603714513499, 1.536177455041032092, 1.524300908219226258, 1.512472848872117082, 1.500692176842816750, 1.488957805516746058, 1.477268661156133867, 1.465623682245745352, 1.454021818848793446, 1.442462031972012504, 1.430943292938879674, 1.419464582769983219, 1.408024891569535697, 1.396623217917042137, 1.385258568263121992, 1.373929956328490576, 1.362636402505086775, 1.351376933258335189, 1.340150580529504643, 1.328956381137116560, 1.317793376176324749, 1.306660610415174117, 1.295557131686601027, 1.284481990275012642, 1.273434238296241139, 1.262412929069615330, 1.251417116480852521, 1.240445854334406572, 1.229498195693849105, 1.218573192208790124, 1.207669893426761121, 1.196787346088403092, 1.185924593404202199, 1.175080674310911677, 1.164254622705678921, 1.153445466655774743, 1.142652227581672841, 1.131873919411078511, 1.121109547701330200, 1.110358108727411031, 1.099618588532597308, 1.088889961938546813, 1.078171191511372307, 1.067461226479967662, 1.056759001602551429, 1.046063435977044209, 1.035373431790528542, 1.024687873002617211, 1.014005623957096480, 1.003325527915696735, 0.992646405507275897, 0.981967053085062602, 0.971286240983903260, 0.960602711668666509, 0.949915177764075969, 0.939222319955262286, 0.928522784747210395, 0.917815182070044311, 0.907098082715690257, 0.896370015589889935, 0.885629464761751528, 0.874874866291025066, 0.864104604811004484, 0.853317009842373353, 0.842510351810368485, 0.831682837734273206, 0.820832606554411814, 0.809957724057418282, 0.799056177355487174, 0.788125868869492430, 0.777164609759129710, 0.766170112735434672, 0.755139984181982249, 0.744071715500508102, 0.732962673584365398, 0.721810090308756203, 0.710611050909655040, 0.699362481103231959, 0.688061132773747808, 0.676703568029522584, 0.665286141392677943, 0.653804979847664947, 0.642255960424536365, 0.630634684933490286, 0.618936451394876075, 0.607156221620300030, 0.595288584291502887, 0.583327712748769489, 0.571267316532588332, 0.559100585511540626, 0.546820125163310577, 0.534417881237165604, 0.521885051592135052, 0.509211982443654398, 0.496388045518671162, 0.483401491653461857, 0.470239275082169006, 0.456886840931420235, 0.443327866073552401, 0.429543940225410703, 0.415514169600356364, 0.401214678896277765, 0.386617977941119573, 0.371692145329917234, 0.356399760258393816, 0.340696481064849122, 0.324529117016909452, 0.307832954674932158, 0.290527955491230394, 0.272513185478464703, 0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842, 0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570, 0.000000000000000000]; pub static ZIG_EXP_F: [f64; 257] = [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573, 0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797, 0.004877655983542396, 0.005619642207205489, 0.006381905937319183, 0.007163353183634991, 0.007963077438017043, 0.008780314985808977, 0.009614413642502212, 0.010464810181029981, 0.011331013597834600, 0.012212592426255378, 0.013109164931254991, 0.014020391403181943, 0.014945968011691148, 0.015885621839973156, 0.016839106826039941, 0.017806200410911355, 0.018786700744696024, 0.019780424338009740, 0.020787204072578114, 0.021806887504283581, 0.022839335406385240, 0.023884420511558174, 0.024942026419731787, 0.026012046645134221, 0.027094383780955803, 0.028188948763978646, 0.029295660224637411, 0.030414443910466622, 0.031545232172893622, 0.032687963508959555, 0.033842582150874358, 0.035009037697397431, 0.036187284781931443, 0.037377282772959382, 0.038578995503074871, 0.039792391023374139, 0.041017441380414840, 0.042254122413316254, 0.043502413568888197, 0.044762297732943289, 0.046033761076175184, 0.047316792913181561, 0.048611385573379504, 0.049917534282706379, 0.051235237055126281, 0.052564494593071685, 0.053905310196046080, 0.055257689676697030, 0.056621641283742870, 0.057997175631200659, 0.059384305633420280, 0.060783046445479660, 0.062193415408541036, 0.063615431999807376, 0.065049117786753805, 0.066494496385339816, 0.067951593421936643, 0.069420436498728783, 0.070901055162371843, 0.072393480875708752, 0.073897746992364746, 0.075413888734058410, 0.076941943170480517, 0.078481949201606435, 0.080033947542319905, 0.081597980709237419, 0.083174093009632397, 0.084762330532368146, 0.086362741140756927, 0.087975374467270231, 0.089600281910032886, 0.091237516631040197, 0.092887133556043569, 0.094549189376055873, 0.096223742550432825, 0.097910853311492213, 0.099610583670637132, 0.101322997425953631, 0.103048160171257702, 0.104786139306570145, 0.106537004050001632, 0.108300825451033755, 0.110077676405185357, 0.111867631670056283, 0.113670767882744286, 0.115487163578633506, 0.117316899211555525, 0.119160057175327641, 0.121016721826674792, 0.122886979509545108, 0.124770918580830933, 0.126668629437510671, 0.128580204545228199, 0.130505738468330773, 0.132445327901387494, 0.134399071702213602, 0.136367070926428829, 0.138349428863580176, 0.140346251074862399, 0.142357645432472146, 0.144383722160634720, 0.146424593878344889, 0.148480375643866735, 0.150551185001039839, 0.152637142027442801, 0.154738369384468027, 0.156854992369365148, 0.158987138969314129, 0.161134939917591952, 0.163298528751901734, 0.165478041874935922, 0.167673618617250081, 0.169885401302527550, 0.172113535315319977, 0.174358169171353411, 0.176619454590494829, 0.178897546572478278, 0.181192603475496261, 0.183504787097767436, 0.185834262762197083, 0.188181199404254262, 0.190545769663195363, 0.192928149976771296, 0.195328520679563189, 0.197747066105098818, 0.200183974691911210, 0.202639439093708962, 0.205113656293837654, 0.207606827724221982, 0.210119159388988230, 0.212650861992978224, 0.215202151075378628, 0.217773247148700472, 0.220364375843359439, 0.222975768058120111, 0.225607660116683956, 0.228260293930716618, 0.230933917169627356, 0.233628783437433291, 0.236345152457059560, 0.239083290262449094, 0.241843469398877131, 0.244625969131892024, 0.247431075665327543, 0.250259082368862240, 0.253110290015629402, 0.255985007030415324, 0.258883549749016173, 0.261806242689362922, 0.264753418835062149, 0.267725419932044739, 0.270722596799059967, 0.273745309652802915, 0.276793928448517301, 0.279868833236972869, 0.282970414538780746, 0.286099073737076826, 0.289255223489677693, 0.292439288161892630, 0.295651704281261252, 0.298892921015581847, 0.302163400675693528, 0.305463619244590256, 0.308794066934560185, 0.312155248774179606, 0.315547685227128949, 0.318971912844957239, 0.322428484956089223, 0.325917972393556354, 0.329440964264136438, 0.332998068761809096, 0.336589914028677717, 0.340217149066780189, 0.343880444704502575, 0.347580494621637148, 0.351318016437483449, 0.355093752866787626, 0.358908472948750001, 0.362762973354817997, 0.366658079781514379, 0.370594648435146223, 0.374573567615902381, 0.378595759409581067, 0.382662181496010056, 0.386773829084137932, 0.390931736984797384, 0.395136981833290435, 0.399390684475231350, 0.403694012530530555, 0.408048183152032673, 0.412454465997161457, 0.416914186433003209, 0.421428728997616908, 0.425999541143034677, 0.430628137288459167, 0.435316103215636907, 0.440065100842354173, 0.444876873414548846, 0.449753251162755330, 0.454696157474615836, 0.459707615642138023, 0.464789756250426511, 0.469944825283960310, 0.475175193037377708, 0.480483363930454543, 0.485871987341885248, 0.491343869594032867, 0.496901987241549881, 0.502549501841348056, 0.508289776410643213, 0.514126393814748894, 0.520063177368233931, 0.526104213983620062, 0.532253880263043655, 0.538516872002862246, 0.544898237672440056, 0.551403416540641733, 0.558038282262587892, 0.564809192912400615, 0.571723048664826150, 0.578787358602845359, 0.586010318477268366, 0.593400901691733762, 0.600968966365232560, 0.608725382079622346, 0.616682180915207878, 0.624852738703666200, 0.633251994214366398, 0.641896716427266423, 0.650805833414571433, 0.660000841079000145, 0.669506316731925177, 0.679350572264765806, 0.689566496117078431, 0.700192655082788606, 0.711274760805076456, 0.722867659593572465, 0.735038092431424039, 0.747868621985195658, 0.761463388849896838, 0.775956852040116218, 0.791527636972496285, 0.808421651523009044, 0.826993296643051101, 0.847785500623990496, 0.871704332381204705, 0.900469929925747703, 0.938143680862176477, 1.000000000000000000]; rand-0.7.2/src/lib.rs010064400017500001750000000537051353150727500126120ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013-2017 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Utilities for random number generation //! //! Rand provides utilities to generate random numbers, to convert them to //! useful types and distributions, and some randomness-related algorithms. //! //! # Quick Start //! //! To get you started quickly, the easiest and highest-level way to get //! a random value is to use [`random()`]; alternatively you can use //! [`thread_rng()`]. The [`Rng`] trait provides a useful API on all RNGs, while //! the [`distributions`] and [`seq`] modules provide further //! functionality on top of RNGs. //! //! ``` //! use rand::prelude::*; //! //! if rand::random() { // generates a boolean //! // Try printing a random unicode code point (probably a bad idea)! //! println!("char: {}", rand::random::()); //! } //! //! let mut rng = rand::thread_rng(); //! let y: f64 = rng.gen(); // generates a float between 0 and 1 //! //! let mut nums: Vec = (1..100).collect(); //! nums.shuffle(&mut rng); //! ``` //! //! # The Book //! //! For the user guide and futher documentation, please read //! [The Rust Rand Book](https://rust-random.github.io/book). #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://rust-random.github.io/rand/")] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![doc(test(attr(allow(unused_variables), deny(warnings))))] #![cfg_attr(not(feature="std"), no_std)] #![cfg_attr(all(feature="simd_support", feature="nightly"), feature(stdsimd))] #![allow(clippy::excessive_precision, clippy::unreadable_literal, clippy::float_cmp)] #[cfg(all(feature="alloc", not(feature="std")))] extern crate alloc; #[allow(unused)] macro_rules! trace { ($($x:tt)*) => ( #[cfg(feature = "log")] { log::trace!($($x)*) } ) } #[allow(unused)] macro_rules! debug { ($($x:tt)*) => ( #[cfg(feature = "log")] { log::debug!($($x)*) } ) } #[allow(unused)] macro_rules! info { ($($x:tt)*) => ( #[cfg(feature = "log")] { log::info!($($x)*) } ) } #[allow(unused)] macro_rules! warn { ($($x:tt)*) => ( #[cfg(feature = "log")] { log::warn!($($x)*) } ) } #[allow(unused)] macro_rules! error { ($($x:tt)*) => ( #[cfg(feature = "log")] { log::error!($($x)*) } ) } // Re-exports from rand_core pub use rand_core::{RngCore, CryptoRng, SeedableRng, Error}; // Public exports #[cfg(feature="std")] pub use crate::rngs::thread::thread_rng; // Public modules pub mod distributions; pub mod prelude; pub mod rngs; pub mod seq; use core::{mem, slice}; use core::num::Wrapping; use crate::distributions::{Distribution, Standard}; use crate::distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow}; /// An automatically-implemented extension trait on [`RngCore`] providing high-level /// generic methods for sampling values and other convenience methods. /// /// This is the primary trait to use when generating random values. /// /// # Generic usage /// /// The basic pattern is `fn foo(rng: &mut R)`. Some /// things are worth noting here: /// /// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no /// difference whether we use `R: Rng` or `R: RngCore`. /// - The `+ ?Sized` un-bounding allows functions to be called directly on /// type-erased references; i.e. `foo(r)` where `r: &mut RngCore`. Without /// this it would be necessary to write `foo(&mut r)`. /// /// An alternative pattern is possible: `fn foo(rng: R)`. This has some /// trade-offs. It allows the argument to be consumed directly without a `&mut` /// (which is how `from_rng(thread_rng())` works); also it still works directly /// on references (including type-erased references). Unfortunately within the /// function `foo` it is not known whether `rng` is a reference type or not, /// hence many uses of `rng` require an extra reference, either explicitly /// (`distr.sample(&mut rng)`) or implicitly (`rng.gen()`); one may hope the /// optimiser can remove redundant references later. /// /// Example: /// /// ``` /// # use rand::thread_rng; /// use rand::Rng; /// /// fn foo(rng: &mut R) -> f32 { /// rng.gen() /// } /// /// # let v = foo(&mut thread_rng()); /// ``` pub trait Rng: RngCore { /// Return a random value supporting the [`Standard`] distribution. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let x: u32 = rng.gen(); /// println!("{}", x); /// println!("{:?}", rng.gen::<(f64, bool)>()); /// ``` /// /// # Arrays and tuples /// /// The `rng.gen()` method is able to generate arrays (up to 32 elements) /// and tuples (up to 12 elements), so long as all element types can be /// generated. /// /// For arrays of integers, especially for those with small element types /// (< 64 bit), it will likely be faster to instead use [`Rng::fill`]. /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let tuple: (u8, i32, char) = rng.gen(); // arbitrary tuple support /// /// let arr1: [f32; 32] = rng.gen(); // array construction /// let mut arr2 = [0u8; 128]; /// rng.fill(&mut arr2); // array fill /// ``` /// /// [`Standard`]: distributions::Standard #[inline] fn gen(&mut self) -> T where Standard: Distribution { Standard.sample(self) } /// Generate a random value in the range [`low`, `high`), i.e. inclusive of /// `low` and exclusive of `high`. /// /// This function is optimised for the case that only a single sample is /// made from the given range. See also the [`Uniform`] distribution /// type which may be faster if sampling from the same range repeatedly. /// /// # Panics /// /// Panics if `low >= high`. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let n: u32 = rng.gen_range(0, 10); /// println!("{}", n); /// let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64); /// println!("{}", m); /// ``` /// /// [`Uniform`]: distributions::uniform::Uniform fn gen_range(&mut self, low: B1, high: B2) -> T where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { T::Sampler::sample_single(low, high, self) } /// Sample a new value, using the given distribution. /// /// ### Example /// /// ``` /// use rand::{thread_rng, Rng}; /// use rand::distributions::Uniform; /// /// let mut rng = thread_rng(); /// let x = rng.sample(Uniform::new(10u32, 15)); /// // Type annotation requires two types, the type and distribution; the /// // distribution can be inferred. /// let y = rng.sample::(Uniform::new(10, 15)); /// ``` fn sample>(&mut self, distr: D) -> T { distr.sample(self) } /// Create an iterator that generates values using the given distribution. /// /// Note that this function takes its arguments by value. This works since /// `(&mut R): Rng where R: Rng` and /// `(&D): Distribution where D: Distribution`, /// however borrowing is not automatic hence `rng.sample_iter(...)` may /// need to be replaced with `(&mut rng).sample_iter(...)`. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// use rand::distributions::{Alphanumeric, Uniform, Standard}; /// /// let rng = thread_rng(); /// /// // Vec of 16 x f32: /// let v: Vec = rng.sample_iter(Standard).take(16).collect(); /// /// // String: /// let s: String = rng.sample_iter(Alphanumeric).take(7).collect(); /// /// // Combined values /// println!("{:?}", rng.sample_iter(Standard).take(5) /// .collect::>()); /// /// // Dice-rolling: /// let die_range = Uniform::new_inclusive(1, 6); /// let mut roll_die = rng.sample_iter(die_range); /// while roll_die.next().unwrap() != 6 { /// println!("Not a 6; rolling again!"); /// } /// ``` fn sample_iter(self, distr: D) -> distributions::DistIter where D: Distribution, Self: Sized { distr.sample_iter(self) } /// Fill `dest` entirely with random bytes (uniform value distribution), /// where `dest` is any type supporting [`AsByteSliceMut`], namely slices /// and arrays over primitive integer types (`i8`, `i16`, `u32`, etc.). /// /// On big-endian platforms this performs byte-swapping to ensure /// portability of results from reproducible generators. /// /// This uses [`fill_bytes`] internally which may handle some RNG errors /// implicitly (e.g. waiting if the OS generator is not ready), but panics /// on other errors. See also [`try_fill`] which returns errors. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut arr = [0i8; 20]; /// thread_rng().fill(&mut arr[..]); /// ``` /// /// [`fill_bytes`]: RngCore::fill_bytes /// [`try_fill`]: Rng::try_fill fn fill(&mut self, dest: &mut T) { self.fill_bytes(dest.as_byte_slice_mut()); dest.to_le(); } /// Fill `dest` entirely with random bytes (uniform value distribution), /// where `dest` is any type supporting [`AsByteSliceMut`], namely slices /// and arrays over primitive integer types (`i8`, `i16`, `u32`, etc.). /// /// On big-endian platforms this performs byte-swapping to ensure /// portability of results from reproducible generators. /// /// This is identical to [`fill`] except that it uses [`try_fill_bytes`] /// internally and forwards RNG errors. /// /// # Example /// /// ``` /// # use rand::Error; /// use rand::{thread_rng, Rng}; /// /// # fn try_inner() -> Result<(), Error> { /// let mut arr = [0u64; 4]; /// thread_rng().try_fill(&mut arr[..])?; /// # Ok(()) /// # } /// /// # try_inner().unwrap() /// ``` /// /// [`try_fill_bytes`]: RngCore::try_fill_bytes /// [`fill`]: Rng::fill fn try_fill(&mut self, dest: &mut T) -> Result<(), Error> { self.try_fill_bytes(dest.as_byte_slice_mut())?; dest.to_le(); Ok(()) } /// Return a bool with a probability `p` of being true. /// /// See also the [`Bernoulli`] distribution, which may be faster if /// sampling from the same probability repeatedly. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// println!("{}", rng.gen_bool(1.0 / 3.0)); /// ``` /// /// # Panics /// /// If `p < 0` or `p > 1`. /// /// [`Bernoulli`]: distributions::bernoulli::Bernoulli #[inline] fn gen_bool(&mut self, p: f64) -> bool { let d = distributions::Bernoulli::new(p).unwrap(); self.sample(d) } /// Return a bool with a probability of `numerator/denominator` of being /// true. I.e. `gen_ratio(2, 3)` has chance of 2 in 3, or about 67%, of /// returning true. If `numerator == denominator`, then the returned value /// is guaranteed to be `true`. If `numerator == 0`, then the returned /// value is guaranteed to be `false`. /// /// See also the [`Bernoulli`] distribution, which may be faster if /// sampling from the same `numerator` and `denominator` repeatedly. /// /// # Panics /// /// If `denominator == 0` or `numerator > denominator`. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// println!("{}", rng.gen_ratio(2, 3)); /// ``` /// /// [`Bernoulli`]: distributions::bernoulli::Bernoulli #[inline] fn gen_ratio(&mut self, numerator: u32, denominator: u32) -> bool { let d = distributions::Bernoulli::from_ratio(numerator, denominator).unwrap(); self.sample(d) } } impl Rng for R {} /// Trait for casting types to byte slices /// /// This is used by the [`Rng::fill`] and [`Rng::try_fill`] methods. pub trait AsByteSliceMut { /// Return a mutable reference to self as a byte slice fn as_byte_slice_mut(&mut self) -> &mut [u8]; /// Call `to_le` on each element (i.e. byte-swap on Big Endian platforms). fn to_le(&mut self); } impl AsByteSliceMut for [u8] { fn as_byte_slice_mut(&mut self) -> &mut [u8] { self } fn to_le(&mut self) {} } macro_rules! impl_as_byte_slice { () => {}; ($t:ty) => { impl AsByteSliceMut for [$t] { fn as_byte_slice_mut(&mut self) -> &mut [u8] { if self.len() == 0 { unsafe { // must not use null pointer slice::from_raw_parts_mut(0x1 as *mut u8, 0) } } else { unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, self.len() * mem::size_of::<$t>() ) } } } fn to_le(&mut self) { for x in self { *x = x.to_le(); } } } impl AsByteSliceMut for [Wrapping<$t>] { fn as_byte_slice_mut(&mut self) -> &mut [u8] { if self.len() == 0 { unsafe { // must not use null pointer slice::from_raw_parts_mut(0x1 as *mut u8, 0) } } else { unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, self.len() * mem::size_of::<$t>() ) } } } fn to_le(&mut self) { for x in self { *x = Wrapping(x.0.to_le()); } } } }; ($t:ty, $($tt:ty,)*) => { impl_as_byte_slice!($t); // TODO: this could replace above impl once Rust #32463 is fixed // impl_as_byte_slice!(Wrapping<$t>); impl_as_byte_slice!($($tt,)*); } } impl_as_byte_slice!(u16, u32, u64, usize,); #[cfg(not(target_os = "emscripten"))] impl_as_byte_slice!(u128); impl_as_byte_slice!(i8, i16, i32, i64, isize,); #[cfg(not(target_os = "emscripten"))] impl_as_byte_slice!(i128); macro_rules! impl_as_byte_slice_arrays { ($n:expr,) => {}; ($n:expr, $N:ident) => { impl AsByteSliceMut for [T; $n] where [T]: AsByteSliceMut { fn as_byte_slice_mut(&mut self) -> &mut [u8] { self[..].as_byte_slice_mut() } fn to_le(&mut self) { self[..].to_le() } } }; ($n:expr, $N:ident, $($NN:ident,)*) => { impl_as_byte_slice_arrays!($n, $N); impl_as_byte_slice_arrays!($n - 1, $($NN,)*); }; (!div $n:expr,) => {}; (!div $n:expr, $N:ident, $($NN:ident,)*) => { impl_as_byte_slice_arrays!($n, $N); impl_as_byte_slice_arrays!(!div $n / 2, $($NN,)*); }; } impl_as_byte_slice_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,); impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,); /// Generates a random value using the thread-local random number generator. /// /// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for /// documentation of the entropy source and [`Standard`] for documentation of /// distributions and type-specific generation. /// /// # Examples /// /// ``` /// let x = rand::random::(); /// println!("{}", x); /// /// let y = rand::random::(); /// println!("{}", y); /// /// if rand::random() { // generates a boolean /// println!("Better lucky than good!"); /// } /// ``` /// /// If you're calling `random()` in a loop, caching the generator as in the /// following example can increase performance. /// /// ``` /// use rand::Rng; /// /// let mut v = vec![1, 2, 3]; /// /// for x in v.iter_mut() { /// *x = rand::random() /// } /// /// // can be made faster by caching thread_rng /// /// let mut rng = rand::thread_rng(); /// /// for x in v.iter_mut() { /// *x = rng.gen(); /// } /// ``` /// /// [`Standard`]: distributions::Standard #[cfg(feature="std")] #[inline] pub fn random() -> T where Standard: Distribution { thread_rng().gen() } #[cfg(test)] mod test { use crate::rngs::mock::StepRng; use super::*; #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::boxed::Box; /// Construct a deterministic RNG with the given seed pub fn rng(seed: u64) -> impl RngCore { // For tests, we want a statistically good, fast, reproducible RNG. // PCG32 will do fine, and will be easy to embed if we ever need to. const INC: u64 = 11634580027462260723; rand_pcg::Pcg32::new(seed, INC) } #[test] fn test_fill_bytes_default() { let mut r = StepRng::new(0x11_22_33_44_55_66_77_88, 0); // check every remainder mod 8, both in small and big vectors. let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87]; for &n in lengths.iter() { let mut buffer = [0u8; 87]; let v = &mut buffer[0..n]; r.fill_bytes(v); // use this to get nicer error messages. for (i, &byte) in v.iter().enumerate() { if byte == 0 { panic!("byte {} of {} is zero", i, n) } } } } #[test] fn test_fill() { let x = 9041086907909331047; // a random u64 let mut rng = StepRng::new(x, 0); // Convert to byte sequence and back to u64; byte-swap twice if BE. let mut array = [0u64; 2]; rng.fill(&mut array[..]); assert_eq!(array, [x, x]); assert_eq!(rng.next_u64(), x); // Convert to bytes then u32 in LE order let mut array = [0u32; 2]; rng.fill(&mut array[..]); assert_eq!(array, [x as u32, (x >> 32) as u32]); assert_eq!(rng.next_u32(), x as u32); // Check equivalence using wrapped arrays let mut warray = [Wrapping(0u32); 2]; rng.fill(&mut warray[..]); assert_eq!(array[0], warray[0].0); assert_eq!(array[1], warray[1].0); } #[test] fn test_fill_empty() { let mut array = [0u32; 0]; let mut rng = StepRng::new(0, 1); rng.fill(&mut array); rng.fill(&mut array[..]); } #[test] fn test_gen_range() { let mut r = rng(101); for _ in 0..1000 { let a = r.gen_range(-4711, 17); assert!(a >= -4711 && a < 17); let a = r.gen_range(-3i8, 42); assert!(a >= -3i8 && a < 42i8); let a = r.gen_range(&10u16, 99); assert!(a >= 10u16 && a < 99u16); let a = r.gen_range(-100i32, &2000); assert!(a >= -100i32 && a < 2000i32); let a = r.gen_range(&12u32, &24u32); assert!(a >= 12u32 && a < 24u32); assert_eq!(r.gen_range(0u32, 1), 0u32); assert_eq!(r.gen_range(-12i64, -11), -12i64); assert_eq!(r.gen_range(3_000_000, 3_000_001), 3_000_000); } } #[test] #[should_panic] fn test_gen_range_panic_int() { let mut r = rng(102); r.gen_range(5, -2); } #[test] #[should_panic] fn test_gen_range_panic_usize() { let mut r = rng(103); r.gen_range(5, 2); } #[test] fn test_gen_bool() { let mut r = rng(105); for _ in 0..5 { assert_eq!(r.gen_bool(0.0), false); assert_eq!(r.gen_bool(1.0), true); } } #[test] fn test_rng_trait_object() { use crate::distributions::{Distribution, Standard}; let mut rng = rng(109); let mut r = &mut rng as &mut dyn RngCore; r.next_u32(); r.gen::(); assert_eq!(r.gen_range(0, 1), 0); let _c: u8 = Standard.sample(&mut r); } #[test] #[cfg(feature="alloc")] fn test_rng_boxed_trait() { use crate::distributions::{Distribution, Standard}; let rng = rng(110); let mut r = Box::new(rng) as Box; r.next_u32(); r.gen::(); assert_eq!(r.gen_range(0, 1), 0); let _c: u8 = Standard.sample(&mut r); } #[test] #[cfg(feature="std")] fn test_random() { // not sure how to test this aside from just getting some values let _n : usize = random(); let _f : f32 = random(); let _o : Option> = random(); let _many : ((), (usize, isize, Option<(u32, (bool,))>), (u8, i8, u16, i16, u32, i32, u64, i64), (f32, (f64, (f64,)))) = random(); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_gen_ratio_average() { const NUM: u32 = 3; const DENOM: u32 = 10; const N: u32 = 100_000; let mut sum: u32 = 0; let mut rng = rng(111); for _ in 0..N { if rng.gen_ratio(NUM, DENOM) { sum += 1; } } // Have Binomial(N, NUM/DENOM) distribution let expected = (NUM * N) / DENOM; // exact integer assert!(((sum - expected) as i32).abs() < 500); } } rand-0.7.2/src/prelude.rs010064400017500001750000000022561352222772600134770ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Convenience re-export of common members //! //! Like the standard library's prelude, this module simplifies importing of //! common items. Unlike the standard prelude, the contents of this module must //! be imported manually: //! //! ``` //! use rand::prelude::*; //! # let mut r = StdRng::from_rng(thread_rng()).unwrap(); //! # let _: f32 = r.gen(); //! ``` #[doc(no_inline)] pub use crate::distributions::Distribution; #[doc(no_inline)] pub use crate::rngs::StdRng; #[cfg(feature="small_rng")] #[doc(no_inline)] pub use crate::rngs::SmallRng; #[doc(no_inline)] #[cfg(feature="std")] pub use crate::rngs::ThreadRng; #[doc(no_inline)] pub use crate::{Rng, RngCore, CryptoRng, SeedableRng}; #[doc(no_inline)] #[cfg(feature="std")] pub use crate::{random, thread_rng}; #[doc(no_inline)] pub use crate::seq::{SliceRandom, IteratorRandom}; rand-0.7.2/src/rngs/adapter/mod.rs010064400017500001750000000010411352222772600151760ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Wrappers / adapters forming RNGs #[cfg(feature="std")] mod read; mod reseeding; #[cfg(feature="std")] pub use self::read::{ReadRng, ReadError}; pub use self::reseeding::ReseedingRng; rand-0.7.2/src/rngs/adapter/read.rs010064400017500001750000000100471352222772600153400ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A wrapper around any Read to treat it as an RNG. use std::io::Read; use std::fmt; use rand_core::{RngCore, Error, impls}; /// An RNG that reads random bytes straight from any type supporting /// [`std::io::Read`], for example files. /// /// This will work best with an infinite reader, but that is not required. /// /// This can be used with `/dev/urandom` on Unix but it is recommended to use /// [`OsRng`] instead. /// /// # Panics /// /// `ReadRng` uses [`std::io::Read::read_exact`], which retries on interrupts. /// All other errors from the underlying reader, including when it does not /// have enough data, will only be reported through [`try_fill_bytes`]. /// The other [`RngCore`] methods will panic in case of an error. /// /// # Example /// /// ``` /// use rand::Rng; /// use rand::rngs::adapter::ReadRng; /// /// let data = vec![1, 2, 3, 4, 5, 6, 7, 8]; /// let mut rng = ReadRng::new(&data[..]); /// println!("{:x}", rng.gen::()); /// ``` /// /// [`OsRng`]: crate::rngs::OsRng /// [`try_fill_bytes`]: RngCore::try_fill_bytes #[derive(Debug)] pub struct ReadRng { reader: R } impl ReadRng { /// Create a new `ReadRng` from a `Read`. pub fn new(r: R) -> ReadRng { ReadRng { reader: r } } } impl RngCore for ReadRng { fn next_u32(&mut self) -> u32 { impls::next_u32_via_fill(self) } fn next_u64(&mut self) -> u64 { impls::next_u64_via_fill(self) } fn fill_bytes(&mut self, dest: &mut [u8]) { self.try_fill_bytes(dest).unwrap_or_else(|err| panic!("reading random bytes from Read implementation failed; error: {}", err)); } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { if dest.is_empty() { return Ok(()); } // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. self.reader.read_exact(dest).map_err(|e| Error::new(ReadError(e))) } } /// `ReadRng` error type #[derive(Debug)] pub struct ReadError(std::io::Error); impl fmt::Display for ReadError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ReadError: {}", self.0) } } impl std::error::Error for ReadError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } } #[cfg(test)] mod test { use super::ReadRng; use crate::RngCore; #[test] fn test_reader_rng_u64() { // transmute from the target to avoid endianness concerns. let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3]; let mut rng = ReadRng::new(&v[..]); assert_eq!(rng.next_u64(), 1_u64.to_be()); assert_eq!(rng.next_u64(), 2_u64.to_be()); assert_eq!(rng.next_u64(), 3_u64.to_be()); } #[test] fn test_reader_rng_u32() { let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3]; let mut rng = ReadRng::new(&v[..]); assert_eq!(rng.next_u32(), 1_u32.to_be()); assert_eq!(rng.next_u32(), 2_u32.to_be()); assert_eq!(rng.next_u32(), 3_u32.to_be()); } #[test] fn test_reader_rng_fill_bytes() { let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; let mut w = [0u8; 8]; let mut rng = ReadRng::new(&v[..]); rng.fill_bytes(&mut w); assert!(v == w); } #[test] fn test_reader_rng_insufficient_bytes() { let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; let mut w = [0u8; 9]; let mut rng = ReadRng::new(&v[..]); let result = rng.try_fill_bytes(&mut w); assert!(result.is_err()); println!("Error: {}", result.unwrap_err()); } } rand-0.7.2/src/rngs/adapter/reseeding.rs010064400017500001750000000301411352222772600163670ustar0000000000000000// Copyright 2018 Developers of the Rand project. // Copyright 2013 The Rust Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A wrapper around another PRNG that reseeds it after it //! generates a certain number of random bytes. use core::mem::size_of; use rand_core::{RngCore, CryptoRng, SeedableRng, Error}; use rand_core::block::{BlockRngCore, BlockRng}; /// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the /// ability to reseed it. /// /// `ReseedingRng` reseeds the underlying PRNG in the following cases: /// /// - On a manual call to [`reseed()`]. /// - After `clone()`, the clone will be reseeded on first use. /// - After a process is forked, the RNG in the child process is reseeded within /// the next few generated values, depending on the block size of the /// underlying PRNG. For ChaCha and Hc128 this is a maximum of /// 15 `u32` values before reseeding. /// - After the PRNG has generated a configurable number of random bytes. /// /// # When should reseeding after a fixed number of generated bytes be used? /// /// Reseeding after a fixed number of generated bytes is never strictly /// *necessary*. Cryptographic PRNGs don't have a limited number of bytes they /// can output, or at least not a limit reachable in any practical way. There is /// no such thing as 'running out of entropy'. /// /// Occasionally reseeding can be seen as some form of 'security in depth'. Even /// if in the future a cryptographic weakness is found in the CSPRNG being used, /// or a flaw in the implementation, occasionally reseeding should make /// exploiting it much more difficult or even impossible. /// /// Use [`ReseedingRng::new`] with a `threshold` of `0` to disable reseeding /// after a fixed number of generated bytes. /// /// # Error handling /// /// Although unlikely, reseeding the wrapped PRNG can fail. `ReseedingRng` will /// never panic but try to handle the error intelligently through some /// combination of retrying and delaying reseeding until later. /// If handling the source error fails `ReseedingRng` will continue generating /// data from the wrapped PRNG without reseeding. /// /// Manually calling [`reseed()`] will not have this retry or delay logic, but /// reports the error. /// /// # Example /// /// ``` /// use rand::prelude::*; /// use rand_chacha::ChaCha20Core; // Internal part of ChaChaRng that /// // implements BlockRngCore /// use rand::rngs::OsRng; /// use rand::rngs::adapter::ReseedingRng; /// /// let prng = ChaCha20Core::from_entropy(); /// let mut reseeding_rng = ReseedingRng::new(prng, 0, OsRng); /// /// println!("{}", reseeding_rng.gen::()); /// /// let mut cloned_rng = reseeding_rng.clone(); /// assert!(reseeding_rng.gen::() != cloned_rng.gen::()); /// ``` /// /// [`BlockRngCore`]: rand_core::block::BlockRngCore /// [`ReseedingRng::new`]: ReseedingRng::new /// [`reseed()`]: ReseedingRng::reseed #[derive(Debug)] pub struct ReseedingRng(BlockRng>) where R: BlockRngCore + SeedableRng, Rsdr: RngCore; impl ReseedingRng where R: BlockRngCore + SeedableRng, Rsdr: RngCore { /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG /// to use as reseeder. /// /// `threshold` sets the number of generated bytes after which to reseed the /// PRNG. Set it to zero to never reseed based on the number of generated /// values. pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { ReseedingRng(BlockRng::new(ReseedingCore::new(rng, threshold, reseeder))) } /// Reseed the internal PRNG. pub fn reseed(&mut self) -> Result<(), Error> { self.0.core.reseed() } } // TODO: this should be implemented for any type where the inner type // implements RngCore, but we can't specify that because ReseedingCore is private impl RngCore for ReseedingRng where R: BlockRngCore + SeedableRng, ::Results: AsRef<[u32]> + AsMut<[u32]> { #[inline(always)] fn next_u32(&mut self) -> u32 { self.0.next_u32() } #[inline(always)] fn next_u64(&mut self) -> u64 { self.0.next_u64() } fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.0.try_fill_bytes(dest) } } impl Clone for ReseedingRng where R: BlockRngCore + SeedableRng + Clone, Rsdr: RngCore + Clone { fn clone(&self) -> ReseedingRng { // Recreating `BlockRng` seems easier than cloning it and resetting // the index. ReseedingRng(BlockRng::new(self.0.core.clone())) } } impl CryptoRng for ReseedingRng where R: BlockRngCore + SeedableRng + CryptoRng, Rsdr: RngCore + CryptoRng {} #[derive(Debug)] struct ReseedingCore { inner: R, reseeder: Rsdr, threshold: i64, bytes_until_reseed: i64, fork_counter: usize, } impl BlockRngCore for ReseedingCore where R: BlockRngCore + SeedableRng, Rsdr: RngCore { type Item = ::Item; type Results = ::Results; fn generate(&mut self, results: &mut Self::Results) { let global_fork_counter = fork::get_fork_counter(); if self.bytes_until_reseed <= 0 || self.is_forked(global_fork_counter) { // We get better performance by not calling only `reseed` here // and continuing with the rest of the function, but by directly // returning from a non-inlined function. return self.reseed_and_generate(results, global_fork_counter); } let num_bytes = results.as_ref().len() * size_of::(); self.bytes_until_reseed -= num_bytes as i64; self.inner.generate(results); } } impl ReseedingCore where R: BlockRngCore + SeedableRng, Rsdr: RngCore { /// Create a new `ReseedingCore`. fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { use ::core::i64::MAX; fork::register_fork_handler(); // Because generating more values than `i64::MAX` takes centuries on // current hardware, we just clamp to that value. // Also we set a threshold of 0, which indicates no limit, to that // value. let threshold = if threshold == 0 { MAX } else if threshold <= MAX as u64 { threshold as i64 } else { MAX }; ReseedingCore { inner: rng, reseeder, threshold: threshold as i64, bytes_until_reseed: threshold as i64, fork_counter: 0, } } /// Reseed the internal PRNG. fn reseed(&mut self) -> Result<(), Error> { R::from_rng(&mut self.reseeder).map(|result| { self.bytes_until_reseed = self.threshold; self.inner = result }) } fn is_forked(&self, global_fork_counter: usize) -> bool { // In theory, on 32-bit platforms, it is possible for // `global_fork_counter` to wrap around after ~4e9 forks. // // This check will detect a fork in the normal case where // `fork_counter < global_fork_counter`, and also when the difference // between both is greater than `isize::MAX` (wrapped around). // // It will still fail to detect a fork if there have been more than // `isize::MAX` forks, without any reseed in between. Seems unlikely // enough. (self.fork_counter.wrapping_sub(global_fork_counter) as isize) < 0 } #[inline(never)] fn reseed_and_generate(&mut self, results: &mut ::Results, global_fork_counter: usize) { #![allow(clippy::if_same_then_else)] // false positive if self.is_forked(global_fork_counter) { info!("Fork detected, reseeding RNG"); } else { trace!("Reseeding RNG (periodic reseed)"); } let num_bytes = results.as_ref().len() * size_of::<::Item>(); if let Err(e) = self.reseed() { warn!("Reseeding RNG failed: {}", e); let _ = e; } self.fork_counter = global_fork_counter; self.bytes_until_reseed = self.threshold - num_bytes as i64; self.inner.generate(results); } } impl Clone for ReseedingCore where R: BlockRngCore + SeedableRng + Clone, Rsdr: RngCore + Clone { fn clone(&self) -> ReseedingCore { ReseedingCore { inner: self.inner.clone(), reseeder: self.reseeder.clone(), threshold: self.threshold, bytes_until_reseed: 0, // reseed clone on first use fork_counter: self.fork_counter, } } } impl CryptoRng for ReseedingCore where R: BlockRngCore + SeedableRng + CryptoRng, Rsdr: RngCore + CryptoRng {} #[cfg(all(unix, not(target_os="emscripten")))] mod fork { use core::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; #[allow(deprecated)] // Required for compatibility with Rust < 1.24. use core::sync::atomic::{ATOMIC_USIZE_INIT, ATOMIC_BOOL_INIT}; // Fork protection // // We implement fork protection on Unix using `pthread_atfork`. // When the process is forked, we increment `RESEEDING_RNG_FORK_COUNTER`. // Every `ReseedingRng` stores the last known value of the static in // `fork_counter`. If the cached `fork_counter` is less than // `RESEEDING_RNG_FORK_COUNTER`, it is time to reseed this RNG. // // If reseeding fails, we don't deal with this by setting a delay, but just // don't update `fork_counter`, so a reseed is attempted as soon as // possible. #[allow(deprecated)] static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; pub fn get_fork_counter() -> usize { RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed) } #[allow(deprecated)] static FORK_HANDLER_REGISTERED: AtomicBool = ATOMIC_BOOL_INIT; extern fn fork_handler() { // Note: fetch_add is defined to wrap on overflow // (which is what we want). RESEEDING_RNG_FORK_COUNTER.fetch_add(1, Ordering::Relaxed); } pub fn register_fork_handler() { if !FORK_HANDLER_REGISTERED.load(Ordering::Relaxed) { unsafe { libc::pthread_atfork(None, None, Some(fork_handler)) }; FORK_HANDLER_REGISTERED.store(true, Ordering::Relaxed); } } } #[cfg(not(all(unix, not(target_os="emscripten"))))] mod fork { pub fn get_fork_counter() -> usize { 0 } pub fn register_fork_handler() {} } #[cfg(test)] mod test { use crate::{Rng, SeedableRng}; use crate::rngs::std::Core; use crate::rngs::mock::StepRng; use super::ReseedingRng; #[test] fn test_reseeding() { let mut zero = StepRng::new(0, 0); let rng = Core::from_rng(&mut zero).unwrap(); let thresh = 1; // reseed every time the buffer is exhausted let mut reseeding = ReseedingRng::new(rng, thresh, zero); // RNG buffer size is [u32; 64] // Debug is only implemented up to length 32 so use two arrays let mut buf = ([0u32; 32], [0u32; 32]); reseeding.fill(&mut buf.0); reseeding.fill(&mut buf.1); let seq = buf; for _ in 0..10 { reseeding.fill(&mut buf.0); reseeding.fill(&mut buf.1); assert_eq!(buf, seq); } } #[test] fn test_clone_reseeding() { let mut zero = StepRng::new(0, 0); let rng = Core::from_rng(&mut zero).unwrap(); let mut rng1 = ReseedingRng::new(rng, 32*4, zero); let first: u32 = rng1.gen(); for _ in 0..10 { let _ = rng1.gen::(); } let mut rng2 = rng1.clone(); assert_eq!(first, rng2.gen::()); } } rand-0.7.2/src/rngs/entropy.rs010064400017500001750000000037771352222772600145210ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Entropy generator, or wrapper around external generators #![allow(deprecated)] // whole module is deprecated use rand_core::{RngCore, CryptoRng, Error}; use crate::rngs::OsRng; /// An interface returning random data from external source(s), provided /// specifically for securely seeding algorithmic generators (PRNGs). /// /// This is deprecated. It is suggested you use [`rngs::OsRng`] instead. /// /// [`rngs::OsRng`]: crate::rngs::OsRng #[derive(Debug)] #[deprecated(since="0.7.0", note="use rngs::OsRng instead")] pub struct EntropyRng { source: OsRng, } impl EntropyRng { /// Create a new `EntropyRng`. /// /// This method will do no system calls or other initialization routines, /// those are done on first use. This is done to make `new` infallible, /// and `try_fill_bytes` the only place to report errors. pub fn new() -> Self { EntropyRng { source: OsRng } } } impl Default for EntropyRng { fn default() -> Self { EntropyRng::new() } } impl RngCore for EntropyRng { fn next_u32(&mut self) -> u32 { self.source.next_u32() } fn next_u64(&mut self) -> u64 { self.source.next_u64() } fn fill_bytes(&mut self, dest: &mut [u8]) { self.source.fill_bytes(dest) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.source.try_fill_bytes(dest) } } impl CryptoRng for EntropyRng {} #[cfg(test)] mod test { use super::*; #[test] fn test_entropy() { let mut rng = EntropyRng::new(); let n = (rng.next_u32() ^ rng.next_u32()).count_ones(); assert!(n >= 2); // p(failure) approx 1e-7 } } rand-0.7.2/src/rngs/mock.rs010064400017500001750000000033041352222772600137340ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Mock random number generator use rand_core::{RngCore, Error, impls}; /// A simple implementation of `RngCore` for testing purposes. /// /// This generates an arithmetic sequence (i.e. adds a constant each step) /// over a `u64` number, using wrapping arithmetic. If the increment is 0 /// the generator yields a constant. /// /// ``` /// use rand::Rng; /// use rand::rngs::mock::StepRng; /// /// let mut my_rng = StepRng::new(2, 1); /// let sample: [u64; 3] = my_rng.gen(); /// assert_eq!(sample, [2, 3, 4]); /// ``` #[derive(Debug, Clone)] pub struct StepRng { v: u64, a: u64, } impl StepRng { /// Create a `StepRng`, yielding an arithmetic sequence starting with /// `initial` and incremented by `increment` each time. pub fn new(initial: u64, increment: u64) -> Self { StepRng { v: initial, a: increment } } } impl RngCore for StepRng { #[inline] fn next_u32(&mut self) -> u32 { self.next_u64() as u32 } #[inline] fn next_u64(&mut self) -> u64 { let result = self.v; self.v = self.v.wrapping_add(self.a); result } #[inline] fn fill_bytes(&mut self, dest: &mut [u8]) { impls::fill_bytes_via_next(self, dest); } #[inline] fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.fill_bytes(dest); Ok(()) } } rand-0.7.2/src/rngs/mod.rs010064400017500001750000000131751353146424500135700ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Random number generators and adapters //! //! ## Background: Random number generators (RNGs) //! //! Computers cannot produce random numbers from nowhere. We classify //! random number generators as follows: //! //! - "True" random number generators (TRNGs) use hard-to-predict data sources //! (e.g. the high-resolution parts of event timings and sensor jitter) to //! harvest random bit-sequences, apply algorithms to remove bias and //! estimate available entropy, then combine these bits into a byte-sequence //! or an entropy pool. This job is usually done by the operating system or //! a hardware generator (HRNG). //! - "Pseudo"-random number generators (PRNGs) use algorithms to transform a //! seed into a sequence of pseudo-random numbers. These generators can be //! fast and produce well-distributed unpredictable random numbers (or not). //! They are usually deterministic: given algorithm and seed, the output //! sequence can be reproduced. They have finite period and eventually loop; //! with many algorithms this period is fixed and can be proven sufficiently //! long, while others are chaotic and the period depends on the seed. //! - "Cryptographically secure" pseudo-random number generators (CSPRNGs) //! are the sub-set of PRNGs which are secure. Security of the generator //! relies both on hiding the internal state and using a strong algorithm. //! //! ## Traits and functionality //! //! All RNGs implement the [`RngCore`] trait, as a consequence of which the //! [`Rng`] extension trait is automatically implemented. Secure RNGs may //! additionally implement the [`CryptoRng`] trait. //! //! All PRNGs require a seed to produce their random number sequence. The //! [`SeedableRng`] trait provides three ways of constructing PRNGs: //! //! - `from_seed` accepts a type specific to the PRNG //! - `from_rng` allows a PRNG to be seeded from any other RNG //! - `seed_from_u64` allows any PRNG to be seeded from a `u64` insecurely //! - `from_entropy` securely seeds a PRNG from fresh entropy //! //! Use the [`rand_core`] crate when implementing your own RNGs. //! //! ## Our generators //! //! This crate provides several random number generators: //! //! - [`OsRng`] is an interface to the operating system's random number //! source. Typically the operating system uses a CSPRNG with entropy //! provided by a TRNG and some type of on-going re-seeding. //! - [`ThreadRng`], provided by the [`thread_rng`] function, is a handle to a //! thread-local CSPRNG with periodic seeding from [`OsRng`]. Because this //! is local, it is typically much faster than [`OsRng`]. It should be //! secure, though the paranoid may prefer [`OsRng`]. //! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security //! (based on reviews, maturity and usage). The current algorithm is ChaCha20, //! which is well established and rigorously analysed. //! [`StdRng`] provides the algorithm used by [`ThreadRng`] but without //! periodic reseeding. //! - [`SmallRng`] is an **insecure** PRNG designed to be fast, simple, require //! little memory, and have good output quality. //! //! The algorithms selected for [`StdRng`] and [`SmallRng`] may change in any //! release and may be platform-dependent, therefore they should be considered //! **not reproducible**. //! //! ## Additional generators //! //! **TRNGs**: The [`rdrand`] crate provides an interface to the RDRAND and //! RDSEED instructions available in modern Intel and AMD CPUs. //! The [`rand_jitter`] crate provides a user-space implementation of //! entropy harvesting from CPU timer jitter, but is very slow and has //! [security issues](https://github.com/rust-random/rand/issues/699). //! //! **PRNGs**: Several companion crates are available, providing individual or //! families of PRNG algorithms. These provide the implementations behind //! [`StdRng`] and [`SmallRng`] but can also be used directly, indeed *should* //! be used directly when **reproducibility** matters. //! Some suggestions are: [`rand_chacha`], [`rand_pcg`], [`rand_xoshiro`]. //! A full list can be found by searching for crates with the [`rng` tag]. //! //! [`SmallRng`]: rngs::SmallRng //! [`StdRng`]: rngs::StdRng //! [`OsRng`]: rngs::OsRng //! [`ThreadRng`]: rngs::ThreadRng //! [`mock::StepRng`]: rngs::mock::StepRng //! [`adapter::ReadRng`]: rngs::adapter::ReadRng //! [`adapter::ReseedingRng`]: rngs::adapter::ReseedingRng //! [`rdrand`]: https://crates.io/crates/rdrand //! [`rand_jitter`]: https://crates.io/crates/rand_jitter //! [`rand_chacha`]: https://crates.io/crates/rand_chacha //! [`rand_pcg`]: https://crates.io/crates/rand_pcg //! [`rand_xoshiro`]: https://crates.io/crates/rand_xoshiro //! [`rng` tag]: https://crates.io/keywords/rng pub mod adapter; #[cfg(feature="std")] mod entropy; pub mod mock; // Public so we don't export `StepRng` directly, making it a bit // more clear it is intended for testing. #[cfg(feature="small_rng")] mod small; mod std; #[cfg(feature="std")] pub(crate) mod thread; #[allow(deprecated)] #[cfg(feature="std")] pub use self::entropy::EntropyRng; #[cfg(feature="small_rng")] pub use self::small::SmallRng; pub use self::std::StdRng; #[cfg(feature="std")] pub use self::thread::ThreadRng; #[cfg(feature="getrandom")] pub use rand_core::OsRng; rand-0.7.2/src/rngs/small.rs010064400017500001750000000074601352222772600141220ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A small fast RNG use rand_core::{RngCore, SeedableRng, Error}; #[cfg(all(not(target_os = "emscripten"), target_pointer_width = "64"))] type Rng = rand_pcg::Pcg64Mcg; #[cfg(not(all(not(target_os = "emscripten"), target_pointer_width = "64")))] type Rng = rand_pcg::Pcg32; /// A small-state, fast non-crypto PRNG /// /// `SmallRng` may be a good choice when a PRNG with small state, cheap /// initialization, good statistical quality and good performance are required. /// It is **not** a good choice when security against prediction or /// reproducibility are important. /// /// This PRNG is **feature-gated**: to use, you must enable the crate feature /// `small_rng`. /// /// The algorithm is deterministic but should not be considered reproducible /// due to dependence on platform and possible replacement in future /// library versions. For a reproducible generator, use a named PRNG from an /// external crate, e.g. [rand_pcg] or [rand_chacha]. /// Refer also to [The Book](https://rust-random.github.io/book/guide-rngs.html). /// /// The PRNG algorithm in `SmallRng` is chosen to be /// efficient on the current platform, without consideration for cryptography /// or security. The size of its state is much smaller than [`StdRng`]. /// The current algorithm is [`Pcg64Mcg`](rand_pcg::Pcg64Mcg) on 64-bit /// platforms and [`Pcg32`](rand_pcg::Pcg32) on 32-bit platforms. Both are /// implemented by the [rand_pcg] crate. /// /// # Examples /// /// Initializing `SmallRng` with a random seed can be done using [`SeedableRng::from_entropy`]: /// /// ``` /// use rand::{Rng, SeedableRng}; /// use rand::rngs::SmallRng; /// /// // Create small, cheap to initialize and fast RNG with a random seed. /// // The randomness is supplied by the operating system. /// let mut small_rng = SmallRng::from_entropy(); /// # let v: u32 = small_rng.gen(); /// ``` /// /// When initializing a lot of `SmallRng`'s, using [`thread_rng`] can be more /// efficient: /// /// ``` /// use std::iter; /// use rand::{SeedableRng, thread_rng}; /// use rand::rngs::SmallRng; /// /// // Create a big, expensive to initialize and slower, but unpredictable RNG. /// // This is cached and done only once per thread. /// let mut thread_rng = thread_rng(); /// // Create small, cheap to initialize and fast RNGs with random seeds. /// // One can generally assume this won't fail. /// let rngs: Vec = iter::repeat(()) /// .map(|()| SmallRng::from_rng(&mut thread_rng).unwrap()) /// .take(10) /// .collect(); /// ``` /// /// [`StdRng`]: crate::rngs::StdRng /// [`thread_rng`]: crate::thread_rng /// [rand_chacha]: https://crates.io/crates/rand_chacha /// [rand_pcg]: https://crates.io/crates/rand_pcg #[derive(Clone, Debug)] pub struct SmallRng(Rng); impl RngCore for SmallRng { #[inline(always)] fn next_u32(&mut self) -> u32 { self.0.next_u32() } #[inline(always)] fn next_u64(&mut self) -> u64 { self.0.next_u64() } #[inline(always)] fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest); } #[inline(always)] fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.0.try_fill_bytes(dest) } } impl SeedableRng for SmallRng { type Seed = ::Seed; #[inline(always)] fn from_seed(seed: Self::Seed) -> Self { SmallRng(Rng::from_seed(seed)) } #[inline(always)] fn from_rng(rng: R) -> Result { Rng::from_rng(rng).map(SmallRng) } } rand-0.7.2/src/rngs/std.rs010064400017500001750000000063721353150727500136050ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The standard RNG use crate::{RngCore, CryptoRng, Error, SeedableRng}; #[cfg(all(any(test, feature = "std"), target_os = "emscripten"))] pub(crate) use rand_hc::Hc128Core as Core; #[cfg(all(any(test, feature = "std"), not(target_os = "emscripten")))] pub(crate) use rand_chacha::ChaCha20Core as Core; #[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng; #[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha20Rng as Rng; /// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient /// on the current platform, to be statistically strong and unpredictable /// (meaning a cryptographically secure PRNG). /// /// The current algorithm used is the ChaCha block cipher with either 20 or 12 /// rounds (see the `stdrng_*` feature flags, documented in the README). /// This may change as new evidence of cipher security and performance /// becomes available. /// /// The algorithm is deterministic but should not be considered reproducible /// due to dependence on configuration and possible replacement in future /// library versions. For a secure reproducible generator, we recommend use of /// the [rand_chacha] crate directly. /// /// [rand_chacha]: https://crates.io/crates/rand_chacha #[derive(Clone, Debug)] pub struct StdRng(Rng); impl RngCore for StdRng { #[inline(always)] fn next_u32(&mut self) -> u32 { self.0.next_u32() } #[inline(always)] fn next_u64(&mut self) -> u64 { self.0.next_u64() } #[inline(always)] fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest); } #[inline(always)] fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.0.try_fill_bytes(dest) } } impl SeedableRng for StdRng { type Seed = ::Seed; #[inline(always)] fn from_seed(seed: Self::Seed) -> Self { StdRng(Rng::from_seed(seed)) } #[inline(always)] fn from_rng(rng: R) -> Result { Rng::from_rng(rng).map(StdRng) } } impl CryptoRng for StdRng {} #[cfg(test)] mod test { use crate::{RngCore, SeedableRng}; use crate::rngs::StdRng; #[test] fn test_stdrng_construction() { // Test value-stability of StdRng. This is expected to break any time // the algorithm is changed. let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; #[cfg(any(feature="stdrng_strong", not(feature="stdrng_fast")))] let target = [3950704604716924505, 5573172343717151650]; #[cfg(all(not(feature="stdrng_strong"), feature="stdrng_fast"))] let target = [10719222850664546238, 14064965282130556830]; let mut rng0 = StdRng::from_seed(seed); let x0 = rng0.next_u64(); let mut rng1 = StdRng::from_rng(rng0).unwrap(); let x1 = rng1.next_u64(); assert_eq!([x0, x1], target); } } rand-0.7.2/src/rngs/thread.rs010064400017500001750000000105321352222772600142530ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Thread-local random number generator use std::cell::UnsafeCell; use std::ptr::NonNull; use crate::{RngCore, CryptoRng, SeedableRng, Error}; use crate::rngs::adapter::ReseedingRng; use crate::rngs::OsRng; use super::std::Core; // Rationale for using `UnsafeCell` in `ThreadRng`: // // Previously we used a `RefCell`, with an overhead of ~15%. There will only // ever be one mutable reference to the interior of the `UnsafeCell`, because // we only have such a reference inside `next_u32`, `next_u64`, etc. Within a // single thread (which is the definition of `ThreadRng`), there will only ever // be one of these methods active at a time. // // A possible scenario where there could be multiple mutable references is if // `ThreadRng` is used inside `next_u32` and co. But the implementation is // completely under our control. We just have to ensure none of them use // `ThreadRng` internally, which is nonsensical anyway. We should also never run // `ThreadRng` in destructors of its implementation, which is also nonsensical. // Number of generated bytes after which to reseed `ThreadRng`. // According to benchmarks, reseeding has a noticable impact with thresholds // of 32 kB and less. We choose 64 kB to avoid significant overhead. const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64; /// The type returned by [`thread_rng`], essentially just a reference to the /// PRNG in thread-local memory. /// /// `ThreadRng` uses the same PRNG as [`StdRng`] for security and performance. /// As hinted by the name, the generator is thread-local. `ThreadRng` is a /// handle to this generator and thus supports `Copy`, but not `Send` or `Sync`. /// /// Unlike `StdRng`, `ThreadRng` uses the [`ReseedingRng`] wrapper to reseed /// the PRNG from fresh entropy every 64 kiB of random data. /// [`OsRng`] is used to provide seed data. /// /// Note that the reseeding is done as an extra precaution against side-channel /// attacks and mis-use (e.g. if somehow weak entropy were supplied initially). /// The PRNG algorithms used are assumed to be secure. /// /// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng /// [`StdRng`]: crate::rngs::StdRng #[derive(Copy, Clone, Debug)] pub struct ThreadRng { // inner raw pointer implies type is neither Send nor Sync rng: NonNull>, } thread_local!( static THREAD_RNG_KEY: UnsafeCell> = { let r = Core::from_rng(OsRng).unwrap_or_else(|err| panic!("could not initialize thread_rng: {}", err)); let rng = ReseedingRng::new(r, THREAD_RNG_RESEED_THRESHOLD, OsRng); UnsafeCell::new(rng) } ); /// Retrieve the lazily-initialized thread-local random number generator, /// seeded by the system. Intended to be used in method chaining style, /// e.g. `thread_rng().gen::()`, or cached locally, e.g. /// `let mut rng = thread_rng();`. Invoked by the `Default` trait, making /// `ThreadRng::default()` equivalent. /// /// For more information see [`ThreadRng`]. pub fn thread_rng() -> ThreadRng { let raw = THREAD_RNG_KEY.with(|t| t.get()); let nn = NonNull::new(raw).unwrap(); ThreadRng { rng: nn } } impl Default for ThreadRng { fn default() -> ThreadRng { crate::prelude::thread_rng() } } impl RngCore for ThreadRng { #[inline(always)] fn next_u32(&mut self) -> u32 { unsafe { self.rng.as_mut().next_u32() } } #[inline(always)] fn next_u64(&mut self) -> u64 { unsafe { self.rng.as_mut().next_u64() } } fn fill_bytes(&mut self, dest: &mut [u8]) { unsafe { self.rng.as_mut().fill_bytes(dest) } } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { unsafe { self.rng.as_mut().try_fill_bytes(dest) } } } impl CryptoRng for ThreadRng {} #[cfg(test)] mod test { #[test] fn test_thread_rng() { use crate::Rng; let mut r = crate::thread_rng(); r.gen::(); assert_eq!(r.gen_range(0, 1), 0); } } rand-0.7.2/src/seq/index.rs010064400017500001750000000340501352222772600137330ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Low-level API for sampling indices #[cfg(feature="alloc")] use core::slice; #[cfg(feature="std")] use std::vec; #[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec::{self, Vec}; // BTreeMap is not as fast in tests, but better than nothing. #[cfg(feature="std")] use std::collections::{HashSet}; #[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::collections::BTreeSet; #[cfg(feature="alloc")] use crate::distributions::{Distribution, Uniform, uniform::SampleUniform}; use crate::Rng; /// A vector of indices. /// /// Multiple internal representations are possible. #[derive(Clone, Debug)] pub enum IndexVec { #[doc(hidden)] U32(Vec), #[doc(hidden)] USize(Vec), } impl IndexVec { /// Returns the number of indices #[inline] pub fn len(&self) -> usize { match *self { IndexVec::U32(ref v) => v.len(), IndexVec::USize(ref v) => v.len(), } } /// Returns `true` if the length is 0. #[inline] pub fn is_empty(&self) -> bool { match *self { IndexVec::U32(ref v) => v.is_empty(), IndexVec::USize(ref v) => v.is_empty(), } } /// Return the value at the given `index`. /// /// (Note: we cannot implement [`std::ops::Index`] because of lifetime /// restrictions.) #[inline] pub fn index(&self, index: usize) -> usize { match *self { IndexVec::U32(ref v) => v[index] as usize, IndexVec::USize(ref v) => v[index], } } /// Return result as a `Vec`. Conversion may or may not be trivial. #[inline] pub fn into_vec(self) -> Vec { match self { IndexVec::U32(v) => v.into_iter().map(|i| i as usize).collect(), IndexVec::USize(v) => v, } } /// Iterate over the indices as a sequence of `usize` values #[inline] pub fn iter(&self) -> IndexVecIter<'_> { match *self { IndexVec::U32(ref v) => IndexVecIter::U32(v.iter()), IndexVec::USize(ref v) => IndexVecIter::USize(v.iter()), } } /// Convert into an iterator over the indices as a sequence of `usize` values #[inline] pub fn into_iter(self) -> IndexVecIntoIter { match self { IndexVec::U32(v) => IndexVecIntoIter::U32(v.into_iter()), IndexVec::USize(v) => IndexVecIntoIter::USize(v.into_iter()), } } } impl PartialEq for IndexVec { fn eq(&self, other: &IndexVec) -> bool { use self::IndexVec::*; match (self, other) { (&U32(ref v1), &U32(ref v2)) => v1 == v2, (&USize(ref v1), &USize(ref v2)) => v1 == v2, (&U32(ref v1), &USize(ref v2)) => (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x as usize == *y)), (&USize(ref v1), &U32(ref v2)) => (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as usize)), } } } impl From> for IndexVec { #[inline] fn from(v: Vec) -> Self { IndexVec::U32(v) } } impl From> for IndexVec { #[inline] fn from(v: Vec) -> Self { IndexVec::USize(v) } } /// Return type of `IndexVec::iter`. #[derive(Debug)] pub enum IndexVecIter<'a> { #[doc(hidden)] U32(slice::Iter<'a, u32>), #[doc(hidden)] USize(slice::Iter<'a, usize>), } impl<'a> Iterator for IndexVecIter<'a> { type Item = usize; #[inline] fn next(&mut self) -> Option { use self::IndexVecIter::*; match *self { U32(ref mut iter) => iter.next().map(|i| *i as usize), USize(ref mut iter) => iter.next().cloned(), } } #[inline] fn size_hint(&self) -> (usize, Option) { match *self { IndexVecIter::U32(ref v) => v.size_hint(), IndexVecIter::USize(ref v) => v.size_hint(), } } } impl<'a> ExactSizeIterator for IndexVecIter<'a> {} /// Return type of `IndexVec::into_iter`. #[derive(Clone, Debug)] pub enum IndexVecIntoIter { #[doc(hidden)] U32(vec::IntoIter), #[doc(hidden)] USize(vec::IntoIter), } impl Iterator for IndexVecIntoIter { type Item = usize; #[inline] fn next(&mut self) -> Option { use self::IndexVecIntoIter::*; match *self { U32(ref mut v) => v.next().map(|i| i as usize), USize(ref mut v) => v.next(), } } #[inline] fn size_hint(&self) -> (usize, Option) { use self::IndexVecIntoIter::*; match *self { U32(ref v) => v.size_hint(), USize(ref v) => v.size_hint(), } } } impl ExactSizeIterator for IndexVecIntoIter {} /// Randomly sample exactly `amount` distinct indices from `0..length`, and /// return them in random order (fully shuffled). /// /// This method is used internally by the slice sampling methods, but it can /// sometimes be useful to have the indices themselves so this is provided as /// an alternative. /// /// The implementation used is not specified; we automatically select the /// fastest available algorithm for the `length` and `amount` parameters /// (based on detailed profiling on an Intel Haswell CPU). Roughly speaking, /// complexity is `O(amount)`, except that when `amount` is small, performance /// is closer to `O(amount^2)`, and when `length` is close to `amount` then /// `O(length)`. /// /// Note that performance is significantly better over `u32` indices than over /// `u64` indices. Because of this we hide the underlying type behind an /// abstraction, `IndexVec`. /// /// If an allocation-free `no_std` function is required, it is suggested /// to adapt the internal `sample_floyd` implementation. /// /// Panics if `amount > length`. pub fn sample(rng: &mut R, length: usize, amount: usize) -> IndexVec where R: Rng + ?Sized { if amount > length { panic!("`amount` of samples must be less than or equal to `length`"); } if length > (::core::u32::MAX as usize) { // We never want to use inplace here, but could use floyd's alg // Lazy version: always use the cache alg. return sample_rejection(rng, length, amount); } let amount = amount as u32; let length = length as u32; // Choice of algorithm here depends on both length and amount. See: // https://github.com/rust-random/rand/pull/479 // We do some calculations with f32. Accuracy is not very important. if amount < 163 { const C: [[f32; 2]; 2] = [[1.6, 8.0/45.0], [10.0, 70.0/9.0]]; let j = if length < 500_000 { 0 } else { 1 }; let amount_fp = amount as f32; let m4 = C[0][j] * amount_fp; // Short-cut: when amount < 12, floyd's is always faster if amount > 11 && (length as f32) < (C[1][j] + m4) * amount_fp { sample_inplace(rng, length, amount) } else { sample_floyd(rng, length, amount) } } else { const C: [f32; 2] = [270.0, 330.0/9.0]; let j = if length < 500_000 { 0 } else { 1 }; if (length as f32) < C[j] * (amount as f32) { sample_inplace(rng, length, amount) } else { sample_rejection(rng, length, amount) } } } /// Randomly sample exactly `amount` indices from `0..length`, using Floyd's /// combination algorithm. /// /// The output values are fully shuffled. (Overhead is under 50%.) /// /// This implementation uses `O(amount)` memory and `O(amount^2)` time. fn sample_floyd(rng: &mut R, length: u32, amount: u32) -> IndexVec where R: Rng + ?Sized { // For small amount we use Floyd's fully-shuffled variant. For larger // amounts this is slow due to Vec::insert performance, so we shuffle // afterwards. Benchmarks show little overhead from extra logic. let floyd_shuffle = amount < 50; debug_assert!(amount <= length); let mut indices = Vec::with_capacity(amount as usize); for j in length - amount .. length { let t = rng.gen_range(0, j + 1); if floyd_shuffle { if let Some(pos) = indices.iter().position(|&x| x == t) { indices.insert(pos, j); continue; } } else if indices.contains(&t) { indices.push(j); continue; } indices.push(t); } if !floyd_shuffle { // Reimplement SliceRandom::shuffle with smaller indices for i in (1..amount).rev() { // invariant: elements with index > i have been locked in place. indices.swap(i as usize, rng.gen_range(0, i + 1) as usize); } } IndexVec::from(indices) } /// Randomly sample exactly `amount` indices from `0..length`, using an inplace /// partial Fisher-Yates method. /// Sample an amount of indices using an inplace partial fisher yates method. /// /// This allocates the entire `length` of indices and randomizes only the first `amount`. /// It then truncates to `amount` and returns. /// /// This method is not appropriate for large `length` and potentially uses a lot /// of memory; because of this we only implement for `u32` index (which improves /// performance in all cases). /// /// Set-up is `O(length)` time and memory and shuffling is `O(amount)` time. fn sample_inplace(rng: &mut R, length: u32, amount: u32) -> IndexVec where R: Rng + ?Sized { debug_assert!(amount <= length); let mut indices: Vec = Vec::with_capacity(length as usize); indices.extend(0..length); for i in 0..amount { let j: u32 = rng.gen_range(i, length); indices.swap(i as usize, j as usize); } indices.truncate(amount as usize); debug_assert_eq!(indices.len(), amount as usize); IndexVec::from(indices) } trait UInt: Copy + PartialOrd + Ord + PartialEq + Eq + SampleUniform + core::hash::Hash { fn zero() -> Self; fn as_usize(self) -> usize; } impl UInt for u32 { #[inline] fn zero() -> Self { 0 } #[inline] fn as_usize(self) -> usize { self as usize } } impl UInt for usize { #[inline] fn zero() -> Self { 0 } #[inline] fn as_usize(self) -> usize { self } } /// Randomly sample exactly `amount` indices from `0..length`, using rejection /// sampling. /// /// Since `amount <<< length` there is a low chance of a random sample in /// `0..length` being a duplicate. We test for duplicates and resample where /// necessary. The algorithm is `O(amount)` time and memory. /// /// This function is generic over X primarily so that results are value-stable /// over 32-bit and 64-bit platforms. fn sample_rejection(rng: &mut R, length: X, amount: X) -> IndexVec where R: Rng + ?Sized, IndexVec: From> { debug_assert!(amount < length); #[cfg(feature="std")] let mut cache = HashSet::with_capacity(amount.as_usize()); #[cfg(not(feature="std"))] let mut cache = BTreeSet::new(); let distr = Uniform::new(X::zero(), length); let mut indices = Vec::with_capacity(amount.as_usize()); for _ in 0..amount.as_usize() { let mut pos = distr.sample(rng); while !cache.insert(pos) { pos = distr.sample(rng); } indices.push(pos); } debug_assert_eq!(indices.len(), amount.as_usize()); IndexVec::from(indices) } #[cfg(test)] mod test { #[cfg(feature="std")] use std::vec; #[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec; use super::*; #[test] fn test_sample_boundaries() { let mut r = crate::test::rng(404); assert_eq!(sample_inplace(&mut r, 0, 0).len(), 0); assert_eq!(sample_inplace(&mut r, 1, 0).len(), 0); assert_eq!(sample_inplace(&mut r, 1, 1).into_vec(), vec![0]); assert_eq!(sample_rejection(&mut r, 1u32, 0).len(), 0); assert_eq!(sample_floyd(&mut r, 0, 0).len(), 0); assert_eq!(sample_floyd(&mut r, 1, 0).len(), 0); assert_eq!(sample_floyd(&mut r, 1, 1).into_vec(), vec![0]); // These algorithms should be fast with big numbers. Test average. let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32) .into_iter().sum(); assert!(1 << 25 < sum && sum < (1 << 25) * 25); let sum: usize = sample_floyd(&mut r, 1 << 25, 10) .into_iter().sum(); assert!(1 << 25 < sum && sum < (1 << 25) * 25); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_sample_alg() { let seed_rng = crate::test::rng; // We can't test which algorithm is used directly, but Floyd's alg // should produce different results from the others. (Also, `inplace` // and `cached` currently use different sizes thus produce different results.) // A small length and relatively large amount should use inplace let (length, amount): (usize, usize) = (100, 50); let v1 = sample(&mut seed_rng(420), length, amount); let v2 = sample_inplace(&mut seed_rng(420), length as u32, amount as u32); assert!(v1.iter().all(|e| e < length)); assert_eq!(v1, v2); // Test Floyd's alg does produce different results let v3 = sample_floyd(&mut seed_rng(420), length as u32, amount as u32); assert!(v1 != v3); // A large length and small amount should use Floyd let (length, amount): (usize, usize) = (1<<20, 50); let v1 = sample(&mut seed_rng(421), length, amount); let v2 = sample_floyd(&mut seed_rng(421), length as u32, amount as u32); assert!(v1.iter().all(|e| e < length)); assert_eq!(v1, v2); // A large length and larger amount should use cache let (length, amount): (usize, usize) = (1<<20, 600); let v1 = sample(&mut seed_rng(422), length, amount); let v2 = sample_rejection(&mut seed_rng(422), length as u32, amount as u32); assert!(v1.iter().all(|e| e < length)); assert_eq!(v1, v2); } } rand-0.7.2/src/seq/mod.rs010064400017500001750000000661571352222772600134200ustar0000000000000000// Copyright 2018 Developers of the Rand project. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Sequence-related functionality //! //! This module provides: //! //! * [`seq::SliceRandom`] slice sampling and mutation //! * [`seq::IteratorRandom`] iterator sampling //! * [`seq::index::sample`] low-level API to choose multiple indices from //! `0..length` //! //! Also see: //! //! * [`distributions::weighted`] module which provides implementations of //! weighted index sampling. //! //! In order to make results reproducible across 32-64 bit architectures, all //! `usize` indices are sampled as a `u32` where possible (also providing a //! small performance boost in some cases). #[cfg(feature="alloc")] pub mod index; #[cfg(feature="alloc")] use core::ops::Index; #[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec::Vec; use crate::Rng; #[cfg(feature="alloc")] use crate::distributions::WeightedError; #[cfg(feature="alloc")] use crate::distributions::uniform::{SampleUniform, SampleBorrow}; /// Extension trait on slices, providing random mutation and sampling methods. /// /// This trait is implemented on all `[T]` slice types, providing several /// methods for choosing and shuffling elements. You must `use` this trait: /// /// ``` /// use rand::seq::SliceRandom; /// /// fn main() { /// let mut rng = rand::thread_rng(); /// let mut bytes = "Hello, random!".to_string().into_bytes(); /// bytes.shuffle(&mut rng); /// let str = String::from_utf8(bytes).unwrap(); /// println!("{}", str); /// } /// ``` /// Example output (non-deterministic): /// ```none /// l,nmroHado !le /// ``` pub trait SliceRandom { /// The element type. type Item; /// Returns a reference to one random element of the slice, or `None` if the /// slice is empty. /// /// For slices, complexity is `O(1)`. /// /// # Example /// /// ``` /// use rand::thread_rng; /// use rand::seq::SliceRandom; /// /// let choices = [1, 2, 4, 8, 16, 32]; /// let mut rng = thread_rng(); /// println!("{:?}", choices.choose(&mut rng)); /// assert_eq!(choices[..0].choose(&mut rng), None); /// ``` fn choose(&self, rng: &mut R) -> Option<&Self::Item> where R: Rng + ?Sized; /// Returns a mutable reference to one random element of the slice, or /// `None` if the slice is empty. /// /// For slices, complexity is `O(1)`. fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> where R: Rng + ?Sized; /// Chooses `amount` elements from the slice at random, without repetition, /// and in random order. The returned iterator is appropriate both for /// collection into a `Vec` and filling an existing buffer (see example). /// /// In case this API is not sufficiently flexible, use [`index::sample`]. /// /// For slices, complexity is the same as [`index::sample`]. /// /// # Example /// ``` /// use rand::seq::SliceRandom; /// /// let mut rng = &mut rand::thread_rng(); /// let sample = "Hello, audience!".as_bytes(); /// /// // collect the results into a vector: /// let v: Vec = sample.choose_multiple(&mut rng, 3).cloned().collect(); /// /// // store in a buffer: /// let mut buf = [0u8; 5]; /// for (b, slot) in sample.choose_multiple(&mut rng, buf.len()).zip(buf.iter_mut()) { /// *slot = *b; /// } /// ``` #[cfg(feature = "alloc")] fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter where R: Rng + ?Sized; /// Similar to [`choose`], but where the likelihood of each outcome may be /// specified. /// /// The specified function `weight` maps each item `x` to a relative /// likelihood `weight(x)`. The probability of each item being selected is /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. /// /// For slices of length `n`, complexity is `O(n)`. /// See also [`choose_weighted_mut`], [`distributions::weighted`]. /// /// # Example /// /// ``` /// use rand::prelude::*; /// /// let choices = [('a', 2), ('b', 1), ('c', 1)]; /// let mut rng = thread_rng(); /// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c' /// println!("{:?}", choices.choose_weighted(&mut rng, |item| item.1).unwrap().0); /// ``` /// [`choose`]: SliceRandom::choose /// [`choose_weighted_mut`]: SliceRandom::choose_weighted_mut /// [`distributions::weighted`]: crate::distributions::weighted #[cfg(feature = "alloc")] fn choose_weighted( &self, rng: &mut R, weight: F, ) -> Result<&Self::Item, WeightedError> where R: Rng + ?Sized, F: Fn(&Self::Item) -> B, B: SampleBorrow, X: SampleUniform + for<'a> ::core::ops::AddAssign<&'a X> + ::core::cmp::PartialOrd + Clone + Default; /// Similar to [`choose_mut`], but where the likelihood of each outcome may /// be specified. /// /// The specified function `weight` maps each item `x` to a relative /// likelihood `weight(x)`. The probability of each item being selected is /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. /// /// For slices of length `n`, complexity is `O(n)`. /// See also [`choose_weighted`], [`distributions::weighted`]. /// /// [`choose_mut`]: SliceRandom::choose_mut /// [`choose_weighted`]: SliceRandom::choose_weighted /// [`distributions::weighted`]: crate::distributions::weighted #[cfg(feature = "alloc")] fn choose_weighted_mut( &mut self, rng: &mut R, weight: F, ) -> Result<&mut Self::Item, WeightedError> where R: Rng + ?Sized, F: Fn(&Self::Item) -> B, B: SampleBorrow, X: SampleUniform + for<'a> ::core::ops::AddAssign<&'a X> + ::core::cmp::PartialOrd + Clone + Default; /// Shuffle a mutable slice in place. /// /// For slices of length `n`, complexity is `O(n)`. /// /// # Example /// /// ``` /// use rand::seq::SliceRandom; /// use rand::thread_rng; /// /// let mut rng = thread_rng(); /// let mut y = [1, 2, 3, 4, 5]; /// println!("Unshuffled: {:?}", y); /// y.shuffle(&mut rng); /// println!("Shuffled: {:?}", y); /// ``` fn shuffle(&mut self, rng: &mut R) where R: Rng + ?Sized; /// Shuffle a slice in place, but exit early. /// /// Returns two mutable slices from the source slice. The first contains /// `amount` elements randomly permuted. The second has the remaining /// elements that are not fully shuffled. /// /// This is an efficient method to select `amount` elements at random from /// the slice, provided the slice may be mutated. /// /// If you only need to choose elements randomly and `amount > self.len()/2` /// then you may improve performance by taking /// `amount = values.len() - amount` and using only the second slice. /// /// If `amount` is greater than the number of elements in the slice, this /// will perform a full shuffle. /// /// For slices, complexity is `O(m)` where `m = amount`. fn partial_shuffle( &mut self, rng: &mut R, amount: usize, ) -> (&mut [Self::Item], &mut [Self::Item]) where R: Rng + ?Sized; } /// Extension trait on iterators, providing random sampling methods. /// /// This trait is implemented on all sized iterators, providing methods for /// choosing one or more elements. You must `use` this trait: /// /// ``` /// use rand::seq::IteratorRandom; /// /// fn main() { /// let mut rng = rand::thread_rng(); /// /// let faces = "πŸ˜€πŸ˜ŽπŸ˜πŸ˜•πŸ˜ πŸ˜’"; /// println!("I am {}!", faces.chars().choose(&mut rng).unwrap()); /// } /// ``` /// Example output (non-deterministic): /// ```none /// I am πŸ˜€! /// ``` pub trait IteratorRandom: Iterator + Sized { /// Choose one element at random from the iterator. /// /// Returns `None` if and only if the iterator is empty. /// /// This method uses [`Iterator::size_hint`] for optimisation. With an /// accurate hint and where [`Iterator::nth`] is a constant-time operation /// this method can offer `O(1)` performance. Where no size hint is /// available, complexity is `O(n)` where `n` is the iterator length. /// Partial hints (where `lower > 0`) also improve performance. /// /// For slices, prefer [`SliceRandom::choose`] which guarantees `O(1)` /// performance. fn choose(mut self, rng: &mut R) -> Option where R: Rng + ?Sized { let (mut lower, mut upper) = self.size_hint(); let mut consumed = 0; let mut result = None; if upper == Some(lower) { return if lower == 0 { None } else { self.nth(gen_index(rng, lower)) }; } // Continue until the iterator is exhausted loop { if lower > 1 { let ix = gen_index(rng, lower + consumed); let skip = if ix < lower { result = self.nth(ix); lower - (ix + 1) } else { lower }; if upper == Some(lower) { return result; } consumed += lower; if skip > 0 { self.nth(skip - 1); } } else { let elem = self.next(); if elem.is_none() { return result; } consumed += 1; let denom = consumed as f64; // accurate to 2^53 elements if rng.gen_bool(1.0 / denom) { result = elem; } } let hint = self.size_hint(); lower = hint.0; upper = hint.1; } } /// Collects values at random from the iterator into a supplied buffer /// until that buffer is filled. /// /// Although the elements are selected randomly, the order of elements in /// the buffer is neither stable nor fully random. If random ordering is /// desired, shuffle the result. /// /// Returns the number of elements added to the buffer. This equals the length /// of the buffer unless the iterator contains insufficient elements, in which /// case this equals the number of elements available. /// /// Complexity is `O(n)` where `n` is the length of the iterator. /// For slices, prefer [`SliceRandom::choose_multiple`]. fn choose_multiple_fill(mut self, rng: &mut R, buf: &mut [Self::Item]) -> usize where R: Rng + ?Sized { let amount = buf.len(); let mut len = 0; while len < amount { if let Some(elem) = self.next() { buf[len] = elem; len += 1; } else { // Iterator exhausted; stop early return len; } } // Continue, since the iterator was not exhausted for (i, elem) in self.enumerate() { let k = gen_index(rng, i + 1 + amount); if let Some(slot) = buf.get_mut(k) { *slot = elem; } } len } /// Collects `amount` values at random from the iterator into a vector. /// /// This is equivalent to `choose_multiple_fill` except for the result type. /// /// Although the elements are selected randomly, the order of elements in /// the buffer is neither stable nor fully random. If random ordering is /// desired, shuffle the result. /// /// The length of the returned vector equals `amount` unless the iterator /// contains insufficient elements, in which case it equals the number of /// elements available. /// /// Complexity is `O(n)` where `n` is the length of the iterator. /// For slices, prefer [`SliceRandom::choose_multiple`]. #[cfg(feature = "alloc")] fn choose_multiple(mut self, rng: &mut R, amount: usize) -> Vec where R: Rng + ?Sized { let mut reservoir = Vec::with_capacity(amount); reservoir.extend(self.by_ref().take(amount)); // Continue unless the iterator was exhausted // // note: this prevents iterators that "restart" from causing problems. // If the iterator stops once, then so do we. if reservoir.len() == amount { for (i, elem) in self.enumerate() { let k = gen_index(rng, i + 1 + amount); if let Some(slot) = reservoir.get_mut(k) { *slot = elem; } } } else { // Don't hang onto extra memory. There is a corner case where // `amount` was much less than `self.len()`. reservoir.shrink_to_fit(); } reservoir } } impl SliceRandom for [T] { type Item = T; fn choose(&self, rng: &mut R) -> Option<&Self::Item> where R: Rng + ?Sized { if self.is_empty() { None } else { Some(&self[gen_index(rng, self.len())]) } } fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> where R: Rng + ?Sized { if self.is_empty() { None } else { let len = self.len(); Some(&mut self[gen_index(rng, len)]) } } #[cfg(feature = "alloc")] fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter where R: Rng + ?Sized { let amount = ::core::cmp::min(amount, self.len()); SliceChooseIter { slice: self, _phantom: Default::default(), indices: index::sample(rng, self.len(), amount).into_iter(), } } #[cfg(feature = "alloc")] fn choose_weighted( &self, rng: &mut R, weight: F, ) -> Result<&Self::Item, WeightedError> where R: Rng + ?Sized, F: Fn(&Self::Item) -> B, B: SampleBorrow, X: SampleUniform + for<'a> ::core::ops::AddAssign<&'a X> + ::core::cmp::PartialOrd + Clone + Default, { use crate::distributions::{Distribution, WeightedIndex}; let distr = WeightedIndex::new(self.iter().map(weight))?; Ok(&self[distr.sample(rng)]) } #[cfg(feature = "alloc")] fn choose_weighted_mut( &mut self, rng: &mut R, weight: F, ) -> Result<&mut Self::Item, WeightedError> where R: Rng + ?Sized, F: Fn(&Self::Item) -> B, B: SampleBorrow, X: SampleUniform + for<'a> ::core::ops::AddAssign<&'a X> + ::core::cmp::PartialOrd + Clone + Default, { use crate::distributions::{Distribution, WeightedIndex}; let distr = WeightedIndex::new(self.iter().map(weight))?; Ok(&mut self[distr.sample(rng)]) } fn shuffle(&mut self, rng: &mut R) where R: Rng + ?Sized { for i in (1..self.len()).rev() { // invariant: elements with index > i have been locked in place. self.swap(i, gen_index(rng, i + 1)); } } fn partial_shuffle( &mut self, rng: &mut R, amount: usize, ) -> (&mut [Self::Item], &mut [Self::Item]) where R: Rng + ?Sized { // This applies Durstenfeld's algorithm for the // [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) // for an unbiased permutation, but exits early after choosing `amount` // elements. let len = self.len(); let end = if amount >= len { 0 } else { len - amount }; for i in (end..len).rev() { // invariant: elements with index > i have been locked in place. self.swap(i, gen_index(rng, i + 1)); } let r = self.split_at_mut(end); (r.1, r.0) } } impl IteratorRandom for I where I: Iterator + Sized {} /// An iterator over multiple slice elements. /// /// This struct is created by /// [`SliceRandom::choose_multiple`](trait.SliceRandom.html#tymethod.choose_multiple). #[cfg(feature = "alloc")] #[derive(Debug)] pub struct SliceChooseIter<'a, S: ?Sized + 'a, T: 'a> { slice: &'a S, _phantom: ::core::marker::PhantomData, indices: index::IndexVecIntoIter, } #[cfg(feature = "alloc")] impl<'a, S: Index + ?Sized + 'a, T: 'a> Iterator for SliceChooseIter<'a, S, T> { type Item = &'a T; fn next(&mut self) -> Option { // TODO: investigate using SliceIndex::get_unchecked when stable self.indices.next().map(|i| &self.slice[i as usize]) } fn size_hint(&self) -> (usize, Option) { (self.indices.len(), Some(self.indices.len())) } } #[cfg(feature = "alloc")] impl<'a, S: Index + ?Sized + 'a, T: 'a> ExactSizeIterator for SliceChooseIter<'a, S, T> { fn len(&self) -> usize { self.indices.len() } } // Sample a number uniformly between 0 and `ubound`. Uses 32-bit sampling where // possible, primarily in order to produce the same output on 32-bit and 64-bit // platforms. #[inline] fn gen_index(rng: &mut R, ubound: usize) -> usize { if ubound <= (core::u32::MAX as usize) { rng.gen_range(0, ubound as u32) as usize } else { rng.gen_range(0, ubound) } } #[cfg(test)] mod test { use super::*; #[cfg(feature = "alloc")] use crate::Rng; #[cfg(all(feature="alloc", not(feature="std")))] use alloc::vec::Vec; #[test] fn test_slice_choose() { let mut r = crate::test::rng(107); let chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']; let mut chosen = [0i32; 14]; // The below all use a binomial distribution with n=1000, p=1/14. // binocdf(40, 1000, 1/14) ~= 2e-5; 1-binocdf(106, ..) ~= 2e-5 for _ in 0..1000 { let picked = *chars.choose(&mut r).unwrap(); chosen[(picked as usize) - ('a' as usize)] += 1; } for count in chosen.iter() { assert!(40 < *count && *count < 106); } chosen.iter_mut().for_each(|x| *x = 0); for _ in 0..1000 { *chosen.choose_mut(&mut r).unwrap() += 1; } for count in chosen.iter() { assert!(40 < *count && *count < 106); } let mut v: [isize; 0] = []; assert_eq!(v.choose(&mut r), None); assert_eq!(v.choose_mut(&mut r), None); } #[derive(Clone)] struct UnhintedIterator { iter: I, } impl Iterator for UnhintedIterator { type Item = I::Item; fn next(&mut self) -> Option { self.iter.next() } } #[derive(Clone)] struct ChunkHintedIterator { iter: I, chunk_remaining: usize, chunk_size: usize, hint_total_size: bool, } impl Iterator for ChunkHintedIterator { type Item = I::Item; fn next(&mut self) -> Option { if self.chunk_remaining == 0 { self.chunk_remaining = ::core::cmp::min(self.chunk_size, self.iter.len()); } self.chunk_remaining = self.chunk_remaining.saturating_sub(1); self.iter.next() } fn size_hint(&self) -> (usize, Option) { (self.chunk_remaining, if self.hint_total_size { Some(self.iter.len()) } else { None }) } } #[derive(Clone)] struct WindowHintedIterator { iter: I, window_size: usize, hint_total_size: bool, } impl Iterator for WindowHintedIterator { type Item = I::Item; fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { (::core::cmp::min(self.iter.len(), self.window_size), if self.hint_total_size { Some(self.iter.len()) } else { None }) } } #[test] #[cfg(not(miri))] // Miri is too slow fn test_iterator_choose() { let r = &mut crate::test::rng(109); fn test_iter + Clone>(r: &mut R, iter: Iter) { let mut chosen = [0i32; 9]; for _ in 0..1000 { let picked = iter.clone().choose(r).unwrap(); chosen[picked] += 1; } for count in chosen.iter() { // Samples should follow Binomial(1000, 1/9) // Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x // Note: have seen 153, which is unlikely but not impossible. assert!(72 < *count && *count < 154, "count not close to 1000/9: {}", count); } } test_iter(r, 0..9); test_iter(r, [0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()); #[cfg(feature = "alloc")] test_iter(r, (0..9).collect::>().into_iter()); test_iter(r, UnhintedIterator { iter: 0..9 }); test_iter(r, ChunkHintedIterator { iter: 0..9, chunk_size: 4, chunk_remaining: 4, hint_total_size: false }); test_iter(r, ChunkHintedIterator { iter: 0..9, chunk_size: 4, chunk_remaining: 4, hint_total_size: true }); test_iter(r, WindowHintedIterator { iter: 0..9, window_size: 2, hint_total_size: false }); test_iter(r, WindowHintedIterator { iter: 0..9, window_size: 2, hint_total_size: true }); assert_eq!((0..0).choose(r), None); assert_eq!(UnhintedIterator{ iter: 0..0 }.choose(r), None); } #[test] #[cfg(not(miri))] // Miri is too slow fn test_shuffle() { let mut r = crate::test::rng(108); let empty: &mut [isize] = &mut []; empty.shuffle(&mut r); let mut one = [1]; one.shuffle(&mut r); let b: &[_] = &[1]; assert_eq!(one, b); let mut two = [1, 2]; two.shuffle(&mut r); assert!(two == [1, 2] || two == [2, 1]); fn move_last(slice: &mut [usize], pos: usize) { // use slice[pos..].rotate_left(1); once we can use that let last_val = slice[pos]; for i in pos..slice.len() - 1 { slice[i] = slice[i + 1]; } *slice.last_mut().unwrap() = last_val; } let mut counts = [0i32; 24]; for _ in 0..10000 { let mut arr: [usize; 4] = [0, 1, 2, 3]; arr.shuffle(&mut r); let mut permutation = 0usize; let mut pos_value = counts.len(); for i in 0..4 { pos_value /= 4 - i; let pos = arr.iter().position(|&x| x == i).unwrap(); assert!(pos < (4 - i)); permutation += pos * pos_value; move_last(&mut arr, pos); assert_eq!(arr[3], i); } for i in 0..4 { assert_eq!(arr[i], i); } counts[permutation] += 1; } for count in counts.iter() { // Binomial(10000, 1/24) with average 416.667 // Octave: binocdf(n, 10000, 1/24) // 99.9% chance samples lie within this range: assert!(352 <= *count && *count <= 483, "count: {}", count); } } #[test] fn test_partial_shuffle() { let mut r = crate::test::rng(118); let mut empty: [u32; 0] = []; let res = empty.partial_shuffle(&mut r, 10); assert_eq!((res.0.len(), res.1.len()), (0, 0)); let mut v = [1, 2, 3, 4, 5]; let res = v.partial_shuffle(&mut r, 2); assert_eq!((res.0.len(), res.1.len()), (2, 3)); assert!(res.0[0] != res.0[1]); // First elements are only modified if selected, so at least one isn't modified: assert!(res.1[0] == 1 || res.1[1] == 2 || res.1[2] == 3); } #[test] #[cfg(feature = "alloc")] fn test_sample_iter() { let min_val = 1; let max_val = 100; let mut r = crate::test::rng(401); let vals = (min_val..max_val).collect::>(); let small_sample = vals.iter().choose_multiple(&mut r, 5); let large_sample = vals.iter().choose_multiple(&mut r, vals.len() + 5); assert_eq!(small_sample.len(), 5); assert_eq!(large_sample.len(), vals.len()); // no randomization happens when amount >= len assert_eq!(large_sample, vals.iter().collect::>()); assert!(small_sample.iter().all(|e| { **e >= min_val && **e <= max_val })); } #[test] #[cfg(feature = "alloc")] #[cfg(not(miri))] // Miri is too slow fn test_weighted() { let mut r = crate::test::rng(406); const N_REPS: u32 = 3000; let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; let total_weight = weights.iter().sum::() as f32; let verify = |result: [i32; 14]| { for (i, count) in result.iter().enumerate() { let exp = (weights[i] * N_REPS) as f32 / total_weight; let mut err = (*count as f32 - exp).abs(); if err != 0.0 { err /= exp; } assert!(err <= 0.25); } }; // choose_weighted fn get_weight(item: &(u32, T)) -> u32 { item.0 } let mut chosen = [0i32; 14]; let mut items = [(0u32, 0usize); 14]; // (weight, index) for (i, item) in items.iter_mut().enumerate() { *item = (weights[i], i); } for _ in 0..N_REPS { let item = items.choose_weighted(&mut r, get_weight).unwrap(); chosen[item.1] += 1; } verify(chosen); // choose_weighted_mut let mut items = [(0u32, 0i32); 14]; // (weight, count) for (i, item) in items.iter_mut().enumerate() { *item = (weights[i], 0); } for _ in 0..N_REPS { items.choose_weighted_mut(&mut r, get_weight).unwrap().1 += 1; } for (ch, item) in chosen.iter_mut().zip(items.iter()) { *ch = item.1; } verify(chosen); // Check error cases let empty_slice = &mut [10][0..0]; assert_eq!(empty_slice.choose_weighted(&mut r, |_| 1), Err(WeightedError::NoItem)); assert_eq!(empty_slice.choose_weighted_mut(&mut r, |_| 1), Err(WeightedError::NoItem)); assert_eq!(['x'].choose_weighted_mut(&mut r, |_| 0), Err(WeightedError::AllWeightsZero)); assert_eq!([0, -1].choose_weighted_mut(&mut r, |x| *x), Err(WeightedError::InvalidWeight)); assert_eq!([-1, 0].choose_weighted_mut(&mut r, |x| *x), Err(WeightedError::InvalidWeight)); } } rand-0.7.2/.cargo_vcs_info.json0000644000000001120000000000000120170ustar00{ "git": { "sha1": "249ebfc4352d8f3e1ebcb2a884f047b31ba32981" } } rand-0.7.2/Cargo.lock0000644000000460730000000000000100120ustar00# This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "autocfg" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "base-x" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bumpalo" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cfg-if" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getrandom" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ppv-lite86" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" version = "0.7.2" dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_isaac" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_pcg" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xorshift" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xoshiro" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ryu" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "stdweb" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb-internal-macros 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb-internal-runtime 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "stdweb-derive" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "stdweb-internal-macros" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base-x 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "stdweb-internal-runtime" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen" version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-macro 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-macro-support 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" "checksum base-x 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "76f4eae81729e69bb1819a26c6caac956cc429238388091f98cb6cd858f16443" "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" "checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df6b0b3dc9991a10b2d91a86d1129314502169a1bf6afa67328945e02498b76" "checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6" "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" "checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a" "checksum serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "11e410fde43e157d789fc290d26bc940778ad0fdd47836426fbac36573710dbb" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum stdweb 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a68c0ce28cf7400ed022e18da3c4591e14e1df02c70e93573cc59921b3923aeb" "checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" "checksum stdweb-internal-macros 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e68f7d08b76979a43e93fe043b66d2626e35d41d68b0b85519202c6dd8ac59fa" "checksum stdweb-internal-runtime 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d52317523542cc0af5b7e31017ad0f7d1e78da50455e38d5657cd17754f617da" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "dcddca308b16cd93c2b67b126c688e5467e4ef2e28200dc7dfe4ae284f2faefc" "checksum wasm-bindgen-backend 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "f805d9328b5fc7e5c6399960fd1889271b9b58ae17bdb2417472156cc9fafdd0" "checksum wasm-bindgen-macro 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff88201a482abfc63921621f6cb18eb1efd74f136b05e5841e7f8ca434539e9" "checksum wasm-bindgen-macro-support 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "6a433d89ecdb9f77d46fcf00c8cf9f3467b7de9954d8710c175f61e2e245bb0e" "checksum wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "d41fc1bc3570cdf8d108c15e014045fd45a95bb5eb36605f96a90461fc34027d"