rand-0.5.5/.gitignore010064400017500001750000000000221323241303400126430ustar0000000000000000target Cargo.lock rand-0.5.5/.travis.yml010064400017500001750000000073071333210603300130000ustar0000000000000000language: rust sudo: false # We aim to test all the following in any combination: # - standard tests, benches, documentation, all available features # - pinned stable, latest stable, beta and nightly Rust releases # - Linux, OS X, Android, iOS, bare metal (i.e. no_std) # - x86_64, ARMv7, a Big-Endian arch (MIPS) matrix: include: - rust: 1.22.0 install: script: - cargo test --tests --no-default-features - cargo test --package rand_core --no-default-features - cargo test --features serde1,log - rust: stable os: osx install: script: - cargo test --tests --no-default-features - cargo test --package rand_core --no-default-features - cargo test --features serde1,log - rust: beta install: script: - cargo test --tests --no-default-features - cargo test --package rand_core --no-default-features - cargo test --features serde1,log - rust: nightly install: - cargo --list | egrep "^\s*deadlinks$" -q || cargo install cargo-deadlinks before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo test --tests --no-default-features --features=alloc - cargo test --package rand_core --no-default-features --features=alloc,serde1 - cargo test --features serde1,log,nightly,alloc - cargo test --all --benches # remove cached documentation, otherwise files from previous PRs can get included - rm -rf target/doc - cargo doc --no-deps --all --all-features - cargo deadlinks --dir target/doc after_success: - travis-cargo --only nightly doc-upload - rust: nightly install: - rustup target add wasm32-unknown-unknown # Use cargo-update since we need a real update-or-install command # Only install if not already installed: #- cargo --list | egrep "\binstall-update$" -q || cargo install cargo-update #- cargo install-update -i cargo-web # Cargo has errors with sub-commands so ignore updating for now: - cargo --list | egrep "^\s*web$" -q || cargo install cargo-web script: - cargo web test --target wasm32-unknown-unknown --nodejs --features=stdweb - rust: nightly install: - rustup target add thumbv6m-none-eabi script: # Bare metal target; no std; only works on nightly - cargo build --no-default-features --target thumbv6m-none-eabi --release # Trust cross-built/emulated targets. We must repeat all non-default values. - rust: stable sudo: required dist: trusty services: docker env: TARGET=x86_64-unknown-freebsd DISABLE_TESTS=1 - rust: stable sudo: required dist: trusty services: docker env: TARGET=mips-unknown-linux-gnu - rust: stable sudo: required dist: trusty services: docker env: TARGET=armv7-linux-androideabi DISABLE_TESTS=1 - rust: stable os: osx sudo: required dist: trusty services: docker env: TARGET=armv7-apple-ios DISABLE_TESTS=1 before_install: - set -e - rustup self update # Used by all Trust targets; others must override: install: - sh utils/ci/install.sh - source ~/.cargo/env || true script: - bash utils/ci/script.sh after_script: set +e cache: cargo before_cache: # Travis can't cache files that are not readable by "others" - chmod -R a+r $HOME/.cargo env: global: secure: "BdDntVHSompN+Qxz5Rz45VI4ZqhD72r6aPl166FADlnkIwS6N6FLWdqs51O7G5CpoMXEDvyYrjmRMZe/GYLIG9cmqmn/wUrWPO+PauGiIuG/D2dmfuUNvSTRcIe7UQLXrfP3yyfZPgqsH6pSnNEVopquQKy3KjzqepgriOJtbyY=" notifications: email: on_success: never rand-0.5.5/CHANGELOG.md010064400017500001750000000311221333210665400125010ustar0000000000000000# 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 [Update Guide](UPDATING.md) useful. ## [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.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.5.5/CONTRIBUTING.md010064400017500001750000000055621331613237300131310ustar0000000000000000# Contributing to Rand Thank you for your interest in contributing to Rand! The following is a list of notes and tips for when you want to contribute to Rand with a pull request. If you want to make major changes, it is usually best to open an issue to discuss the idea first. Rand doesn't (yet) use rustfmt. It is best to follow the style of the surrounding code, and try to keep an 80 character line limit. ## Documentation We especially welcome documentation PRs. As of Rust 1.25 there are differences in how stable and nightly render documentation links. Make sure it works on stable, then nightly should be good too. One Travis CI build checks for dead links using `cargo-deadlinks`. If you want to run the check locally: ```sh cargo install cargo-deadlinks # It is recommended to remove left-over files from previous compilations rm -rf /target/doc cargo doc --no-deps cargo deadlinks --dir target/doc ``` When making changes to code examples in the documentation, make sure they build with: ```sh cargo test --doc ``` A helpful command to rebuild documentation automatically on save (only works on Linux): ``` while inotifywait -r -e close_write src/ rand_core/; do cargo doc; done ``` ## Testing Rand already contains a number of unit tests, but could use more. Also the existing ones could use clean-up. Any work on the tests is appreciated. Not every change or new bit of functionality requires tests, but if you can think of a test that adds value, please add it. Depending on the code you change, test with one of: ```sh cargo test cargo test --package rand_core # Test log, serde and 128-bit support cargo test --features serde1,log,nightly ``` We want to be able to not only run the unit tests with `std` available, but also without. Because `thread_rng()` and `FromEntropy` are not available without the `std` feature, you may have to disable a new test with `#[cfg(feature="std")]`. In other cases using `::test::rng` with a constant seed is a good option: ```rust let mut rng = ::test::rng(528); // just pick some number ``` Only the unit tests should work in `no_std` mode, we don't want to complicate the doc-tests. Run the tests with: ```sh # Test no_std support cargo test --lib --no-default-features cargo test --package rand_core --no-default-features # Test no_std+alloc support; requires nightly cargo test --lib --no-default-features --features alloc ``` ## Benchmarking A lot of code in Rand is performance-sensitive, most of it is expected to be used in hot loops in some libraries/applications. If you change code in the `rngs`, `prngs` or `distributions` modules, especially when you see an 'obvious cleanup', make sure the benchmarks do not regress. It is nice to report the benchmark results in the PR (or to report nothing's changed). ```sh # Benchmarks (requires nightly) cargo bench # Some benchmarks have a faster path with i128_support cargo bench --features=nightly ``` rand-0.5.5/Cargo.toml.orig010064400017500001750000000040711333210667500135650ustar0000000000000000[package] name = "rand" version = "0.5.5" # NB: When modifying, also modify html_root_url in lib.rs authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" repository = "https://github.com/rust-lang-nursery/rand" documentation = "https://docs.rs/rand" homepage = "https://crates.io/crates/rand" description = """ Random number generators and other randomness functionality. """ keywords = ["random", "rng"] categories = ["algorithms", "no-std"] [badges] travis-ci = { repository = "rust-lang-nursery/rand" } appveyor = { repository = "alexcrichton/rand" } [features] default = ["std" ] # without "std" rand uses libcore nightly = ["i128_support"] # enables all features requiring nightly rust std = ["rand_core/std", "alloc", "libc", "winapi", "cloudabi", "fuchsia-zircon"] alloc = ["rand_core/alloc"] # enables Vec and Box support (without std) i128_support = [] # enables i128 and u128 support serde1 = ["serde", "serde_derive", "rand_core/serde1"] # enables serialization for PRNGs [workspace] members = ["rand_core"] [dependencies] rand_core = { path = "rand_core", version = "0.2", default-features = false } log = { version = "0.4", optional = true } serde = { version = "1", optional = true } serde_derive = { version = "1", optional = true } [target.'cfg(unix)'.dependencies] libc = { version = "0.2", optional = true } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["minwindef", "ntsecapi", "profileapi", "winnt"], optional = true } [target.'cfg(target_os = "cloudabi")'.dependencies] cloudabi = { version = "0.0.3", optional = true } [target.'cfg(target_os = "fuchsia")'.dependencies] fuchsia-zircon = { version = "0.3.2", optional = true } [target.wasm32-unknown-unknown.dependencies] # use with `--target wasm32-unknown-unknown --features=stdweb` stdweb = { version = "0.4", optional = true } [dev-dependencies] # This is for testing serde, unfortunately we can't specify feature-gated dev # deps yet, see: https://github.com/rust-lang/cargo/issues/1596 bincode = "1.0" [package.metadata.docs.rs] all-features = true rand-0.5.5/Cargo.toml0000644000000040620000000000000100260ustar00# 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] name = "rand" version = "0.5.5" authors = ["The Rust Project Developers"] description = "Random number generators and other randomness functionality.\n" homepage = "https://crates.io/crates/rand" documentation = "https://docs.rs/rand" readme = "README.md" keywords = ["random", "rng"] categories = ["algorithms", "no-std"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang-nursery/rand" [package.metadata.docs.rs] all-features = true [dependencies.log] version = "0.4" optional = true [dependencies.rand_core] version = "0.2" default-features = false [dependencies.serde] version = "1" optional = true [dependencies.serde_derive] version = "1" optional = true [dev-dependencies.bincode] version = "1.0" [features] alloc = ["rand_core/alloc"] default = ["std"] i128_support = [] nightly = ["i128_support"] serde1 = ["serde", "serde_derive", "rand_core/serde1"] std = ["rand_core/std", "alloc", "libc", "winapi", "cloudabi", "fuchsia-zircon"] [target."cfg(target_os = \"cloudabi\")".dependencies.cloudabi] version = "0.0.3" optional = true [target."cfg(target_os = \"fuchsia\")".dependencies.fuchsia-zircon] version = "0.3.2" optional = true [target."cfg(unix)".dependencies.libc] version = "0.2" optional = true [target."cfg(windows)".dependencies.winapi] version = "0.3" features = ["minwindef", "ntsecapi", "profileapi", "winnt"] optional = true [target.wasm32-unknown-unknown.dependencies.stdweb] version = "0.4" optional = true [badges.appveyor] repository = "alexcrichton/rand" [badges.travis-ci] repository = "rust-lang-nursery/rand" rand-0.5.5/LICENSE-APACHE010064400017500001750000000251411323634522600126230ustar0000000000000000 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.5.5/LICENSE-MIT010064400017500001750000000020571323241303400123210ustar0000000000000000Copyright (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.5.5/README.md010064400017500001750000000122201333210603300121340ustar0000000000000000# Rand [![Build Status](https://travis-ci.org/rust-lang-nursery/rand.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rand) [![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rand?svg=true)](https://ci.appveyor.com/project/alexcrichton/rand) [![Latest version](https://img.shields.io/crates/v/rand.svg)](https://crates.io/crates/rand) [![Documentation](https://docs.rs/rand/badge.svg)](https://docs.rs/rand) [![Minimum rustc version](https://img.shields.io/badge/rustc-1.22+-yellow.svg)](https://github.com/rust-lang-nursery/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; this crate is most useful when implementing RNGs. API reference: [master branch](https://rust-lang-nursery.github.io/rand/rand/index.html), [by release](https://docs.rs/rand/0.5). ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] rand = "0.5" ``` and this to your crate root: ```rust extern crate rand; use rand::prelude::*; fn main() { // basic usage with random(): let x: u8 = random(); println!("{}", x); let y = random::(); println!("{}", y); if random() { // generates a boolean println!("Heads!"); } // normal usage needs both an RNG and a function to generate the appropriate // type, range, distribution, etc. let mut rng = thread_rng(); if rng.gen() { // random bool let x: f64 = rng.gen(); // random number in range [0, 1) println!("x is: {}", x); let ch = rng.gen::(); // Sometimes you need type annotation println!("char is: {}", ch); println!("Number from 0 to 9: {}", rng.gen_range(0, 10)); } } ``` ## Functionality The Rand crate provides: - A convenient to use default RNG, `thread_rng`: an automatically seeded, crypto-grade generator stored in thread-local memory. - Pseudo-random number generators: `StdRng`, `SmallRng`, `prng` module. - Functionality for seeding PRNGs: the `FromEntropy` trait, and as sources of external randomness `EntropyRng`, `OsRng` and `JitterRng`. - Most content from [`rand_core`](https://crates.io/crates/rand_core) (re-exported): base random number generator traits and error-reporting types. - 'Distributions' producing many different types of random values: - A `Standard` distribution for integers, floats, and derived types including tuples, arrays and `Option` - Unbiased sampling from specified `Uniform` ranges. - Sampling from exponential/normal/gamma distributions. - Sampling from binomial/poisson distributions. - `gen_bool` aka Bernoulli distribution. - `seq`-uence related functionality: - Sampling a subset of elements. - Randomly shuffling a list. ## Versions Version 0.5 is the latest version and contains many breaking changes. See [the Upgrade Guide](UPDATING.md) for guidance on updating from previous versions. Version 0.4 was released in December 2017. It contains almost no breaking changes since the 0.3 series. For more details, see the [changelog](CHANGELOG.md). ### Rust version requirements The 0.5 release of Rand requires **Rustc version 1.22 or greater**. Rand 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 only the `std` feature enabled by default. The following optional features are available: - `alloc` can be used instead of `std` to provide `Vec` and `Box`. - `i128_support` enables support for generating `u128` and `i128` values. - `log` enables some logging via the `log` crate. - `nightly` enables all unstable features (`i128_support`). - `serde1` enables serialization for some types, via Serde version 1. - `stdweb` enables support for `OsRng` on `wasm-unknown-unknown` via `stdweb` combined with `cargo-web`. `no_std` mode is activated by setting `default-features = false`; this removes functionality depending on `std`: - `thread_rng()`, and `random()` are not available, as they require thread-local storage and an entropy source. - `OsRng` and `EntropyRng` are unavailable. - `JitterRng` code is still present, but a nanosecond timer must be provided via `JitterRng::new_with_timer` - Since no external entropy is available, it is not possible to create generators with fresh seeds using the `FromEntropy` trait (user must provide a seed). - Exponential, normal and gamma type distributions are unavailable since `exp` and `log` functions are not provided in `core`. - The `seq`-uence module is unavailable, as it requires `Vec`. # 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) for details. rand-0.5.5/UPDATING.md010064400017500001750000000250211331613237400124260ustar0000000000000000# Update Guide This guide gives a few more details than the [changelog], in particular giving guidance on how to use new features and migrate away from old ones. [changelog]: CHANGELOG.md ## Rand 0.5 The 0.5 release has quite significant changes over the 0.4 release; as such, it may be worth reading through the following coverage of breaking changes. This release also contains many optimisations, which are not detailed below. ### Crates We have a new crate: `rand_core`! This crate houses some important traits, `RngCore`, `BlockRngCore`, `SeedableRng` and `CryptoRng`, the error types, as well as two modules with helpers for implementations: `le` and `impls`. It is recommended that implementations of generators use the `rand_core` crate while other users use only the `rand` crate, which re-exports most parts of `rand_core`. The `rand_derive` crate has been deprecated due to very low usage and deprecation of `Rand`. ### Features Several new Cargo feature flags have been added: - `alloc`, used without `std`, allows use of `Box` and `Vec` - `serde1` adds serialization support to some PRNGs - `log` adds logging in a few places (primarily to `OsRng` and `JitterRng`) ### `Rng` and friends (core traits) `Rng` trait has been split into two traits, a "back end" `RngCore` (implemented by generators) and a "front end" `Rng` implementing all the convenient extension methods. Implementations of generators must `impl RngCore` instead. Usage of `rand_core` for implementations is encouraged; the `rand_core::{le, impls}` modules may prove useful. Users of `Rng` *who don't need to implement it* won't need to make so many changes; often users can forget about `RngCore` and only import `Rng`. Instead of `RngCore::next_u32()` / `next_u64()` users should prefer `Rng::gen()`, and instead of `RngCore::fill_bytes(dest)`, `Rng::fill(dest)` can be used. #### `Rng` / `RngCore` methods To allow error handling from fallible sources (e.g. `OsRng`), a new `RngCore::try_fill_bytes` method has been added; for example `EntropyRng` uses this mechanism to fall back to `JitterRng` if `OsRng` fails, and various handlers produce better error messages. As before, the other methods will panic on failure, but since these are usually used with algorithmic generators which are usually infallible, this is considered an appropriate compromise. A few methods from the old `Rng` have been removed or deprecated: - `next_f32` and `next_f64`; these are no longer implementable by generators; use `gen` instead - `gen_iter`; users may instead use standard iterators with closures: `::std::iter::repeat(()).map(|()| rng.gen())` - `gen_ascii_chars`; use `repeat` as above and `rng.sample(Alphanumeric)` - `gen_weighted_bool(n)`; use `gen_bool(1.0 / n)` instead `Rng` has a few new methods: - `sample(distr)` is a shortcut for `distr.sample(rng)` for any `Distribution` - `gen_bool(p)` generates a boolean with probability `p` of being true - `fill` and `try_fill`, corresponding to `fill_bytes` and `try_fill_bytes` respectively (i.e. the only difference is error handling); these can fill and integer slice / array directly, and provide better performance than `gen()` #### Constructing PRNGs ##### New randomly-initialised PRNGs A new trait has been added: `FromEntropy`. This is automatically implemented for any type supporting `SeedableRng`, and provides construction from fresh, strong entropy: ```rust use rand::{ChaChaRng, FromEntropy}; let mut rng = ChaChaRng::from_entropy(); ``` ##### Seeding PRNGs The `SeedableRng` trait has been modified to include the seed type via an associated type (`SeedableRng::Seed`) instead of a template parameter (`SeedableRng`). Additionally, all PRNGs now seed from a byte-array (`[u8; N]` for some fixed N). This allows generic handling of PRNG seeding which was not previously possible. PRNGs are no longer constructed from other PRNGs via `Rand` support / `gen()`, but through `SeedableRng::from_rng`, which allows error handling and is intentionally explicit. `SeedableRng::reseed` has been removed since it has no utility over `from_seed` and its performance advantage is questionable. Implementations of `SeedableRng` may need to change their `Seed` type to a byte-array; this restriction has been made to ensure portable handling of Endianness. Helper functions are available in `rand_core::le` to read `u32` and `u64` values from byte arrays. #### Block-based PRNGs rand_core has a new helper trait, `BlockRngCore`, and implementation, `BlockRng`. These are for use by generators which generate a block of random data at a time instead of word-sized values. Using this trait and implementation has two advantages: optimised `RngCore` methods are provided, and the PRNG can be used with `ReseedingRng` with very low overhead. #### Cryptographic RNGs A new trait has been added: `CryptoRng`. This is purely a marker trait to indicate which generators should be suitable for cryptography, e.g. `fn foo(rng: &mut R)`. *Suitability for cryptographic use cannot be guaranteed.* ### Error handling A new `Error` type has been added, designed explicitly for no-std compatibility, simplicity, and enough flexibility for our uses (carrying a `cause` when possible): ```rust pub struct Error { pub kind: ErrorKind, pub msg: &'static str, // some fields omitted } ``` The associated `ErrorKind` allows broad classification of errors into permanent, unexpected, transient and not-yet-ready kinds. The following use the new error type: - `RngCore::try_fill_bytes` - `Rng::try_fill` - `OsRng::new` - `JitterRng::new` ### External generators We have a new generator, `EntropyRng`, which wraps `OsRng` and `JitterRng` (preferring to use the former, but falling back to the latter if necessary). This allows easy construction with fallback via `SeedableRng::from_rng`, e.g. `IsaacRng::from_rng(EntropyRng::new())?`. This is equivalent to using `FromEntropy` except for error handling. It is recommended to use `EntropyRng` over `OsRng` to avoid errors on platforms with broken system generator, but it should be noted that the `JitterRng` fallback is very slow. ### PRNGs *Pseudo-Random Number Generators* (i.e. deterministic algorithmic generators) have had a few changes since 0.4, and are now housed in the `prng` module (old names remain temporarily available for compatibility; eventually these generators will likely be housed outside the `rand` crate). All PRNGs now do not implement `Copy` to prevent accidental copying of the generator's state (and thus repetitions of generated values). Explicit cloning via `Clone` is still available. All PRNGs now have a custom implementation of `Debug` which does not print any internal state; this helps avoid accidentally leaking cryptographic generator state in log files. External PRNG implementations are advised to follow this pattern (see also doc on `RngCore`). `SmallRng` has been added as a wrapper, currently around `XorShiftRng` (but likely another algorithm soon). This is for uses where small state and fast initialisation are important but cryptographic strength is not required. (Actual performance of generation varies by benchmark; dependending on usage this may or may not be the fastest algorithm, but will always be fast.) #### `ReseedingRng` The `ReseedingRng` wrapper has been signficantly altered to reduce overhead. Unfortunately the new `ReseedingRng` is not compatible with all RNGs, but only those using `BlockRngCore`. #### ISAAC PRNGs The `IsaacRng` and `Isaac64Rng` PRNGs now have an additional construction method: `new_from_u64(seed)`. 64 bits of state is insufficient for cryptography but may be of use in simulations and games. This will likely be superceeded by a method to construct any PRNG from any hashable object in the future. #### HC-128 This is a new cryptographic generator, selected as one of the "stream ciphers suitable for widespread adoption" by eSTREAM. This is now the default cryptographic generator, used by `StdRng` and `thread_rng()`. ### Helper functions/traits The `Rand` trait has been deprecated. Instead, users are encouraged to use `Standard` which is a real distribution and supports the same sampling as `Rand`. `Rng::gen()` now uses `Standard` and should work exactly as before. See the documentation of the `distributions` module on how to implement `Distribution` for `Standard` for user types `T` `weak_rng()` has been deprecated; use `SmallRng::from_entropy()` instead. ### Distributions The `Sample` and `IndependentSample` traits have been replaced by a single trait, `Distribution`. This is largely equivalent to `IndependentSample`, but with `ind_sample` replaced by just `sample`. Support for mutable distributions has been dropped; although it appears there may be a few genuine uses, these are not used widely enough to justify the existance of two independent traits or of having to provide mutable access to a distribution object. Both `Sample` and `IndependentSample` are still available, but deprecated; they will be removed in a future release. `Distribution::sample` (as well as several other functions) can now be called directly on type-erased (unsized) RNGs. `RandSample` has been removed (see `Rand` deprecation and new `Standard` distribution). The `Closed01` wrapper has been removed, but `OpenClosed01` has been added. #### Uniform distributions Two new distributions are available: - `Standard` produces uniformly-distributed samples for many different types, and acts as a replacement for `Rand` - `Alphanumeric` samples `char`s from the ranges `a-z A-Z 0-9` ##### Ranges The `Range` distribution has been heavily adapted, and renamed to `Uniform`: - `Uniform::new(low, high)` remains (half open `[low, high)`) - `Uniform::new_inclusive(low, high)` has been added, including `high` in the sample range - `Uniform::sample_single(low, high, rng)` is a faster variant for single usage sampling from `[low, high)` `Uniform` can now be implemented for user-defined types; see the `uniform` module. #### Non-uniform distributions Two distributions have been added: - Poisson, modelling the number of events expected from a constant-rate source within a fixed time interval (e.g. nuclear decay) - Binomial, modelling the outcome of a fixed number of yes-no trials The sampling methods are based on those in "Numerical Recipes in C". ##### Exponential and Normal distributions The main `Exp` and `Normal` distributions are unchanged, however the "standard" versions, `Exp1` and `StandardNormal` are no longer wrapper types, but full distributions. Instead of writing `let Exp1(x) = rng.gen();` you now write `let x = rng.sample(Exp1);`. rand-0.5.5/appveyor.yml010064400017500001750000000032401333210603300132470ustar0000000000000000environment: # At the time this was added AppVeyor was having troubles with checking # revocation of SSL certificates of sites like static.rust-lang.org and what # we think is crates.io. The libcurl HTTP client by default checks for # revocation on Windows and according to a mailing list [1] this can be # disabled. # # The `CARGO_HTTP_CHECK_REVOKE` env var here tells cargo to disable SSL # revocation checking on Windows in libcurl. Note, though, that rustup, which # we're using to download Rust here, also uses libcurl as the default backend. # Unlike Cargo, however, rustup doesn't have a mechanism to disable revocation # checking. To get rustup working we set `RUSTUP_USE_HYPER` which forces it to # use the Hyper instead of libcurl backend. Both Hyper and libcurl use # schannel on Windows but it appears that Hyper configures it slightly # differently such that revocation checking isn't turned on by default. # # [1]: https://curl.haxx.se/mail/lib-2016-03/0202.html RUSTUP_USE_HYPER: 1 CARGO_HTTP_CHECK_REVOKE: false matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc install: - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - rustc -V - cargo -V build: false test_script: - cargo test --all # cannot use --all and --features together - cargo test --all --benches - cargo test --features serde1,log,nightly - cargo test --tests --no-default-features --features=alloc,serde1 - cargo test --package rand_core --no-default-features --features=alloc,serde1 rand-0.5.5/benches/distributions.rs010064400017500001750000000124031333210603300155370ustar0000000000000000#![feature(test)] #![cfg_attr(all(feature="i128_support", feature="nightly"), allow(stable_features))] // stable since 2018-03-27 #![cfg_attr(all(feature="i128_support", feature="nightly"), feature(i128_type, i128))] extern crate test; extern crate rand; const RAND_BENCH_N: u64 = 1000; use std::mem::size_of; use test::Bencher; use rand::{Rng, FromEntropy, XorShiftRng}; use rand::distributions::*; macro_rules! distr_int { ($fnn:ident, $ty:ty, $distr:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = XorShiftRng::from_entropy(); let distr = $distr; b.iter(|| { let mut accum = 0 as $ty; for _ in 0..::RAND_BENCH_N { let x: $ty = distr.sample(&mut rng); accum = accum.wrapping_add(x); } accum }); b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N; } } } macro_rules! distr_float { ($fnn:ident, $ty:ty, $distr:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = XorShiftRng::from_entropy(); let distr = $distr; b.iter(|| { let mut accum = 0.0; for _ in 0..::RAND_BENCH_N { let x: $ty = distr.sample(&mut rng); accum += x; } accum }); b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N; } } } macro_rules! distr { ($fnn:ident, $ty:ty, $distr:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = XorShiftRng::from_entropy(); let distr = $distr; b.iter(|| { let mut accum = 0u32; for _ in 0..::RAND_BENCH_N { let x: $ty = distr.sample(&mut rng); accum = accum.wrapping_add(x as u32); } accum }); b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N; } } } // uniform distr_int!(distr_uniform_i8, i8, Uniform::new(20i8, 100)); distr_int!(distr_uniform_i16, i16, Uniform::new(-500i16, 2000)); distr_int!(distr_uniform_i32, i32, Uniform::new(-200_000_000i32, 800_000_000)); distr_int!(distr_uniform_i64, i64, Uniform::new(3i64, 123_456_789_123)); #[cfg(feature = "i128_support")] distr_int!(distr_uniform_i128, i128, Uniform::new(-123_456_789_123i128, 123_456_789_123_456_789)); distr_float!(distr_uniform_f32, f32, Uniform::new(2.26f32, 2.319)); distr_float!(distr_uniform_f64, f64, Uniform::new(2.26f64, 2.319)); // standard distr_int!(distr_standard_i8, i8, Standard); distr_int!(distr_standard_i16, i16, Standard); distr_int!(distr_standard_i32, i32, Standard); distr_int!(distr_standard_i64, i64, Standard); #[cfg(feature = "i128_support")] distr_int!(distr_standard_i128, i128, Standard); distr!(distr_standard_bool, bool, Standard); distr!(distr_standard_alphanumeric, char, Alphanumeric); distr!(distr_standard_codepoint, char, Standard); distr_float!(distr_standard_f32, f32, Standard); distr_float!(distr_standard_f64, f64, Standard); distr_float!(distr_open01_f32, f32, Open01); distr_float!(distr_open01_f64, f64, Open01); distr_float!(distr_openclosed01_f32, f32, OpenClosed01); distr_float!(distr_openclosed01_f64, f64, OpenClosed01); // distributions distr_float!(distr_exp, f64, Exp::new(1.23 * 4.56)); distr_float!(distr_normal, f64, Normal::new(-1.23, 4.56)); distr_float!(distr_log_normal, f64, LogNormal::new(-1.23, 4.56)); distr_float!(distr_gamma_large_shape, f64, Gamma::new(10., 1.0)); distr_float!(distr_gamma_small_shape, f64, Gamma::new(0.1, 1.0)); distr_float!(distr_cauchy, f64, Cauchy::new(4.2, 6.9)); distr_int!(distr_binomial, u64, Binomial::new(20, 0.7)); distr_int!(distr_poisson, u64, Poisson::new(4.0)); distr!(distr_bernoulli, bool, Bernoulli::new(0.18)); // construct and sample from a range macro_rules! gen_range_int { ($fnn:ident, $ty:ident, $low:expr, $high:expr) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = XorShiftRng::from_entropy(); b.iter(|| { let mut high = $high; let mut accum: $ty = 0; for _ in 0..::RAND_BENCH_N { accum = accum.wrapping_add(rng.gen_range($low, high)); // force recalculation of range each time high = high.wrapping_add(1) & std::$ty::MAX; } accum }); b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N; } } } gen_range_int!(gen_range_i8, i8, -20i8, 100); gen_range_int!(gen_range_i16, i16, -500i16, 2000); gen_range_int!(gen_range_i32, i32, -200_000_000i32, 800_000_000); gen_range_int!(gen_range_i64, i64, 3i64, 123_456_789_123); #[cfg(feature = "i128_support")] gen_range_int!(gen_range_i128, i128, -12345678901234i128, 123_456_789_123_456_789); #[bench] fn dist_iter(b: &mut Bencher) { let mut rng = XorShiftRng::from_entropy(); let distr = Normal::new(-2.71828, 3.14159); let mut iter = distr.sample_iter(&mut rng); b.iter(|| { let mut accum = 0.0; for _ in 0..::RAND_BENCH_N { accum += iter.next().unwrap(); } accum }); b.bytes = size_of::() as u64 * ::RAND_BENCH_N; } rand-0.5.5/benches/generators.rs010064400017500001750000000124711333210603300150130ustar0000000000000000#![feature(test)] extern crate test; extern crate rand; 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::prng::{XorShiftRng, Hc128Rng, IsaacRng, Isaac64Rng, ChaChaRng}; use rand::prng::hc128::Hc128Core; use rand::rngs::adapter::ReseedingRng; use rand::rngs::{OsRng, JitterRng, EntropyRng}; 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_xorshift, XorShiftRng::from_entropy()); gen_bytes!(gen_bytes_chacha20, ChaChaRng::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()); gen_bytes!(gen_bytes_small, SmallRng::from_entropy()); gen_bytes!(gen_bytes_os, OsRng::new().unwrap()); 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_xorshift, u32, XorShiftRng::from_entropy()); gen_uint!(gen_u32_chacha20, u32, ChaChaRng::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()); gen_uint!(gen_u32_small, u32, SmallRng::from_entropy()); gen_uint!(gen_u32_os, u32, OsRng::new().unwrap()); gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy()); gen_uint!(gen_u64_chacha20, u64, ChaChaRng::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()); gen_uint!(gen_u64_small, u64, SmallRng::from_entropy()); gen_uint!(gen_u64_os, u64, OsRng::new().unwrap()); // Do not test JitterRng like the others by running it RAND_BENCH_N times per, // measurement, because it is way too slow. Only run it once. #[bench] fn gen_u64_jitter(b: &mut Bencher) { let mut rng = JitterRng::new().unwrap(); b.iter(|| { rng.gen::() }); b.bytes = size_of::() as u64; } 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_hc128, Hc128Rng); init_gen!(init_isaac, IsaacRng); init_gen!(init_isaac64, Isaac64Rng); init_gen!(init_chacha, ChaChaRng); #[bench] fn init_jitter(b: &mut Bencher) { b.iter(|| { JitterRng::new().unwrap() }); } const RESEEDING_THRESHOLD: u64 = 1024*1024*1024; // something high enough to get // deterministic measurements #[bench] fn reseeding_hc128_bytes(b: &mut Bencher) { let mut rng = ReseedingRng::new(Hc128Core::from_entropy(), RESEEDING_THRESHOLD, EntropyRng::new()); 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; } macro_rules! reseeding_uint { ($fnn:ident, $ty:ty) => { #[bench] fn $fnn(b: &mut Bencher) { let mut rng = ReseedingRng::new(Hc128Core::from_entropy(), RESEEDING_THRESHOLD, EntropyRng::new()); 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; } } } reseeding_uint!(reseeding_hc128_u32, u32); reseeding_uint!(reseeding_hc128_u64, u64); 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.5.5/benches/misc.rs010064400017500001750000000113511333210603300135710ustar0000000000000000#![feature(test)] extern crate test; extern crate rand; const RAND_BENCH_N: u64 = 1000; use test::Bencher; use rand::prelude::*; use rand::seq::*; #[bench] fn misc_gen_bool_const(b: &mut Bencher) { let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; for _ in 0..::RAND_BENCH_N { accum ^= rng.gen_bool(0.18); } accum }) } #[bench] fn misc_gen_bool_var(b: &mut Bencher) { let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; let mut p = 0.18; for _ in 0..::RAND_BENCH_N { accum ^= rng.gen_bool(p); p += 0.0001; } accum }) } #[bench] fn misc_bernoulli_const(b: &mut Bencher) { let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap(); let d = rand::distributions::Bernoulli::new(0.18); b.iter(|| { // Can be evaluated at compile time. let mut accum = true; for _ in 0..::RAND_BENCH_N { accum ^= rng.sample(d); } accum }) } #[bench] fn misc_bernoulli_var(b: &mut Bencher) { let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let mut accum = true; let mut p = 0.18; for _ in 0..::RAND_BENCH_N { let d = rand::distributions::Bernoulli::new(p); accum ^= rng.sample(d); p += 0.0001; } accum }) } macro_rules! sample_binomial { ($name:ident, $n:expr, $p:expr) => { #[bench] fn $name(b: &mut Bencher) { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); let (n, p) = ($n, $p); b.iter(|| { let d = rand::distributions::Binomial::new(n, p); rng.sample(d) }) } } } sample_binomial!(misc_binomial_1, 1, 0.9); sample_binomial!(misc_binomial_10, 10, 0.9); sample_binomial!(misc_binomial_100, 100, 0.99); sample_binomial!(misc_binomial_1000, 1000, 0.01); sample_binomial!(misc_binomial_1e12, 1000_000_000_000, 0.2); #[bench] fn misc_shuffle_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &mut [usize] = &mut [1; 100]; b.iter(|| { rng.shuffle(x); x[0] }) } #[bench] fn misc_sample_iter_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e) }) } #[bench] fn misc_sample_slice_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { sample_slice(&mut rng, x, 10) }) } #[bench] fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { sample_slice_ref(&mut rng, x, 10) }) } macro_rules! sample_indices { ($name:ident, $amount:expr, $length:expr) => { #[bench] fn $name(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); b.iter(|| { sample_indices(&mut rng, $length, $amount) }) } } } sample_indices!(misc_sample_indices_10_of_1k, 10, 1000); sample_indices!(misc_sample_indices_50_of_1k, 50, 1000); sample_indices!(misc_sample_indices_100_of_1k, 100, 1000); #[bench] fn gen_1k_iter_repeat(b: &mut Bencher) { use std::iter; let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let v: Vec = iter::repeat(()).map(|()| rng.gen()).take(128).collect(); v }); b.bytes = 1024; } #[bench] #[allow(deprecated)] fn gen_1k_gen_iter(b: &mut Bencher) { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { let v: Vec = rng.gen_iter().take(128).collect(); v }); b.bytes = 1024; } #[bench] fn gen_1k_sample_iter(b: &mut Bencher) { use rand::distributions::{Distribution, Standard}; let mut rng = SmallRng::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 = SmallRng::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 = SmallRng::from_rng(&mut thread_rng()).unwrap(); let mut buf = [0u64; 128]; b.iter(|| { rng.fill(&mut buf[..]); buf }); b.bytes = 1024; } rand-0.5.5/examples/monte-carlo.rs010064400017500001750000000031731331042026600152730ustar0000000000000000// Copyright 2013-2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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")] extern crate rand; 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.5.5/examples/monty-hall.rs010064400017500001750000000077371333210603300151460ustar0000000000000000// Copyright 2013-2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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")] extern crate rand; use rand::Rng; use rand::distributions::{Distribution, Uniform}; 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 { let choices = free_doors(&[car, choice]); rand::seq::sample_slice(rng, &choices, 1)[0] } // 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.5.5/src/distributions/bernoulli.rs010064400017500001750000000072431333210603300167200ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 Rng; use 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); /// 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, } impl Bernoulli { /// Construct a new `Bernoulli` with the given probability of success `p`. /// /// # Panics /// /// If `p < 0` or `p > 1`. /// /// # 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) -> Bernoulli { assert!((p >= 0.0) & (p <= 1.0), "Bernoulli::new not called with 0 <= p <= 0"); // Technically, this should be 2^64 or `u64::MAX + 1` because we compare // using `<` when sampling. However, `u64::MAX` rounds to an `f64` // larger than `u64::MAX` anyway. const MAX_P_INT: f64 = ::core::u64::MAX as f64; let p_int = if p < 1.0 { (p * MAX_P_INT) as u64 } else { // Avoid overflow: `MAX_P_INT` cannot be represented as u64. ::core::u64::MAX }; 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 == ::core::u64::MAX { return true; } let r: u64 = rng.gen(); r < self.p_int } } #[cfg(test)] mod test { use Rng; use distributions::Distribution; use super::Bernoulli; #[test] fn test_trivial() { let mut r = ::test::rng(1); let always_false = Bernoulli::new(0.0); let always_true = Bernoulli::new(1.0); 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] fn test_average() { const P: f64 = 0.3; let d = Bernoulli::new(P); const N: u32 = 10_000_000; let mut sum: u32 = 0; let mut rng = ::test::rng(2); for _ in 0..N { if d.sample(&mut rng) { sum += 1; } } let avg = (sum as f64) / (N as f64); assert!((avg - P).abs() < 1e-3); } } rand-0.5.5/src/distributions/binomial.rs010064400017500001750000000135061333210603300165160ustar0000000000000000// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use Rng; use distributions::{Distribution, Bernoulli, Cauchy}; use distributions::log_gamma::log_gamma; /// 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`. /// /// # Example /// /// ``` /// use rand::distributions::{Binomial, Distribution}; /// /// let bin = Binomial::new(20, 0.3); /// let v = bin.sample(&mut rand::thread_rng()); /// println!("{} is from a binomial distribution", v); /// ``` #[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 } } } 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; } // For low n, it is faster to sample directly. For both methods, // performance is independent of p. On Intel Haswell CPU this method // appears to be faster for approx n < 300. if self.n < 300 { let mut result = 0; let d = Bernoulli::new(self.p); for _ in 0 .. self.n { result += rng.sample(d) as u32; } return result as u64; } // 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 }; // prepare some cached values let float_n = self.n as f64; let ln_fact_n = log_gamma(float_n + 1.0); let pc = 1.0 - p; let log_p = p.ln(); let log_pc = pc.ln(); let expected = self.n as f64 * p; let sq = (expected * (2.0 * pc)).sqrt(); let mut lresult; // 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 comp_dev: f64; loop { // draw from the Cauchy distribution comp_dev = rng.sample(cauchy); // shift the peak of the comparison ditribution lresult = expected + sq * comp_dev; // repeat the drawing until we are in the range of possible values if lresult >= 0.0 && lresult < float_n + 1.0 { break; } } // the result should be discrete lresult = lresult.floor(); let log_binomial_dist = ln_fact_n - log_gamma(lresult+1.0) - log_gamma(float_n - lresult + 1.0) + lresult*log_p + (float_n - lresult)*log_pc; // this is the binomial probability divided by the comparison probability // we will generate a uniform random value and if it is larger than this, // we interpret it as a value falling out of the distribution and repeat let comparison_coeff = (log_binomial_dist.exp() * sq) * (1.2 * (1.0 + comp_dev*comp_dev)); if comparison_coeff >= rng.gen() { break; } } // invert the result for p < 0.5 if p != self.p { self.n - lresult as u64 } else { lresult as u64 } } } #[cfg(test)] mod test { use Rng; use 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); let variance = results.iter().map(|x| (x - mean) * (x - mean)).sum::() / results.len() as f64; assert!((variance - expected_variance).abs() < expected_variance / 10.0); } #[test] fn test_binomial() { let mut rng = ::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 = ::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.5.5/src/distributions/cauchy.rs010064400017500001750000000064641332655332100162160ustar0000000000000000// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use Rng; use 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))` /// /// # Example /// /// ``` /// use rand::distributions::{Cauchy, Distribution}; /// /// let cau = Cauchy::new(2.0, 5.0); /// let v = cau.sample(&mut rand::thread_rng()); /// println!("{} is from a Cauchy(2, 5) distribution", v); /// ``` #[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 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] fn test_cauchy_median() { let cauchy = Cauchy::new(10.0, 5.0); let mut rng = ::test::rng(123); let mut numbers: [f64; 1000] = [0.0; 1000]; for i in 0..1000 { numbers[i] = cauchy.sample(&mut rng); } let median = median(&mut numbers); println!("Cauchy median: {}", median); assert!((median - 10.0).abs() < 0.5); // not 100% certain, but probable enough } #[test] fn test_cauchy_mean() { let cauchy = Cauchy::new(10.0, 5.0); let mut rng = ::test::rng(123); let mut sum = 0.0; for _ in 0..1000 { sum += cauchy.sample(&mut rng); } let mean = sum / 1000.0; println!("Cauchy mean: {}", mean); // for a Cauchy distribution the mean should not converge assert!((mean - 10.0).abs() > 0.5); // 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.5.5/src/distributions/exponential.rs010064400017500001750000000067141333210603300172550ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use {Rng}; use distributions::{ziggurat, ziggurat_tables, Distribution}; /// 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 /// /// # Example /// ``` /// use rand::prelude::*; /// use rand::distributions::Exp1; /// /// let val: f64 = SmallRng::from_entropy().sample(Exp1); /// println!("{}", val); /// ``` #[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`. /// /// # Example /// /// ``` /// use rand::distributions::{Exp, Distribution}; /// /// let exp = Exp::new(2.0); /// let v = exp.sample(&mut rand::thread_rng()); /// println!("{} is from a Exp(2) distribution", v); /// ``` #[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 distributions::Distribution; use super::Exp; #[test] fn test_exp() { let exp = Exp::new(10.0); let mut rng = ::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.5.5/src/distributions/float.rs010064400017500001750000000171101333210603300160240ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 Rng; use distributions::{Distribution, Standard}; /// 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`]: struct.Standard.html /// [`Open01`]: struct.Open01.html /// [`Uniform`]: uniform/struct.Uniform.html #[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`]: struct.Standard.html /// [`OpenClosed01`]: struct.OpenClosed01.html /// [`Uniform`]: uniform/struct.Uniform.html #[derive(Clone, Copy, Debug)] pub struct Open01; pub(crate) 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:ty, $uty: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 = (($exponent_bias + exponent) as $uty) << $fraction_bits; unsafe { mem::transmute(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::<$ty>() * 8; let precision = $fraction_bits + 1; let scale = 1.0 / ((1 as $uty << precision) as $ty); let value: $uty = rng.gen(); scale * (value >> (float_size - precision)) as $ty } } 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::<$ty>() * 8; let precision = $fraction_bits + 1; let scale = 1.0 / ((1 as $uty << precision) as $ty); let value: $uty = rng.gen(); let value = value >> (float_size - precision); // Add 1 to shift up; will not overflow because of right-shift: scale * (value + 1) as $ty } } 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. const EPSILON: $ty = 1.0 / (1u64 << $fraction_bits) as $ty; let float_size = mem::size_of::<$ty>() * 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, 23, 127 } float_impls! { f64, u64, 52, 1023 } #[cfg(test)] mod tests { use Rng; use distributions::{Open01, OpenClosed01}; use rngs::mock::StepRng; const EPSILON32: f32 = ::core::f32::EPSILON; const EPSILON64: f64 = ::core::f64::EPSILON; #[test] fn standard_fp_edge_cases() { let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.gen::(), 0.0); assert_eq!(zeros.gen::(), 0.0); let mut one32 = StepRng::new(1 << 8, 0); assert_eq!(one32.gen::(), EPSILON32 / 2.0); let mut one64 = StepRng::new(1 << 11, 0); assert_eq!(one64.gen::(), EPSILON64 / 2.0); let mut max = StepRng::new(!0, 0); assert_eq!(max.gen::(), 1.0 - EPSILON32 / 2.0); assert_eq!(max.gen::(), 1.0 - EPSILON64 / 2.0); } #[test] fn openclosed01_edge_cases() { let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.sample::(OpenClosed01), 0.0 + EPSILON32 / 2.0); assert_eq!(zeros.sample::(OpenClosed01), 0.0 + EPSILON64 / 2.0); let mut one32 = StepRng::new(1 << 8, 0); assert_eq!(one32.sample::(OpenClosed01), EPSILON32); let mut one64 = StepRng::new(1 << 11, 0); assert_eq!(one64.sample::(OpenClosed01), EPSILON64); let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::(OpenClosed01), 1.0); assert_eq!(max.sample::(OpenClosed01), 1.0); } #[test] fn open01_edge_cases() { let mut zeros = StepRng::new(0, 0); assert_eq!(zeros.sample::(Open01), 0.0 + EPSILON32 / 2.0); assert_eq!(zeros.sample::(Open01), 0.0 + EPSILON64 / 2.0); let mut one32 = StepRng::new(1 << 9, 0); assert_eq!(one32.sample::(Open01), EPSILON32 / 2.0 * 3.0); let mut one64 = StepRng::new(1 << 12, 0); assert_eq!(one64.sample::(Open01), EPSILON64 / 2.0 * 3.0); let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::(Open01), 1.0 - EPSILON32 / 2.0); assert_eq!(max.sample::(Open01), 1.0 - EPSILON64 / 2.0); } } rand-0.5.5/src/distributions/gamma.rs010064400017500001750000000237401333210603300160070ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use self::GammaRepr::*; use self::ChiSquaredRepr::*; use Rng; use distributions::normal::StandardNormal; use 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`. /// /// # Example /// /// ``` /// use rand::distributions::{Distribution, Gamma}; /// /// let gamma = Gamma::new(2.0, 5.0); /// let v = gamma.sample(&mut rand::thread_rng()); /// println!("{} is from a Gamma(2, 5) distribution", v); /// ``` /// /// [^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) #[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)`. /// /// # Example /// /// ``` /// use rand::distributions::{ChiSquared, Distribution}; /// /// let chi = ChiSquared::new(11.0); /// let v = chi.sample(&mut rand::thread_rng()); /// println!("{} is from a χ²(11) distribution", v) /// ``` #[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)`. /// /// # Example /// /// ``` /// use rand::distributions::{FisherF, Distribution}; /// /// let f = FisherF::new(2.0, 32.0); /// let v = f.sample(&mut rand::thread_rng()); /// println!("{} is from an F(2, 32) distribution", v) /// ``` #[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. /// /// # Example /// /// ``` /// use rand::distributions::{StudentT, Distribution}; /// /// let t = StudentT::new(11.0); /// let v = t.sample(&mut rand::thread_rng()); /// println!("{} is from a t(11) distribution", v) /// ``` #[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() } } #[cfg(test)] mod test { use distributions::Distribution; use super::{ChiSquared, StudentT, FisherF}; #[test] fn test_chi_squared_one() { let chi = ChiSquared::new(1.0); let mut rng = ::test::rng(201); for _ in 0..1000 { chi.sample(&mut rng); } } #[test] fn test_chi_squared_small() { let chi = ChiSquared::new(0.5); let mut rng = ::test::rng(202); for _ in 0..1000 { chi.sample(&mut rng); } } #[test] fn test_chi_squared_large() { let chi = ChiSquared::new(30.0); let mut rng = ::test::rng(203); for _ in 0..1000 { 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 = ::test::rng(204); for _ in 0..1000 { f.sample(&mut rng); } } #[test] fn test_t() { let t = StudentT::new(11.0); let mut rng = ::test::rng(205); for _ in 0..1000 { t.sample(&mut rng); } } } rand-0.5.5/src/distributions/integer.rs010064400017500001750000000061251333210603300163600ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 {Rng}; use distributions::{Distribution, Standard}; 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(feature = "i128_support")] impl Distribution for Standard { #[inline] fn sample(&self, rng: &mut R) -> u128 { // Use LE; we explicitly generate one value before the next. let x = rng.next_u64() as u128; let y = rng.next_u64() as u128; (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(feature = "i128_support")] impl_int_from_uint! { i128, u128 } impl_int_from_uint! { isize, usize } #[cfg(test)] mod tests { use Rng; use distributions::{Standard}; #[test] fn test_integers() { let mut rng = ::test::rng(806); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); #[cfg(feature = "i128_support")] rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); #[cfg(feature = "i128_support")] rng.sample::(Standard); } } rand-0.5.5/src/distributions/log_gamma.rs010064400017500001750000000034771333210603300166550ustar0000000000000000// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. /// 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. 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() } rand-0.5.5/src/distributions/mod.rs010064400017500001750000000707261333210603300155120ustar0000000000000000// Copyright 2013-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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, including [`gen`], [`gen_range`] and //! of course [`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. //! //! //! # Distribution to sample from a `Uniform` range //! //! 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`]. //! //! //! # Other distributions //! //! 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] for //! more details. //! //! [`Alphanumeric`] is a simple distribution to sample random letters and //! numbers of the `char` type; in contrast [`Standard`] may sample any valid //! `char`. //! //! //! # Non-uniform probability distributions //! //! Rand currently provides the following probability distributions: //! //! - Related to real-valued quantities that grow linearly //! (e.g. errors, offsets): //! - [`Normal`] distribution, and [`StandardNormal`] as a primitive //! - [`Cauchy`] distribution //! - Related to Bernoulli trials (yes/no events, with a given probability): //! - [`Binomial`] distribution //! - [`Bernoulli`] distribution, similar to [`Rng::gen_bool`]. //! - Related to positive real-valued quantities that grow exponentially //! (e.g. prices, incomes, populations): //! - [`LogNormal`] distribution //! - Related to the occurrence of independent events at a given rate: //! - [`Poisson`] distribution //! - [`Exp`]onential distribution, and [`Exp1`] as a primitive //! - Gamma and derived distributions: //! - [`Gamma`] distribution //! - [`ChiSquared`] distribution //! - [`StudentT`] distribution //! - [`FisherF`] distribution //! //! //! # Examples //! //! Sampling from a distribution: //! //! ``` //! use rand::{thread_rng, Rng}; //! use rand::distributions::Exp; //! //! let exp = Exp::new(2.0); //! let v = thread_rng().sample(exp); //! println!("{} is from an Exp(2) distribution", v); //! ``` //! //! Implementing the [`Standard`] distribution for a user type: //! //! ``` //! # #![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() } //! } //! } //! ``` //! //! //! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution //! [`Distribution`]: trait.Distribution.html //! [`gen_range`]: ../trait.Rng.html#method.gen_range //! [`gen`]: ../trait.Rng.html#method.gen //! [`sample`]: ../trait.Rng.html#method.sample //! [`new_inclusive`]: struct.Uniform.html#method.new_inclusive //! [`random()`]: ../fn.random.html //! [`Rng::gen_bool`]: ../trait.Rng.html#method.gen_bool //! [`Rng::gen_range`]: ../trait.Rng.html#method.gen_range //! [`Rng::gen()`]: ../trait.Rng.html#method.gen //! [`Rng`]: ../trait.Rng.html //! [`uniform` module]: uniform/index.html //! [Floating point implementation]: struct.Standard.html#floating-point-implementation // distributions //! [`Alphanumeric`]: struct.Alphanumeric.html //! [`Bernoulli`]: struct.Bernoulli.html //! [`Binomial`]: struct.Binomial.html //! [`Cauchy`]: struct.Cauchy.html //! [`ChiSquared`]: struct.ChiSquared.html //! [`Exp`]: struct.Exp.html //! [`Exp1`]: struct.Exp1.html //! [`FisherF`]: struct.FisherF.html //! [`Gamma`]: struct.Gamma.html //! [`LogNormal`]: struct.LogNormal.html //! [`Normal`]: struct.Normal.html //! [`Open01`]: struct.Open01.html //! [`OpenClosed01`]: struct.OpenClosed01.html //! [`Pareto`]: struct.Pareto.html //! [`Poisson`]: struct.Poisson.html //! [`Standard`]: struct.Standard.html //! [`StandardNormal`]: struct.StandardNormal.html //! [`StudentT`]: struct.StudentT.html //! [`Uniform`]: struct.Uniform.html //! [`Uniform::new`]: struct.Uniform.html#method.new //! [`Uniform::new_inclusive`]: struct.Uniform.html#method.new_inclusive use Rng; #[doc(inline)] pub use self::other::Alphanumeric; #[doc(inline)] pub use self::uniform::Uniform; #[doc(inline)] pub use self::float::{OpenClosed01, Open01}; #[deprecated(since="0.5.0", note="use Uniform instead")] pub use self::uniform::Uniform as Range; #[cfg(feature="std")] #[doc(inline)] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; #[cfg(feature="std")] #[doc(inline)] pub use self::normal::{Normal, LogNormal, StandardNormal}; #[cfg(feature="std")] #[doc(inline)] pub use self::exponential::{Exp, Exp1}; #[cfg(feature="std")] #[doc(inline)] pub use self::pareto::Pareto; #[cfg(feature = "std")] #[doc(inline)] pub use self::poisson::Poisson; #[cfg(feature = "std")] #[doc(inline)] pub use self::binomial::Binomial; #[doc(inline)] pub use self::bernoulli::Bernoulli; #[cfg(feature = "std")] #[doc(inline)] pub use self::cauchy::Cauchy; pub mod uniform; #[cfg(feature="std")] #[doc(hidden)] pub mod gamma; #[cfg(feature="std")] #[doc(hidden)] pub mod normal; #[cfg(feature="std")] #[doc(hidden)] pub mod exponential; #[cfg(feature="std")] #[doc(hidden)] pub mod pareto; #[cfg(feature = "std")] #[doc(hidden)] pub mod poisson; #[cfg(feature = "std")] #[doc(hidden)] pub mod binomial; #[doc(hidden)] pub mod bernoulli; #[cfg(feature = "std")] #[doc(hidden)] pub mod cauchy; mod float; mod integer; #[cfg(feature="std")] mod log_gamma; mod other; #[cfg(feature="std")] mod ziggurat_tables; #[cfg(feature="std")] use distributions::float::IntoFloat; /// Types that can be used to create a random instance of `Support`. #[deprecated(since="0.5.0", note="use Distribution instead")] pub trait Sample { /// Generate a random value of `Support`, using `rng` as the /// source of randomness. fn sample(&mut self, rng: &mut R) -> Support; } /// `Sample`s that do not require keeping track of state. /// /// Since no state is recorded, each sample is (statistically) /// independent of all others, assuming the `Rng` used has this /// property. #[allow(deprecated)] #[deprecated(since="0.5.0", note="use Distribution instead")] pub trait IndependentSample: Sample { /// Generate a random value. fn ind_sample(&self, &mut R) -> Support; } /// DEPRECATED: Use `distributions::uniform` instead. #[deprecated(since="0.5.0", note="use uniform instead")] pub mod range { pub use distributions::uniform::Uniform as Range; pub use distributions::uniform::SampleUniform as SampleRange; } #[allow(deprecated)] mod impls { use Rng; use distributions::{Distribution, Sample, IndependentSample, WeightedChoice}; #[cfg(feature="std")] use distributions::exponential::Exp; #[cfg(feature="std")] use distributions::gamma::{Gamma, ChiSquared, FisherF, StudentT}; #[cfg(feature="std")] use distributions::normal::{Normal, LogNormal}; use distributions::range::{Range, SampleRange}; impl<'a, T: Clone> Sample for WeightedChoice<'a, T> { fn sample(&mut self, rng: &mut R) -> T { Distribution::sample(self, rng) } } impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { fn ind_sample(&self, rng: &mut R) -> T { Distribution::sample(self, rng) } } impl Sample for Range { fn sample(&mut self, rng: &mut R) -> T { Distribution::sample(self, rng) } } impl IndependentSample for Range { fn ind_sample(&self, rng: &mut R) -> T { Distribution::sample(self, rng) } } #[cfg(feature="std")] macro_rules! impl_f64 { ($($name: ident), *) => { $( impl Sample for $name { fn sample(&mut self, rng: &mut R) -> f64 { Distribution::sample(self, rng) } } impl IndependentSample for $name { fn ind_sample(&self, rng: &mut R) -> f64 { Distribution::sample(self, rng) } } )* } } #[cfg(feature="std")] impl_f64!(Exp, Gamma, ChiSquared, FisherF, StudentT, Normal, LogNormal); } /// 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. /// /// [`Rng`]: ../trait.Rng.html /// [`sample_iter`]: trait.Distribution.html#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. /// /// # Example /// /// ``` /// use rand::thread_rng; /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard}; /// /// let mut rng = thread_rng(); /// /// // Vec of 16 x f32: /// let v: Vec = Standard.sample_iter(&mut rng).take(16).collect(); /// /// // String: /// let s: String = Alphanumeric.sample_iter(&mut rng).take(7).collect(); /// /// // Dice-rolling: /// let die_range = Uniform::new_inclusive(1, 6); /// let mut roll_die = die_range.sample_iter(&mut rng); /// while roll_die.next().unwrap() != 6 { /// println!("Not a 6; rolling again!"); /// } /// ``` fn sample_iter<'a, R>(&'a self, rng: &'a mut R) -> DistIter<'a, Self, R, T> where Self: Sized, R: Rng { DistIter { distr: self, rng: 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. /// /// [`Distribution`]: trait.Distribution.html /// [`sample_iter`]: trait.Distribution.html#method.sample_iter #[derive(Debug)] pub struct DistIter<'a, D: 'a, R: 'a, T> { distr: &'a D, rng: &'a mut R, phantom: ::core::marker::PhantomData, } impl<'a, D, R, T> Iterator for DistIter<'a, D, R, T> where D: Distribution, R: Rng + 'a { type Item = T; #[inline(always)] fn next(&mut self) -> Option { Some(self.distr.sample(self.rng)) } fn size_hint(&self) -> (usize, Option) { (usize::max_value(), None) } } /// 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. /// /// ## Built-in 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 following aggregate types also implement the distribution `Standard` as /// long as their component types implement it: /// /// * Tuples and arrays: Each element of the tuple or array is generated /// independently, using the `Standard` distribution recursively. /// * `Option` where `Standard` is implemented for `T`: Returns `None` with /// probability 0.5; otherwise generates a random `x: T` and returns `Some(x)`. /// /// # Example /// ``` /// use rand::prelude::*; /// use rand::distributions::Standard; /// /// let val: f32 = SmallRng::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). /// /// [`Open01`]: struct.Open01.html /// [`OpenClosed01`]: struct.OpenClosed01.html /// [`Uniform`]: uniform/struct.Uniform.html #[derive(Clone, Copy, Debug)] pub struct Standard; #[allow(deprecated)] impl ::Rand for T where Standard: Distribution { fn rand(rng: &mut R) -> Self { Standard.sample(rng) } } /// A value with a particular weight for use with `WeightedChoice`. #[derive(Copy, Clone, Debug)] pub struct Weighted { /// The numerical weight of this item pub weight: u32, /// The actual item which is being weighted pub item: T, } /// A distribution that selects from a finite collection of weighted items. /// /// Each item has an associated weight that influences how likely it /// is to be chosen: higher weight is more likely. /// /// The `Clone` restriction is a limitation of the `Distribution` trait. /// Note that `&T` is (cheaply) `Clone` for all `T`, as is `u32`, so one can /// store references or indices into another vector. /// /// # Example /// /// ``` /// use rand::distributions::{Weighted, WeightedChoice, Distribution}; /// /// let mut items = vec!(Weighted { weight: 2, item: 'a' }, /// Weighted { weight: 4, item: 'b' }, /// Weighted { weight: 1, item: 'c' }); /// let wc = WeightedChoice::new(&mut items); /// let mut rng = rand::thread_rng(); /// for _ in 0..16 { /// // on average prints 'a' 4 times, 'b' 8 and 'c' twice. /// println!("{}", wc.sample(&mut rng)); /// } /// ``` #[derive(Debug)] pub struct WeightedChoice<'a, T:'a> { items: &'a mut [Weighted], weight_range: Uniform, } impl<'a, T: Clone> WeightedChoice<'a, T> { /// Create a new `WeightedChoice`. /// /// Panics if: /// /// - `items` is empty /// - the total weight is 0 /// - the total weight is larger than a `u32` can contain. pub fn new(items: &'a mut [Weighted]) -> WeightedChoice<'a, T> { // strictly speaking, this is subsumed by the total weight == 0 case assert!(!items.is_empty(), "WeightedChoice::new called with no items"); let mut running_total: u32 = 0; // we convert the list from individual weights to cumulative // weights so we can binary search. This *could* drop elements // with weight == 0 as an optimisation. for item in items.iter_mut() { running_total = match running_total.checked_add(item.weight) { Some(n) => n, None => panic!("WeightedChoice::new called with a total weight \ larger than a u32 can contain") }; item.weight = running_total; } assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0"); WeightedChoice { items, // we're likely to be generating numbers in this range // relatively often, so might as well cache it weight_range: Uniform::new(0, running_total) } } } impl<'a, T: Clone> Distribution for WeightedChoice<'a, T> { fn sample(&self, rng: &mut R) -> T { // we want to find the first element that has cumulative // weight > sample_weight, which we do by binary since the // cumulative weights of self.items are sorted. // choose a weight in [0, total_weight) let sample_weight = self.weight_range.sample(rng); // short circuit when it's the first item if sample_weight < self.items[0].weight { return self.items[0].item.clone(); } let mut idx = 0; let mut modifier = self.items.len(); // now we know that every possibility has an element to the // left, so we can just search for the last element that has // cumulative weight <= sample_weight, then the next one will // be "it". (Note that this greatest element will never be the // last element of the vector, since sample_weight is chosen // in [0, total_weight) and the cumulative weight of the last // one is exactly the total weight.) while modifier > 1 { let i = idx + modifier / 2; if self.items[i].weight <= sample_weight { // we're small, so look to the right, but allow this // exact element still. idx = i; // we need the `/ 2` to round up otherwise we'll drop // the trailing elements when `modifier` is odd. modifier += 1; } else { // otherwise we're too big, so go left. (i.e. do // nothing) } modifier /= 2; } self.items[idx + 1].item.clone() } } /// 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)] 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 { 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; } } } #[cfg(test)] mod tests { use Rng; use rngs::mock::StepRng; use super::{WeightedChoice, Weighted, Distribution}; #[test] fn test_weighted_choice() { // this makes assumptions about the internal implementation of // WeightedChoice. It may fail when the implementation in // `distributions::uniform::UniformInt` changes. macro_rules! t { ($items:expr, $expected:expr) => {{ let mut items = $items; let mut total_weight = 0; for item in &items { total_weight += item.weight; } let wc = WeightedChoice::new(&mut items); let expected = $expected; // Use extremely large steps between the random numbers, because // we test with small ranges and `UniformInt` is designed to prefer // the most significant bits. let mut rng = StepRng::new(0, !0 / (total_weight as u64)); for &val in expected.iter() { assert_eq!(wc.sample(&mut rng), val) } }} } t!([Weighted { weight: 1, item: 10}], [10]); // skip some t!([Weighted { weight: 0, item: 20}, Weighted { weight: 2, item: 21}, Weighted { weight: 0, item: 22}, Weighted { weight: 1, item: 23}], [21, 21, 23]); // different weights t!([Weighted { weight: 4, item: 30}, Weighted { weight: 3, item: 31}], [30, 31, 30, 31, 30, 31, 30]); // check that we're binary searching // correctly with some vectors of odd // length. t!([Weighted { weight: 1, item: 40}, Weighted { weight: 1, item: 41}, Weighted { weight: 1, item: 42}, Weighted { weight: 1, item: 43}, Weighted { weight: 1, item: 44}], [40, 41, 42, 43, 44]); t!([Weighted { weight: 1, item: 50}, Weighted { weight: 1, item: 51}, Weighted { weight: 1, item: 52}, Weighted { weight: 1, item: 53}, Weighted { weight: 1, item: 54}, Weighted { weight: 1, item: 55}, Weighted { weight: 1, item: 56}], [50, 54, 51, 55, 52, 56, 53]); } #[test] fn test_weighted_clone_initialization() { let initial : Weighted = Weighted {weight: 1, item: 1}; let clone = initial.clone(); assert_eq!(initial.weight, clone.weight); assert_eq!(initial.item, clone.item); } #[test] #[should_panic] fn test_weighted_clone_change_weight() { let initial : Weighted = Weighted {weight: 1, item: 1}; let mut clone = initial.clone(); clone.weight = 5; assert_eq!(initial.weight, clone.weight); } #[test] #[should_panic] fn test_weighted_clone_change_item() { let initial : Weighted = Weighted {weight: 1, item: 1}; let mut clone = initial.clone(); clone.item = 5; assert_eq!(initial.item, clone.item); } #[test] #[should_panic] fn test_weighted_choice_no_items() { WeightedChoice::::new(&mut []); } #[test] #[should_panic] fn test_weighted_choice_zero_weight() { WeightedChoice::new(&mut [Weighted { weight: 0, item: 0}, Weighted { weight: 0, item: 1}]); } #[test] #[should_panic] fn test_weighted_choice_weight_overflows() { let x = ::core::u32::MAX / 2; // x + x + 2 is the overflow WeightedChoice::new(&mut [Weighted { weight: x, item: 0 }, Weighted { weight: 1, item: 1 }, Weighted { weight: x, item: 2 }, Weighted { weight: 1, item: 3 }]); } #[test] #[allow(deprecated)] fn test_backwards_compat_sample() { use distributions::{Sample, IndependentSample}; struct Constant { val: T } impl Sample for Constant { fn sample(&mut self, _: &mut R) -> T { self.val } } impl IndependentSample for Constant { fn ind_sample(&self, _: &mut R) -> T { self.val } } let mut sampler = Constant{ val: 293 }; assert_eq!(sampler.sample(&mut ::test::rng(233)), 293); assert_eq!(sampler.ind_sample(&mut ::test::rng(234)), 293); } #[cfg(feature="std")] #[test] #[allow(deprecated)] fn test_backwards_compat_exp() { use distributions::{IndependentSample, Exp}; let sampler = Exp::new(1.0); sampler.ind_sample(&mut ::test::rng(235)); } #[cfg(feature="std")] #[test] fn test_distributions_iter() { use distributions::Normal; let mut rng = ::test::rng(210); let distr = Normal::new(10.0, 10.0); let results: Vec<_> = distr.sample_iter(&mut rng).take(100).collect(); println!("{:?}", results); } } rand-0.5.5/src/distributions/normal.rs010064400017500001750000000124631333210603300162150ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use Rng; use distributions::{ziggurat, ziggurat_tables, Distribution, Open01}; /// 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 /// /// # Example /// ``` /// use rand::prelude::*; /// use rand::distributions::StandardNormal; /// /// let val: f64 = SmallRng::from_entropy().sample(StandardNormal); /// println!("{}", val); /// ``` #[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. /// /// # Example /// /// ``` /// use rand::distributions::{Normal, Distribution}; /// /// // mean 2, standard deviation 3 /// let normal = Normal::new(2.0, 3.0); /// let v = normal.sample(&mut rand::thread_rng()); /// println!("{} is from a N(2, 9) distribution", v) /// ``` #[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. /// /// # Example /// /// ``` /// use rand::distributions::{LogNormal, Distribution}; /// /// // mean 2, standard deviation 3 /// let log_normal = LogNormal::new(2.0, 3.0); /// let v = log_normal.sample(&mut rand::thread_rng()); /// println!("{} is from an ln N(2, 9) distribution", v) /// ``` #[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 distributions::Distribution; use super::{Normal, LogNormal}; #[test] fn test_normal() { let norm = Normal::new(10.0, 10.0); let mut rng = ::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 = ::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.5.5/src/distributions/other.rs010064400017500001750000000151461333210603300160470ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 {Rng}; use 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 { let range = Uniform::new(0u32, 0x11_0000); loop { match char::from_u32(range.sample(rng)) { Some(c) => return c, // About 0.2% of numbers in the range 0..0x110000 are invalid // codepoints (surrogates). None => {} } } } } 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 { #[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 {Rng, RngCore, Standard}; use distributions::Alphanumeric; #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String; #[test] fn test_misc() { let rng: &mut RngCore = &mut ::test::rng(820); rng.sample::(Standard); rng.sample::(Standard); } #[cfg(feature="alloc")] #[test] fn test_chars() { use core::iter; let mut rng = ::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 = ::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); } } rand-0.5.5/src/distributions/pareto.rs010064400017500001750000000040011332655332100162150ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use Rng; use distributions::{Distribution, OpenClosed01}; /// Samples floating-point numbers according to the Pareto distribution /// /// # Example /// ``` /// use rand::prelude::*; /// use rand::distributions::Pareto; /// /// let val: f64 = SmallRng::from_entropy().sample(Pareto::new(1., 2.)); /// println!("{}", val); /// ``` #[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 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 = ::test::rng(1); for _ in 0..1000 { let r = d.sample(&mut rng); assert!(r >= scale); } } } rand-0.5.5/src/distributions/poisson.rs010064400017500001750000000121241333210603300164110ustar0000000000000000// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. use Rng; use distributions::{Distribution, Cauchy}; use distributions::log_gamma::log_gamma; /// The Poisson distribution `Poisson(lambda)`. /// /// This distribution has a density function: /// `f(k) = lambda^k * exp(-lambda) / k!` for `k >= 0`. /// /// # Example /// /// ``` /// use rand::distributions::{Poisson, Distribution}; /// /// let poi = Poisson::new(2.0); /// let v = poi.sample(&mut rand::thread_rng()); /// println!("{} is from a Poisson(2) distribution", v); /// ``` #[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 distributions::Distribution; use super::Poisson; #[test] fn test_poisson_10() { let poisson = Poisson::new(10.0); let mut rng = ::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] fn test_poisson_15() { // Take the 'high expected values' path let poisson = Poisson::new(15.0); let mut rng = ::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.5.5/src/distributions/uniform.rs010064400017500001750000000742441333210603300164110ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! //! ``` //! use rand::prelude::*; //! use rand::distributions::uniform::{Uniform, SampleUniform, //! UniformSampler, UniformFloat}; //! //! struct MyF32(f32); //! //! #[derive(Clone, Copy, Debug)] //! struct UniformMyF32 { //! inner: UniformFloat, //! } //! //! impl UniformSampler for UniformMyF32 { //! type X = MyF32; //! fn new(low: Self::X, high: Self::X) -> Self { //! UniformMyF32 { //! inner: UniformFloat::::new(low.0, high.0), //! } //! } //! fn new_inclusive(low: Self::X, high: Self::X) -> Self { //! UniformSampler::new(low, high) //! } //! fn sample(&self, rng: &mut R) -> Self::X { //! MyF32(self.inner.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()); //! ``` //! //! [`Uniform`]: struct.Uniform.html //! [`Rng::gen_range`]: ../../trait.Rng.html#method.gen_range //! [`SampleUniform`]: trait.SampleUniform.html //! [`UniformSampler`]: trait.UniformSampler.html //! [`UniformInt`]: struct.UniformInt.html //! [`UniformFloat`]: struct.UniformFloat.html //! [`UniformDuration`]: struct.UniformDuration.html #[cfg(feature = "std")] use std::time::Duration; use Rng; use distributions::Distribution; use distributions::float::IntoFloat; /// 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 should attempt to sample in `[low, high)` for /// `Uniform::new(low, high)`, i.e., excluding `high`, but this may be very /// difficult. All the primitive integer types satisfy this property, and the /// float types normally satisfy it, but rounding may mean `high` can occur. /// /// # 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); /// } /// ``` /// /// [`Uniform::new`]: struct.Uniform.html#method.new /// [`Uniform::new_inclusive`]: struct.Uniform.html#method.new_inclusive /// [`new`]: struct.Uniform.html#method.new /// [`new_inclusive`]: struct.Uniform.html#method.new_inclusive #[derive(Clone, Copy, Debug)] pub struct Uniform { inner: 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: X, high: X) -> Uniform { Uniform { inner: 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: X, high: X) -> Uniform { Uniform { inner: X::Sampler::new_inclusive(low, high) } } } impl Distribution for Uniform { fn sample(&self, rng: &mut R) -> X { self.inner.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. /// /// [`UniformSampler`]: trait.UniformSampler.html /// [module documentation]: index.html /// [`Uniform`]: struct.Uniform.html 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]: index.html /// [`Uniform`]: struct.Uniform.html /// [`sample_single`]: trait.UniformSampler.html#method.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: Self::X, high: Self::X) -> Self; /// 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: Self::X, high: Self::X) -> Self; /// 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)`. /// /// Usually users should not call this directly but instead use /// `Uniform::sample_single`, which asserts that `low < high` before calling /// this. /// /// Via this method, implementations can provide a method optimized for /// sampling only a single value from the specified range. The default /// implementation simply calls `UniformSampler::new` then `sample` on the /// result. fn sample_single(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { 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) } } //////////////////////////////////////////////////////////////////////////////// // 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 a closed range, the number of possible numbers we should generate is /// `range = (high - low + 1)`. It is not possible to end up with a uniform /// distribution if we map *all* the random integers that can be generated to /// this range. We have to map integers from a `zone` that is a multiple of the /// range. The rest of the integers, that cause a bias, are rejected. /// /// The problem with `range` is that to cover the full range of the type, it has /// to store `unsigned_max + 1`, which can't be represented. But if the range /// covers the full range of the type, no modulus is needed. A range of size 0 /// can't exist, so we use that to represent this special case. Wrapping /// arithmetic even makes representing `unsigned_max + 1` as 0 simple. /// /// We don't calculate `zone` directly, but first calculate the number of /// integers to reject. To handle `unsigned_max + 1` not fitting in the type, /// we use: /// `ints_to_reject = (unsigned_max + 1) % range;` /// `ints_to_reject = (unsigned_max - range + 1) % range;` /// /// The smallest integer PRNGs generate is `u32`. That is why for small integer /// sizes (`i8`/`u8` and `i16`/`u16`) there is an optimization: don't pick the /// largest zone that can fit in the small type, but pick the largest zone that /// can fit in an `u32`. `ints_to_reject` is always less than half the size of /// the small integer. This means the first bit of `zone` is always 1, and so /// are all the other preceding bits of a larger integer. The easiest way to /// grow the `zone` for the larger type is to simply sign extend it. /// /// 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. /// /// [`UniformSampler`]: trait.UniformSampler.html /// [`Uniform`]: struct.Uniform.html #[derive(Clone, Copy, Debug)] pub struct UniformInt { low: X, range: X, zone: X, } macro_rules! uniform_int_impl { ($ty:ty, $signed:ty, $unsigned:ident, $i_large: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: Self::X, high: Self::X) -> Self { 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: Self::X, high: Self::X) -> Self { assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); let unsigned_max = ::core::$unsigned::MAX; let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned; let ints_to_reject = if range > 0 { (unsigned_max - range + 1) % range } else { 0 }; let zone = unsigned_max - ints_to_reject; UniformInt { low: low, // These are really $unsigned values, but store as $ty: range: range as $ty, zone: zone as $ty } } fn sample(&self, rng: &mut R) -> Self::X { let range = self.range as $unsigned as $u_large; if range > 0 { // Grow `zone` to fit a type of at least 32 bits, by // sign-extending it (the first bit is always 1, so are all // the preceding bits of the larger type). // For types that already have the right size, all the // casting is a no-op. let zone = self.zone as $signed as $i_large 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: Self::X, high: Self::X, rng: &mut R) -> Self::X { assert!(low < high, "Uniform::sample_single called with 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 range << range.leading_zeros() }; 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, i8, u8, i32, u32 } uniform_int_impl! { i16, i16, u16, i32, u32 } uniform_int_impl! { i32, i32, u32, i32, u32 } uniform_int_impl! { i64, i64, u64, i64, u64 } #[cfg(feature = "i128_support")] uniform_int_impl! { i128, i128, u128, u128, u128 } uniform_int_impl! { isize, isize, usize, isize, usize } uniform_int_impl! { u8, i8, u8, i32, u32 } uniform_int_impl! { u16, i16, u16, i32, u32 } uniform_int_impl! { u32, i32, u32, i32, u32 } uniform_int_impl! { u64, i64, u64, i64, u64 } uniform_int_impl! { usize, isize, usize, isize, usize } #[cfg(feature = "i128_support")] uniform_int_impl! { u128, u128, u128, i128, u128 } 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) } } } } wmul_impl! { u8, u16, 8 } wmul_impl! { u16, u32, 16 } wmul_impl! { u32, u64, 32 } #[cfg(feature = "i128_support")] 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 shuffeling 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) } } } } #[cfg(not(feature = "i128_support"))] wmul_impl_large! { u64, 32 } #[cfg(feature = "i128_support")] 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 } /// 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`. /// /// Currently there is no difference between [`new`] and [`new_inclusive`], /// because the boundaries of a floats range are a bit of a fuzzy concept due to /// rounding errors. /// /// [`UniformSampler`]: trait.UniformSampler.html /// [`new`]: trait.UniformSampler.html#tymethod.new /// [`new_inclusive`]: trait.UniformSampler.html#tymethod.new_inclusive /// [`Uniform`]: struct.Uniform.html /// [`Standard`]: ../struct.Standard.html #[derive(Clone, Copy, Debug)] pub struct UniformFloat { scale: X, offset: X, } macro_rules! uniform_float_impl { ($ty:ty, $bits_to_discard:expr, $next_u:ident) => { impl SampleUniform for $ty { type Sampler = UniformFloat<$ty>; } impl UniformSampler for UniformFloat<$ty> { type X = $ty; fn new(low: Self::X, high: Self::X) -> Self { assert!(low < high, "Uniform::new called with `low >= high`"); let scale = high - low; let offset = low - scale; UniformFloat { scale: scale, offset: offset, } } fn new_inclusive(low: Self::X, high: Self::X) -> Self { assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); let scale = high - low; let offset = low - scale; UniformFloat { scale: scale, offset: offset, } } fn sample(&self, rng: &mut R) -> Self::X { // Generate a value in the range [1, 2) let value1_2 = (rng.$next_u() >> $bits_to_discard) .into_float_with_exponent(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. value1_2 * self.scale + self.offset } fn sample_single(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { assert!(low < high, "Uniform::sample_single called with low >= high"); let scale = high - low; let offset = low - scale; // Generate a value in the range [1, 2) let value1_2 = (rng.$next_u() >> $bits_to_discard) .into_float_with_exponent(0); // Doing multiply before addition allows some architectures to // use a single instruction. value1_2 * scale + offset } } } } uniform_float_impl! { f32, 32 - 23, next_u32 } uniform_float_impl! { f64, 64 - 52, next_u64 } /// 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. /// /// [`UniformSampler`]: trait.UniformSampler.html /// [`Uniform`]: struct.Uniform.html #[cfg(feature = "std")] #[derive(Clone, Copy, Debug)] pub struct UniformDuration { offset: Duration, mode: UniformDurationMode, } #[cfg(feature = "std")] #[derive(Debug, Copy, Clone)] enum UniformDurationMode { Small { nanos: Uniform, }, Large { size: Duration, secs: Uniform, } } #[cfg(feature = "std")] impl SampleUniform for Duration { type Sampler = UniformDuration; } #[cfg(feature = "std")] impl UniformSampler for UniformDuration { type X = Duration; #[inline] fn new(low: Duration, high: Duration) -> UniformDuration { assert!(low < high, "Uniform::new called with `low >= high`"); UniformDuration::new_inclusive(low, high - Duration::new(0, 1)) } #[inline] fn new_inclusive(low: Duration, high: Duration) -> UniformDuration { assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); let size = high - low; let nanos = size .as_secs() .checked_mul(1_000_000_000) .and_then(|n| n.checked_add(size.subsec_nanos() as u64)); let mode = match nanos { Some(nanos) => { UniformDurationMode::Small { nanos: Uniform::new_inclusive(0, nanos), } } None => { UniformDurationMode::Large { size: size, secs: Uniform::new_inclusive(0, size.as_secs()), } } }; UniformDuration { mode, offset: low, } } #[inline] fn sample(&self, rng: &mut R) -> Duration { let d = match self.mode { UniformDurationMode::Small { nanos } => { let nanos = nanos.sample(rng); Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) } UniformDurationMode::Large { size, 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 d = Duration::new(secs.sample(rng), nano_range.sample(rng)); if d <= size { break d; } } } }; self.offset + d } } #[cfg(test)] mod tests { use Rng; use distributions::uniform::{Uniform, UniformSampler, UniformFloat, SampleUniform}; #[should_panic] #[test] fn test_uniform_bad_limits_equal_int() { Uniform::new(10, 10); } #[should_panic] #[test] fn test_uniform_bad_limits_equal_float() { Uniform::new(10., 10.); } #[test] fn test_uniform_good_limits_equal_int() { let mut rng = ::test::rng(804); let dist = Uniform::new_inclusive(10, 10); for _ in 0..20 { assert_eq!(rng.sample(dist), 10); } } #[test] fn test_uniform_good_limits_equal_float() { let mut rng = ::test::rng(805); 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); } #[should_panic] #[test] fn test_uniform_bad_limits_flipped_float() { Uniform::new(10., 5.); } #[test] fn test_integers() { let mut rng = ::test::rng(251); macro_rules! t { ($($ty:ident),*) => {{ $( let v: &[($ty, $ty)] = &[(0, 10), (10, 127), (::core::$ty::MIN, ::core::$ty::MAX)]; 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!(low <= v && v < high); } let my_uniform = Uniform::new_inclusive(low, high); for _ in 0..1000 { let v: $ty = rng.sample(my_uniform); assert!(low <= v && v <= high); } for _ in 0..1000 { let v: $ty = rng.gen_range(low, high); assert!(low <= v && v < high); } } )* }} } t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); #[cfg(feature = "i128_support")] t!(i128, u128) } #[test] fn test_floats() { let mut rng = ::test::rng(252); macro_rules! t { ($($ty:ty),*) => {{ $( let v: &[($ty, $ty)] = &[(0.0, 100.0), (-1e35, -1e25), (1e-35, 1e-25), (-1e35, 1e35)]; 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!(low <= v && v < high); } } )* }} } t!(f32, f64) } #[test] #[cfg(feature = "std")] fn test_durations() { use std::time::Duration; let mut rng = ::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() { #[derive(Clone, Copy, PartialEq, PartialOrd)] struct MyF32 { x: f32, } #[derive(Clone, Copy, Debug)] struct UniformMyF32 { inner: UniformFloat, } impl UniformSampler for UniformMyF32 { type X = MyF32; fn new(low: Self::X, high: Self::X) -> Self { UniformMyF32 { inner: UniformFloat::::new(low.x, high.x), } } fn new_inclusive(low: Self::X, high: Self::X) -> Self { UniformSampler::new(low, high) } fn sample(&self, rng: &mut R) -> Self::X { MyF32 { x: self.inner.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 = ::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.inner.low, 2); assert_eq!(r.inner.range, 5); let r = Uniform::from(2.0f64..7.0); assert_eq!(r.inner.offset, -3.0); assert_eq!(r.inner.scale, 5.0); } } rand-0.5.5/src/distributions/ziggurat_tables.rs010064400017500001750000000603271332655332100201260ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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.5.5/src/lib.rs010064400017500001750000001221211333210670600125710ustar0000000000000000// Copyright 2013-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! //! # Basic usage //! //! To get you started quickly, the easiest and highest-level way to get //! a random value is to use [`random()`]. //! //! ``` //! let x: u8 = rand::random(); //! println!("{}", x); //! //! let y = rand::random::(); //! println!("{}", y); //! //! if rand::random() { // generates a boolean //! println!("Heads!"); //! } //! ``` //! //! This supports generating most common types but is not very flexible, thus //! you probably want to learn a bit more about the Rand library. //! //! //! # The two-step process to get a random value //! //! Generating random values is typically a two-step process: //! //! - get some *random data* (an integer or bit/byte sequence) from a random //! number generator (RNG); //! - use some function to transform that *data* into the type of value you want //! (this function is an implementation of some *distribution* describing the //! kind of value produced). //! //! Rand represents the first step with the [`RngCore`] trait and the second //! step via a combination of the [`Rng`] extension trait and the //! [`distributions` module]. //! In practice you probably won't use [`RngCore`] directly unless you are //! implementing a random number generator (RNG). //! //! There are many kinds of RNGs, with different trade-offs. You can read more //! about them in the [`rngs` module] and even more in the [`prng` module], //! however, often you can just use [`thread_rng()`]. This function //! automatically initializes an RNG in thread-local memory, then returns a //! reference to it. It is fast, good quality, and secure (unpredictable). //! //! To turn the output of the RNG into something usable, you usually want to use //! the methods from the [`Rng`] trait. Some of the most useful methods are: //! //! - [`gen`] generates a random value appropriate for the type (just like //! [`random()`]). For integers this is normally the full representable range //! (e.g. from `0u32` to `std::u32::MAX`), for floats this is between 0 and 1, //! and some other types are supported, including arrays and tuples. See the //! [`Standard`] distribution which provides the implementations. //! - [`gen_range`] samples from a specific range of values; this is like //! [`gen`] but with specific upper and lower bounds. //! - [`sample`] samples directly from some distribution. //! //! [`random()`] is defined using just the above: `thread_rng().gen()`. //! //! ## Distributions //! //! What are distributions, you ask? Specifying only the type and range of //! values (known as the *sample space*) is not enough; samples must also have //! a *probability distribution*, describing the relative probability of //! sampling each value in that space. //! //! In many cases a *uniform* distribution is used, meaning roughly that each //! value is equally likely (or for "continuous" types like floats, that each //! equal-sized sub-range has the same probability of containing a sample). //! [`gen`] and [`gen_range`] both use statistically uniform distributions. //! //! The [`distributions` module] provides implementations //! of some other distributions, including Normal, Log-Normal and Exponential. //! //! It is worth noting that the functionality already mentioned is implemented //! with distributions: [`gen`] samples values using the [`Standard`] //! distribution, while [`gen_range`] uses [`Uniform`]. //! //! ## Importing (prelude) //! //! The most convenient way to import items from Rand is to use the [prelude]. //! This includes the most important parts of Rand, but only those unlikely to //! cause name conflicts. //! //! Note that Rand 0.5 has significantly changed the module organization and //! contents relative to previous versions. Where possible old names have been //! kept (but are hidden in the documentation), however these will be removed //! in the future. We therefore recommend migrating to use the prelude or the //! new module organization in your imports. //! //! //! ## Examples //! //! ``` //! use rand::prelude::*; //! //! // thread_rng is often the most convenient source of randomness: //! let mut rng = thread_rng(); //! //! if rng.gen() { // random bool //! let x: f64 = rng.gen(); // random number in range [0, 1) //! println!("x is: {}", x); //! let ch = rng.gen::(); // using type annotation //! println!("char is: {}", ch); //! println!("Number from 0 to 9: {}", rng.gen_range(0, 10)); //! } //! ``` //! //! //! # More functionality //! //! The [`Rng`] trait includes a few more methods not mentioned above: //! //! - [`Rng::sample_iter`] allows iterating over values from a chosen //! distribution. //! - [`Rng::gen_bool`] generates boolean "events" with a given probability. //! - [`Rng::fill`] and [`Rng::try_fill`] are fast alternatives to fill a slice //! of integers. //! - [`Rng::shuffle`] randomly shuffles elements in a slice. //! - [`Rng::choose`] picks one element at random from a slice. //! //! For more slice/sequence related functionality, look in the [`seq` module]. //! //! There is also [`distributions::WeightedChoice`], which can be used to pick //! elements at random with some probability. But it does not work well at the //! moment and is going through a redesign. //! //! //! # Error handling //! //! Error handling in Rand is a compromise between simplicity and necessity. //! Most RNGs and sampling functions will never produce errors, and making these //! able to handle errors would add significant overhead (to code complexity //! and ergonomics of usage at least, and potentially also performance, //! depending on the approach). //! However, external RNGs can fail, and being able to handle this is important. //! //! It has therefore been decided that *most* methods should not return a //! `Result` type, with as exceptions [`Rng::try_fill`], //! [`RngCore::try_fill_bytes`], and [`SeedableRng::from_rng`]. //! //! Note that it is the RNG that panics when it fails but is not used through a //! method that can report errors. Currently Rand contains only three RNGs that //! can return an error (and thus may panic), and documents this property: //! [`OsRng`], [`EntropyRng`] and [`ReadRng`]. Other RNGs, like [`ThreadRng`] //! and [`StdRng`], can be used with all methods without concern. //! //! One further problem is that if Rand is unable to get any external randomness //! when initializing an RNG with [`EntropyRng`], it will panic in //! [`FromEntropy::from_entropy`], and notably in [`thread_rng()`]. Except by //! compromising security, this problem is as unsolvable as running out of //! memory. //! //! //! # Distinction between Rand and `rand_core` //! //! The [`rand_core`] crate provides the necessary traits and functionality for //! implementing RNGs; this includes the [`RngCore`] and [`SeedableRng`] traits //! and the [`Error`] type. //! Crates implementing RNGs should depend on [`rand_core`]. //! //! Applications and libraries consuming random values are encouraged to use the //! Rand crate, which re-exports the common parts of [`rand_core`]. //! //! //! # More examples //! //! For some inspiration, see the examples: //! //! - [Monte Carlo estimation of π]( //! https://github.com/rust-lang-nursery/rand/blob/master/examples/monte-carlo.rs) //! - [Monty Hall Problem]( //! https://github.com/rust-lang-nursery/rand/blob/master/examples/monty-hall.rs) //! //! //! [`distributions` module]: distributions/index.html //! [`distributions::WeightedChoice`]: distributions/struct.WeightedChoice.html //! [`FromEntropy::from_entropy`]: trait.FromEntropy.html#tymethod.from_entropy //! [`EntropyRng`]: rngs/struct.EntropyRng.html //! [`Error`]: struct.Error.html //! [`gen_range`]: trait.Rng.html#method.gen_range //! [`gen`]: trait.Rng.html#method.gen //! [`OsRng`]: rngs/struct.OsRng.html //! [prelude]: prelude/index.html //! [`rand_core`]: https://crates.io/crates/rand_core //! [`random()`]: fn.random.html //! [`ReadRng`]: rngs/adapter/struct.ReadRng.html //! [`Rng::choose`]: trait.Rng.html#method.choose //! [`Rng::fill`]: trait.Rng.html#method.fill //! [`Rng::gen_bool`]: trait.Rng.html#method.gen_bool //! [`Rng::gen`]: trait.Rng.html#method.gen //! [`Rng::sample_iter`]: trait.Rng.html#method.sample_iter //! [`Rng::shuffle`]: trait.Rng.html#method.shuffle //! [`RngCore`]: trait.RngCore.html //! [`RngCore::try_fill_bytes`]: trait.RngCore.html#method.try_fill_bytes //! [`rngs` module]: rngs/index.html //! [`prng` module]: prng/index.html //! [`Rng`]: trait.Rng.html //! [`Rng::try_fill`]: trait.Rng.html#method.try_fill //! [`sample`]: trait.Rng.html#method.sample //! [`SeedableRng`]: trait.SeedableRng.html //! [`SeedableRng::from_rng`]: trait.SeedableRng.html#method.from_rng //! [`seq` module]: seq/index.html //! [`SmallRng`]: rngs/struct.SmallRng.html //! [`StdRng`]: rngs/struct.StdRng.html //! [`thread_rng()`]: fn.thread_rng.html //! [`ThreadRng`]: rngs/struct.ThreadRng.html //! [`Standard`]: distributions/struct.Standard.html //! [`Uniform`]: distributions/struct.Uniform.html #![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://docs.rs/rand/0.5.5")] #![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="alloc", not(feature="std")), feature(alloc))] #![cfg_attr(all(feature="i128_support", feature="nightly"), allow(stable_features))] // stable since 2018-03-27 #![cfg_attr(all(feature="i128_support", feature="nightly"), feature(i128_type, i128))] #![cfg_attr(feature = "stdweb", recursion_limit="128")] #[cfg(feature="std")] extern crate std as core; #[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc; #[cfg(test)] #[cfg(feature="serde1")] extern crate bincode; #[cfg(feature="serde1")] extern crate serde; #[cfg(feature="serde1")] #[macro_use] extern crate serde_derive; #[cfg(all(target_arch="wasm32", not(target_os="emscripten"), feature="stdweb"))] #[macro_use] extern crate stdweb; extern crate rand_core; #[cfg(feature = "log")] #[macro_use] extern crate log; #[allow(unused)] #[cfg(not(feature = "log"))] macro_rules! trace { ($($x:tt)*) => () } #[allow(unused)] #[cfg(not(feature = "log"))] macro_rules! debug { ($($x:tt)*) => () } #[allow(unused)] #[cfg(not(feature = "log"))] macro_rules! info { ($($x:tt)*) => () } #[allow(unused)] #[cfg(not(feature = "log"))] macro_rules! warn { ($($x:tt)*) => () } #[allow(unused)] #[cfg(not(feature = "log"))] macro_rules! error { ($($x:tt)*) => () } // Re-exports from rand_core pub use rand_core::{RngCore, CryptoRng, SeedableRng}; pub use rand_core::{ErrorKind, Error}; // Public exports #[cfg(feature="std")] pub use rngs::thread::thread_rng; // Public modules pub mod distributions; pub mod prelude; pub mod prng; pub mod rngs; #[cfg(feature = "alloc")] pub mod seq; //////////////////////////////////////////////////////////////////////////////// // Compatibility re-exports. Documentation is hidden; will be removed eventually. #[cfg(feature="std")] #[doc(hidden)] pub use rngs::adapter::read; #[doc(hidden)] pub use rngs::adapter::ReseedingRng; #[allow(deprecated)] #[cfg(feature="std")] #[doc(hidden)] pub use rngs::EntropyRng; #[allow(deprecated)] #[cfg(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") )))] #[doc(hidden)] pub use rngs::OsRng; #[doc(hidden)] pub use prng::{ChaChaRng, IsaacRng, Isaac64Rng, XorShiftRng}; #[doc(hidden)] pub use rngs::StdRng; #[allow(deprecated)] #[doc(hidden)] pub mod jitter { pub use rngs::{JitterRng, TimerError}; } #[allow(deprecated)] #[cfg(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") )))] #[doc(hidden)] pub mod os { pub use rngs::OsRng; } #[allow(deprecated)] #[doc(hidden)] pub mod chacha { //! The ChaCha random number generator. pub use prng::ChaChaRng; } #[doc(hidden)] pub mod isaac { //! The ISAAC random number generator. pub use prng::{IsaacRng, Isaac64Rng}; } #[cfg(feature="std")] #[doc(hidden)] pub use rngs::ThreadRng; //////////////////////////////////////////////////////////////////////////////// use core::{marker, mem, slice}; use distributions::{Distribution, Standard}; use distributions::uniform::{SampleUniform, UniformSampler}; /// A type that can be randomly generated using an [`Rng`]. /// /// This is merely an adapter around the [`Standard`] distribution for /// convenience and backwards-compatibility. /// /// [`Rng`]: trait.Rng.html /// [`Standard`]: distributions/struct.Standard.html #[deprecated(since="0.5.0", note="replaced by distributions::Standard")] pub trait Rand : Sized { /// Generates a random instance of this type using the specified source of /// randomness. fn rand(rng: &mut R) -> Self; } /// 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()); /// ``` /// /// [`RngCore`]: trait.RngCore.html pub trait Rng: RngCore { /// Return a random value supporting the [`Standard`] distribution. /// /// [`Standard`]: distributions/struct.Standard.html /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let x: u32 = rng.gen(); /// println!("{}", x); /// println!("{:?}", rng.gen::<(f64, bool)>()); /// ``` #[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/struct.Uniform.html fn gen_range(&mut self, low: T, high: T) -> T { 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. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// use rand::distributions::{Alphanumeric, Uniform, Standard}; /// /// let mut rng = thread_rng(); /// /// // Vec of 16 x f32: /// let v: Vec = thread_rng().sample_iter(&Standard).take(16).collect(); /// /// // String: /// let s: String = rng.sample_iter(&Alphanumeric).take(7).collect(); /// /// // Combined values /// println!("{:?}", thread_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<'a, T, D: Distribution>(&'a mut self, distr: &'a D) -> distributions::DistIter<'a, D, Self, T> where 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`]: trait.RngCore.html#method.fill_bytes /// [`try_fill`]: trait.Rng.html#method.try_fill /// [`AsByteSliceMut`]: trait.AsByteSliceMut.html 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 uses [`try_fill_bytes`] internally and forwards all RNG errors. In /// some cases errors may be resolvable; see [`ErrorKind`] and /// documentation for the RNG in use. If you do not plan to handle these /// errors you may prefer to use [`fill`]. /// /// # 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() /// ``` /// /// [`ErrorKind`]: enum.ErrorKind.html /// [`try_fill_bytes`]: trait.RngCore.html#method.try_fill_bytes /// [`fill`]: trait.Rng.html#method.fill /// [`AsByteSliceMut`]: trait.AsByteSliceMut.html 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. /// /// This is a wrapper around [`distributions::Bernoulli`]. /// /// # 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. /// /// [`distributions::Bernoulli`]: distributions/bernoulli/struct.Bernoulli.html #[inline] fn gen_bool(&mut self, p: f64) -> bool { let d = distributions::Bernoulli::new(p); self.sample(d) } /// Return a random element from `values`. /// /// Return `None` if `values` is empty. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let choices = [1, 2, 4, 8, 16, 32]; /// let mut rng = thread_rng(); /// println!("{:?}", rng.choose(&choices)); /// assert_eq!(rng.choose(&choices[..0]), None); /// ``` fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> { if values.is_empty() { None } else { Some(&values[self.gen_range(0, values.len())]) } } /// Return a mutable pointer to a random element from `values`. /// /// Return `None` if `values` is empty. fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> { if values.is_empty() { None } else { let len = values.len(); Some(&mut values[self.gen_range(0, len)]) } } /// Shuffle a mutable slice in place. /// /// This applies Durstenfeld's algorithm for the [Fisher–Yates shuffle]( /// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) /// which produces an unbiased permutation. /// /// # Example /// /// ``` /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let mut y = [1, 2, 3]; /// rng.shuffle(&mut y); /// println!("{:?}", y); /// rng.shuffle(&mut y); /// println!("{:?}", y); /// ``` fn shuffle(&mut self, values: &mut [T]) { let mut i = values.len(); while i >= 2 { // invariant: elements with index >= i have been locked in place. i -= 1; // lock element i in place. values.swap(i, self.gen_range(0, i + 1)); } } /// Return an iterator that will yield an infinite number of randomly /// generated items. /// /// # Example /// /// ``` /// # #![allow(deprecated)] /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let x = rng.gen_iter::().take(10).collect::>(); /// println!("{:?}", x); /// println!("{:?}", rng.gen_iter::<(f64, bool)>().take(5) /// .collect::>()); /// ``` #[allow(deprecated)] #[deprecated(since="0.5.0", note="use Rng::sample_iter(&Standard) instead")] fn gen_iter(&mut self) -> Generator where Standard: Distribution { Generator { rng: self, _marker: marker::PhantomData } } /// Return a bool with a 1 in n chance of true /// /// # Example /// /// ``` /// # #![allow(deprecated)] /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// assert_eq!(rng.gen_weighted_bool(0), true); /// assert_eq!(rng.gen_weighted_bool(1), true); /// // Just like `rng.gen::()` a 50-50% chance, but using a slower /// // method with different results. /// println!("{}", rng.gen_weighted_bool(2)); /// // First meaningful use of `gen_weighted_bool`. /// println!("{}", rng.gen_weighted_bool(3)); /// ``` #[deprecated(since="0.5.0", note="use gen_bool instead")] fn gen_weighted_bool(&mut self, n: u32) -> bool { // Short-circuit after `n <= 1` to avoid panic in `gen_range` n <= 1 || self.gen_range(0, n) == 0 } /// Return an iterator of random characters from the set A-Z,a-z,0-9. /// /// # Example /// /// ``` /// # #![allow(deprecated)] /// use rand::{thread_rng, Rng}; /// /// let s: String = thread_rng().gen_ascii_chars().take(10).collect(); /// println!("{}", s); /// ``` #[allow(deprecated)] #[deprecated(since="0.5.0", note="use sample_iter(&Alphanumeric) instead")] fn gen_ascii_chars(&mut self) -> AsciiGenerator<&mut Self> { AsciiGenerator { rng: self } } } impl Rng for R {} /// Trait for casting types to byte slices /// /// This is used by the [`fill`] and [`try_fill`] methods. /// /// [`fill`]: trait.Rng.html#method.fill /// [`try_fill`]: trait.Rng.html#method.try_fill 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(&mut self[0] as *mut $t as *mut u8, self.len() * mem::size_of::<$t>() ) } } } fn to_le(&mut self) { for x in self { *x = x.to_le(); } } } } } impl_as_byte_slice!(u16); impl_as_byte_slice!(u32); impl_as_byte_slice!(u64); #[cfg(feature="i128_support")] impl_as_byte_slice!(u128); impl_as_byte_slice!(usize); impl_as_byte_slice!(i8); impl_as_byte_slice!(i16); impl_as_byte_slice!(i32); impl_as_byte_slice!(i64); #[cfg(feature="i128_support")] impl_as_byte_slice!(i128); impl_as_byte_slice!(isize); macro_rules! impl_as_byte_slice_arrays { ($n:expr,) => {}; ($n:expr, $N:ident, $($NN:ident,)*) => { impl_as_byte_slice_arrays!($n - 1, $($NN,)*); 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() } } }; (!div $n:expr,) => {}; (!div $n:expr, $N:ident, $($NN:ident,)*) => { impl_as_byte_slice_arrays!(!div $n / 2, $($NN,)*); 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() } } }; } 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,); /// Iterator which will generate a stream of random items. /// /// This iterator is created via the [`gen_iter`] method on [`Rng`]. /// /// [`gen_iter`]: trait.Rng.html#method.gen_iter /// [`Rng`]: trait.Rng.html #[derive(Debug)] #[allow(deprecated)] #[deprecated(since="0.5.0", note="use Rng::sample_iter instead")] pub struct Generator { rng: R, _marker: marker::PhantomData T>, } #[allow(deprecated)] impl Iterator for Generator where Standard: Distribution { type Item = T; fn next(&mut self) -> Option { Some(self.rng.gen()) } } /// Iterator which will continuously generate random ascii characters. /// /// This iterator is created via the [`gen_ascii_chars`] method on [`Rng`]. /// /// [`gen_ascii_chars`]: trait.Rng.html#method.gen_ascii_chars /// [`Rng`]: trait.Rng.html #[derive(Debug)] #[allow(deprecated)] #[deprecated(since="0.5.0", note="use distributions::Alphanumeric instead")] pub struct AsciiGenerator { rng: R, } #[allow(deprecated)] impl Iterator for AsciiGenerator { type Item = char; fn next(&mut self) -> Option { const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789"; Some(*self.rng.choose(GEN_ASCII_STR_CHARSET).unwrap() as char) } } /// A convenience extension to [`SeedableRng`] allowing construction from fresh /// entropy. This trait is automatically implemented for any PRNG implementing /// [`SeedableRng`] and is not intended to be implemented by users. /// /// This is equivalent to using `SeedableRng::from_rng(EntropyRng::new())` then /// unwrapping the result. /// /// Since this is convenient and secure, it is the recommended way to create /// PRNGs, though two alternatives may be considered: /// /// * Deterministic creation using [`SeedableRng::from_seed`] with a fixed seed /// * Seeding from `thread_rng`: `SeedableRng::from_rng(thread_rng())?`; /// this will usually be faster and should also be secure, but requires /// trusting one extra component. /// /// ## Example /// /// ``` /// use rand::{Rng, FromEntropy}; /// use rand::rngs::StdRng; /// /// let mut rng = StdRng::from_entropy(); /// println!("Random die roll: {}", rng.gen_range(1, 7)); /// ``` /// /// [`EntropyRng`]: rngs/struct.EntropyRng.html /// [`SeedableRng`]: trait.SeedableRng.html /// [`SeedableRng::from_seed`]: trait.SeedableRng.html#tymethod.from_seed #[cfg(feature="std")] pub trait FromEntropy: SeedableRng { /// Creates a new instance, automatically seeded with fresh entropy. /// /// Normally this will use `OsRng`, but if that fails `JitterRng` will be /// used instead. Both should be suitable for cryptography. It is possible /// that both entropy sources will fail though unlikely; failures would /// almost certainly be platform limitations or build issues, i.e. most /// applications targetting PC/mobile platforms should not need to worry /// about this failing. /// /// # Panics /// /// If all entropy sources fail this will panic. If you need to handle /// errors, use the following code, equivalent aside from error handling: /// /// ``` /// # use rand::Error; /// use rand::prelude::*; /// use rand::rngs::EntropyRng; /// /// # fn try_inner() -> Result<(), Error> { /// // This uses StdRng, but is valid for any R: SeedableRng /// let mut rng = StdRng::from_rng(EntropyRng::new())?; /// /// println!("random number: {}", rng.gen_range(1, 10)); /// # Ok(()) /// # } /// /// # try_inner().unwrap() /// ``` fn from_entropy() -> Self; } #[cfg(feature="std")] impl FromEntropy for R { fn from_entropy() -> R { R::from_rng(EntropyRng::new()).unwrap_or_else(|err| panic!("FromEntropy::from_entropy() failed: {}", err)) } } /// DEPRECATED: use [`SmallRng`] instead. /// /// Create a weak random number generator with a default algorithm and seed. /// /// It returns the fastest `Rng` algorithm currently available in Rust without /// consideration for cryptography or security. If you require a specifically /// seeded `Rng` for consistency over time you should pick one algorithm and /// create the `Rng` yourself. /// /// This will seed the generator with randomness from `thread_rng`. /// /// [`SmallRng`]: rngs/struct.SmallRng.html #[deprecated(since="0.5.0", note="removed in favor of SmallRng")] #[cfg(feature="std")] pub fn weak_rng() -> XorShiftRng { XorShiftRng::from_rng(thread_rng()).unwrap_or_else(|err| panic!("weak_rng failed: {:?}", err)) } /// 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. /// /// ``` /// # #![allow(deprecated)] /// 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(); /// } /// ``` /// /// [`thread_rng`]: fn.thread_rng.html /// [`Standard`]: distributions/struct.Standard.html #[cfg(feature="std")] #[inline] pub fn random() -> T where Standard: Distribution { thread_rng().gen() } /// DEPRECATED: use `seq::sample_iter` instead. /// /// Randomly sample up to `amount` elements from a finite iterator. /// The order of elements in the sample is not random. /// /// # Example /// /// ``` /// # #![allow(deprecated)] /// use rand::{thread_rng, sample}; /// /// let mut rng = thread_rng(); /// let sample = sample(&mut rng, 1..100, 5); /// println!("{:?}", sample); /// ``` #[cfg(feature="std")] #[inline] #[deprecated(since="0.4.0", note="renamed to seq::sample_iter")] pub fn sample(rng: &mut R, iterable: I, amount: usize) -> Vec where I: IntoIterator, R: Rng, { // the legacy sample didn't care whether amount was met seq::sample_iter(rng, iterable, amount) .unwrap_or_else(|e| e) } #[cfg(test)] mod test { use rngs::mock::StepRng; use super::*; #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::boxed::Box; pub struct TestRng { inner: R } impl RngCore for TestRng { fn next_u32(&mut self) -> u32 { self.inner.next_u32() } fn next_u64(&mut self) -> u64 { self.inner.next_u64() } fn fill_bytes(&mut self, dest: &mut [u8]) { self.inner.fill_bytes(dest) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.inner.try_fill_bytes(dest) } } pub fn rng(seed: u64) -> TestRng { // TODO: use from_hashable let mut state = seed; let mut seed = ::Seed::default(); for x in seed.iter_mut() { // PCG algorithm const MUL: u64 = 6364136223846793005; const INC: u64 = 11634580027462260723; let oldstate = state; state = oldstate.wrapping_mul(MUL).wrapping_add(INC); let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32; let rot = (oldstate >> 59) as u32; *x = xorshifted.rotate_right(rot) as u8; } TestRng { inner: StdRng::from_seed(seed) } } #[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); } #[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(-3, 42); assert!(a >= -3 && a < 42); assert_eq!(r.gen_range(0, 1), 0); assert_eq!(r.gen_range(-12, -11), -12); } for _ in 0..1000 { let a = r.gen_range(10, 42); assert!(a >= 10 && a < 42); assert_eq!(r.gen_range(0, 1), 0); 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] #[allow(deprecated)] fn test_gen_weighted_bool() { let mut r = rng(104); assert_eq!(r.gen_weighted_bool(0), true); assert_eq!(r.gen_weighted_bool(1), true); } #[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_choose() { let mut r = rng(107); assert_eq!(r.choose(&[1, 1, 1]).map(|&x|x), Some(1)); let v: &[isize] = &[]; assert_eq!(r.choose(v), None); } #[test] fn test_shuffle() { let mut r = rng(108); let empty: &mut [isize] = &mut []; r.shuffle(empty); let mut one = [1]; r.shuffle(&mut one); let b: &[_] = &[1]; assert_eq!(one, b); let mut two = [1, 2]; r.shuffle(&mut two); assert!(two == [1, 2] || two == [2, 1]); let mut x = [1, 1, 1]; r.shuffle(&mut x); let b: &[_] = &[1, 1, 1]; assert_eq!(x, b); } #[test] fn test_rng_trait_object() { use distributions::{Distribution, Standard}; let mut rng = rng(109); let mut r = &mut rng as &mut RngCore; r.next_u32(); r.gen::(); let mut v = [1, 1, 1]; r.shuffle(&mut v); let b: &[_] = &[1, 1, 1]; assert_eq!(v, b); 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 distributions::{Distribution, Standard}; let rng = rng(110); let mut r = Box::new(rng) as Box; r.next_u32(); r.gen::(); let mut v = [1, 1, 1]; r.shuffle(&mut v); let b: &[_] = &[1, 1, 1]; assert_eq!(v, b); 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(); } } rand-0.5.5/src/prelude.rs010064400017500001750000000022541333210603300134600ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 _ = StdRng::from_entropy(); //! # let mut r = SmallRng::from_rng(thread_rng()).unwrap(); //! # let _: f32 = r.gen(); //! ``` #[doc(no_inline)] pub use distributions::Distribution; #[doc(no_inline)] pub use rngs::{SmallRng, StdRng}; #[doc(no_inline)] #[cfg(feature="std")] pub use rngs::ThreadRng; #[doc(no_inline)] pub use {Rng, RngCore, CryptoRng, SeedableRng}; #[doc(no_inline)] #[cfg(feature="std")] pub use {FromEntropy, random, thread_rng}; rand-0.5.5/src/prng/chacha.rs010064400017500001750000000426201333210603300141760ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://www.rust-lang.org/COPYRIGHT. // // 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 ChaCha random number generator. use core::fmt; use rand_core::{CryptoRng, RngCore, SeedableRng, Error, le}; use rand_core::block::{BlockRngCore, BlockRng}; const SEED_WORDS: usize = 8; // 8 words for the 256-bit key const STATE_WORDS: usize = 16; /// A cryptographically secure random number generator that uses the ChaCha /// algorithm. /// /// ChaCha is a stream cipher designed by Daniel J. Bernstein [^1], that we use /// as an RNG. It is an improved variant of the Salsa20 cipher family, which was /// selected as one of the "stream ciphers suitable for widespread adoption" by /// eSTREAM [^2]. /// /// ChaCha uses add-rotate-xor (ARX) operations as its basis. These are safe /// against timing attacks, although that is mostly a concern for ciphers and /// not for RNGs. Also it is very suitable for SIMD implementation. /// Here we do not provide a SIMD implementation yet, except for what is /// provided by auto-vectorisation. /// /// With the ChaCha algorithm it is possible to choose the number of rounds the /// core algorithm should run. The number of rounds is a tradeoff between /// performance and security, where 8 rounds is the minimum potentially /// secure configuration, and 20 rounds is widely used as a conservative choice. /// We use 20 rounds in this implementation, but hope to allow type-level /// configuration in the future. /// /// We use a 64-bit counter and 64-bit stream identifier as in Benstein's /// implementation [^1] except that we use a stream identifier in place of a /// nonce. A 64-bit counter over 64-byte (16 word) blocks allows 1 ZiB of output /// before cycling, and the stream identifier allows 264 unique /// streams of output per seed. Both counter and stream are initialized to zero /// but may be set via [`set_word_pos`] and [`set_stream`]. /// /// The word layout is: /// /// ```text /// constant constant constant constant /// seed seed seed seed /// seed seed seed seed /// counter counter nonce nonce /// ``` /// /// This implementation uses an output buffer of sixteen `u32` words, and uses /// [`BlockRng`] to implement the [`RngCore`] methods. /// /// [^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( /// https://cr.yp.to/chacha.html) /// /// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( /// http://www.ecrypt.eu.org/stream/) /// /// [`set_word_pos`]: #method.set_word_pos /// [`set_stream`]: #method.set_stream /// [`BlockRng`]: ../../../rand_core/block/struct.BlockRng.html /// [`RngCore`]: ../../trait.RngCore.html #[derive(Clone, Debug)] pub struct ChaChaRng(BlockRng); impl RngCore for ChaChaRng { #[inline] fn next_u32(&mut self) -> u32 { self.0.next_u32() } #[inline] fn next_u64(&mut self) -> u64 { self.0.next_u64() } #[inline] fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest) } #[inline] fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.0.try_fill_bytes(dest) } } impl SeedableRng for ChaChaRng { type Seed = ::Seed; fn from_seed(seed: Self::Seed) -> Self { ChaChaRng(BlockRng::::from_seed(seed)) } fn from_rng(rng: R) -> Result { BlockRng::::from_rng(rng).map(ChaChaRng) } } impl CryptoRng for ChaChaRng {} impl ChaChaRng { /// Create an ChaCha random number generator using the default /// fixed key of 8 zero words. /// /// # Examples /// /// ``` /// # #![allow(deprecated)] /// use rand::{RngCore, ChaChaRng}; /// /// let mut ra = ChaChaRng::new_unseeded(); /// println!("{:?}", ra.next_u32()); /// println!("{:?}", ra.next_u32()); /// ``` /// /// Since this equivalent to a RNG with a fixed seed, repeated executions /// of an unseeded RNG will produce the same result. This code sample will /// consistently produce: /// /// - 2917185654 /// - 2419978656 #[deprecated(since="0.5.0", note="use the FromEntropy or SeedableRng trait")] pub fn new_unseeded() -> ChaChaRng { ChaChaRng::from_seed([0; SEED_WORDS*4]) } /// Get the offset from the start of the stream, in 32-bit words. /// /// Since the generated blocks are 16 words (24) long and the /// counter is 64-bits, the offset is a 68-bit number. Sub-word offsets are /// not supported, hence the result can simply be multiplied by 4 to get a /// byte-offset. /// /// Note: this function is currently only available when the `i128_support` /// feature is enabled. In the future this will be enabled by default. #[cfg(feature = "i128_support")] pub fn get_word_pos(&self) -> u128 { let mut c = (self.0.core.state[13] as u64) << 32 | (self.0.core.state[12] as u64); let mut index = self.0.index(); // c is the end of the last block generated, unless index is at end if index >= STATE_WORDS { index = 0; } else { c = c.wrapping_sub(1); } ((c as u128) << 4) | (index as u128) } /// Set the offset from the start of the stream, in 32-bit words. /// /// As with `get_word_pos`, we use a 68-bit number. Since the generator /// simply cycles at the end of its period (1 ZiB), we ignore the upper /// 60 bits. /// /// Note: this function is currently only available when the `i128_support` /// feature is enabled. In the future this will be enabled by default. #[cfg(feature = "i128_support")] pub fn set_word_pos(&mut self, word_offset: u128) { let index = (word_offset as usize) & 0xF; let counter = (word_offset >> 4) as u64; self.0.core.state[12] = counter as u32; self.0.core.state[13] = (counter >> 32) as u32; if index != 0 { self.0.generate_and_set(index); // also increments counter } else { self.0.reset(); } } /// Set the stream number. /// /// This is initialized to zero; 264 unique streams of output /// are available per seed/key. /// /// Note that in order to reproduce ChaCha output with a specific 64-bit /// nonce, one can convert that nonce to a `u64` in little-endian fashion /// and pass to this function. In theory a 96-bit nonce can be used by /// passing the last 64-bits to this function and using the first 32-bits as /// the most significant half of the 64-bit counter (which may be set /// indirectly via `set_word_pos`), but this is not directly supported. pub fn set_stream(&mut self, stream: u64) { let index = self.0.index(); self.0.core.state[14] = stream as u32; self.0.core.state[15] = (stream >> 32) as u32; if index < STATE_WORDS { // we need to regenerate a partial result buffer { // reverse of counter adjustment in generate() if self.0.core.state[12] == 0 { self.0.core.state[13] = self.0.core.state[13].wrapping_sub(1); } self.0.core.state[12] = self.0.core.state[12].wrapping_sub(1); } self.0.generate_and_set(index); } } } /// The core of `ChaChaRng`, used with `BlockRng`. #[derive(Clone)] pub struct ChaChaCore { state: [u32; STATE_WORDS], } // Custom Debug implementation that does not expose the internal state impl fmt::Debug for ChaChaCore { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ChaChaCore {{}}") } } macro_rules! quarter_round{ ($a: expr, $b: expr, $c: expr, $d: expr) => {{ $a = $a.wrapping_add($b); $d ^= $a; $d = $d.rotate_left(16); $c = $c.wrapping_add($d); $b ^= $c; $b = $b.rotate_left(12); $a = $a.wrapping_add($b); $d ^= $a; $d = $d.rotate_left( 8); $c = $c.wrapping_add($d); $b ^= $c; $b = $b.rotate_left( 7); }} } macro_rules! double_round{ ($x: expr) => {{ // Column round quarter_round!($x[ 0], $x[ 4], $x[ 8], $x[12]); quarter_round!($x[ 1], $x[ 5], $x[ 9], $x[13]); quarter_round!($x[ 2], $x[ 6], $x[10], $x[14]); quarter_round!($x[ 3], $x[ 7], $x[11], $x[15]); // Diagonal round quarter_round!($x[ 0], $x[ 5], $x[10], $x[15]); quarter_round!($x[ 1], $x[ 6], $x[11], $x[12]); quarter_round!($x[ 2], $x[ 7], $x[ 8], $x[13]); quarter_round!($x[ 3], $x[ 4], $x[ 9], $x[14]); }} } impl BlockRngCore for ChaChaCore { type Item = u32; type Results = [u32; STATE_WORDS]; fn generate(&mut self, results: &mut Self::Results) { // For some reason extracting this part into a separate function // improves performance by 50%. fn core(results: &mut [u32; STATE_WORDS], state: &[u32; STATE_WORDS]) { let mut tmp = *state; let rounds = 20; for _ in 0..rounds / 2 { double_round!(tmp); } for i in 0..STATE_WORDS { results[i] = tmp[i].wrapping_add(state[i]); } } core(results, &self.state); // update 64-bit counter self.state[12] = self.state[12].wrapping_add(1); if self.state[12] != 0 { return; }; self.state[13] = self.state[13].wrapping_add(1); } } impl SeedableRng for ChaChaCore { type Seed = [u8; SEED_WORDS*4]; fn from_seed(seed: Self::Seed) -> Self { let mut seed_le = [0u32; SEED_WORDS]; le::read_u32_into(&seed, &mut seed_le); Self { state: [0x61707865, 0x3320646E, 0x79622D32, 0x6B206574, // constants seed_le[0], seed_le[1], seed_le[2], seed_le[3], // seed seed_le[4], seed_le[5], seed_le[6], seed_le[7], // seed 0, 0, 0, 0], // counter } } } impl CryptoRng for ChaChaCore {} impl From for ChaChaRng { fn from(core: ChaChaCore) -> Self { ChaChaRng(BlockRng::new(core)) } } #[cfg(test)] mod test { use {RngCore, SeedableRng}; use super::ChaChaRng; #[test] fn test_chacha_construction() { let seed = [0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 3,0,0,0,0,0,0,0]; let mut rng1 = ChaChaRng::from_seed(seed); assert_eq!(rng1.next_u32(), 137206642); let mut rng2 = ChaChaRng::from_rng(rng1).unwrap(); assert_eq!(rng2.next_u32(), 1325750369); } #[test] fn test_chacha_true_values_a() { // Test vectors 1 and 2 from // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 let seed = [0u8; 32]; let mut rng = ChaChaRng::from_seed(seed); let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, 0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b, 0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8, 0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2]; assert_eq!(results, expected); for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, 0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32, 0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874, 0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b]; assert_eq!(results, expected); } #[test] fn test_chacha_true_values_b() { // Test vector 3 from // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 let seed = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; let mut rng = ChaChaRng::from_seed(seed); // Skip block 0 for _ in 0..16 { rng.next_u32(); } let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0x2452eb3a, 0x9249f8ec, 0x8d829d9b, 0xddd4ceb1, 0xe8252083, 0x60818b01, 0xf38422b8, 0x5aaa49c9, 0xbb00ca8e, 0xda3ba7b4, 0xc4b592d1, 0xfdf2732f, 0x4436274e, 0x2561b3c8, 0xebdd4aa6, 0xa0136c00]; assert_eq!(results, expected); } #[test] #[cfg(feature = "i128_support")] fn test_chacha_true_values_c() { // Test vector 4 from // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 let seed = [0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let expected = [0xfb4dd572, 0x4bc42ef1, 0xdf922636, 0x327f1394, 0xa78dea8f, 0x5e269039, 0xa1bebbc1, 0xcaf09aae, 0xa25ab213, 0x48a6b46c, 0x1b9d9bcb, 0x092c5be6, 0x546ca624, 0x1bec45d5, 0x87f47473, 0x96f0992e]; let expected_end = 3 * 16; let mut results = [0u32; 16]; // Test block 2 by skipping block 0 and 1 let mut rng1 = ChaChaRng::from_seed(seed); for _ in 0..32 { rng1.next_u32(); } for i in results.iter_mut() { *i = rng1.next_u32(); } assert_eq!(results, expected); assert_eq!(rng1.get_word_pos(), expected_end); // Test block 2 by using `set_word_pos` let mut rng2 = ChaChaRng::from_seed(seed); rng2.set_word_pos(2 * 16); for i in results.iter_mut() { *i = rng2.next_u32(); } assert_eq!(results, expected); assert_eq!(rng2.get_word_pos(), expected_end); // Test skipping behaviour with other types let mut buf = [0u8; 32]; rng2.fill_bytes(&mut buf[..]); assert_eq!(rng2.get_word_pos(), expected_end + 8); rng2.fill_bytes(&mut buf[0..25]); assert_eq!(rng2.get_word_pos(), expected_end + 15); rng2.next_u64(); assert_eq!(rng2.get_word_pos(), expected_end + 17); rng2.next_u32(); rng2.next_u64(); assert_eq!(rng2.get_word_pos(), expected_end + 20); rng2.fill_bytes(&mut buf[0..1]); assert_eq!(rng2.get_word_pos(), expected_end + 21); } #[test] fn test_chacha_multiple_blocks() { let seed = [0,0,0,0, 1,0,0,0, 2,0,0,0, 3,0,0,0, 4,0,0,0, 5,0,0,0, 6,0,0,0, 7,0,0,0]; let mut rng = ChaChaRng::from_seed(seed); // Store the 17*i-th 32-bit word, // i.e., the i-th word of the i-th 16-word block let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); for _ in 0..16 { rng.next_u32(); } } let expected = [0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, 0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384, 0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, 0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4]; assert_eq!(results, expected); } #[test] fn test_chacha_true_bytes() { let seed = [0u8; 32]; let mut rng = ChaChaRng::from_seed(seed); let mut results = [0u8; 32]; rng.fill_bytes(&mut results); let expected = [118, 184, 224, 173, 160, 241, 61, 144, 64, 93, 106, 229, 83, 134, 189, 40, 189, 210, 25, 184, 160, 141, 237, 26, 168, 54, 239, 204, 139, 119, 13, 199]; assert_eq!(results, expected); } #[test] fn test_chacha_nonce() { // Test vector 5 from // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 // Although we do not support setting a nonce, we try it here anyway so // we can use this test vector. let seed = [0u8; 32]; let mut rng = ChaChaRng::from_seed(seed); // 96-bit nonce in LE order is: 0,0,0,0, 0,0,0,0, 0,0,0,2 rng.set_stream(2u64 << (24 + 32)); let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0x374dc6c2, 0x3736d58c, 0xb904e24a, 0xcd3f93ef, 0x88228b1a, 0x96a4dfb3, 0x5b76ab72, 0xc727ee54, 0x0e0e978a, 0xf3145c95, 0x1b748ea8, 0xf786c297, 0x99c28f5f, 0x628314e8, 0x398a19fa, 0x6ded1b53]; assert_eq!(results, expected); } #[test] fn test_chacha_clone_streams() { let seed = [0,0,0,0, 1,0,0,0, 2,0,0,0, 3,0,0,0, 4,0,0,0, 5,0,0,0, 6,0,0,0, 7,0,0,0]; let mut rng = ChaChaRng::from_seed(seed); let mut clone = rng.clone(); for _ in 0..16 { assert_eq!(rng.next_u64(), clone.next_u64()); } rng.set_stream(51); for _ in 0..7 { assert!(rng.next_u32() != clone.next_u32()); } clone.set_stream(51); // switch part way through block for _ in 7..16 { assert_eq!(rng.next_u32(), clone.next_u32()); } } } rand-0.5.5/src/prng/hc128.rs010064400017500001750000000473021332655332100136270ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://www.rust-lang.org/COPYRIGHT. // // 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 HC-128 random number generator. use core::fmt; use rand_core::{CryptoRng, RngCore, SeedableRng, Error, le}; use rand_core::block::{BlockRngCore, BlockRng}; const SEED_WORDS: usize = 8; // 128 bit key followed by 128 bit iv /// A cryptographically secure random number generator that uses the HC-128 /// algorithm. /// /// HC-128 is a stream cipher designed by Hongjun Wu[^1], that we use as an /// RNG. It is selected as one of the "stream ciphers suitable for widespread /// adoption" by eSTREAM[^2]. /// /// HC-128 is an array based RNG. In this it is similar to RC-4 and ISAAC before /// it, but those have never been proven cryptographically secure (or have even /// been significantly compromised, as in the case of RC-4[^5]). /// /// Because HC-128 works with simple indexing into a large array and with a few /// operations that parallelize well, it has very good performance. The size of /// the array it needs, 4kb, can however be a disadvantage. /// /// This implementation is not based on the version of HC-128 submitted to the /// eSTREAM contest, but on a later version by the author with a few small /// improvements from December 15, 2009[^3]. /// /// HC-128 has no known weaknesses that are easier to exploit than doing a /// brute-force search of 2128. A very comprehensive analysis of the /// current state of known attacks / weaknesses of HC-128 is given in *Some /// Results On Analysis And Implementation Of HC-128 Stream Cipher*[^4]. /// /// The average cycle length is expected to be /// 21024*32+10-1 = 232777. /// We support seeding with a 256-bit array, which matches the 128-bit key /// concatenated with a 128-bit IV from the stream cipher. /// /// This implementation uses an output buffer of sixteen `u32` words, and uses /// [`BlockRng`] to implement the [`RngCore`] methods. /// /// ## References /// [^1]: Hongjun Wu (2008). ["The Stream Cipher HC-128"]( /// http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf). /// *The eSTREAM Finalists*, LNCS 4986, pp. 39–47, Springer-Verlag. /// /// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( /// http://www.ecrypt.eu.org/stream/) /// /// [^3]: Hongjun Wu, [Stream Ciphers HC-128 and HC-256]( /// https://www.ntu.edu.sg/home/wuhj/research/hc/index.html) /// /// [^4]: Shashwat Raizada (January 2015),["Some Results On Analysis And /// Implementation Of HC-128 Stream Cipher"]( /// http://library.isical.ac.in:8080/jspui/bitstream/123456789/6636/1/TH431.pdf). /// /// [^5]: Internet Engineering Task Force (February 2015), /// ["Prohibiting RC4 Cipher Suites"](https://tools.ietf.org/html/rfc7465). /// /// [`BlockRng`]: ../../../rand_core/block/struct.BlockRng.html /// [`RngCore`]: ../../trait.RngCore.html #[derive(Clone, Debug)] pub struct Hc128Rng(BlockRng); impl RngCore for Hc128Rng { #[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 SeedableRng for Hc128Rng { type Seed = ::Seed; fn from_seed(seed: Self::Seed) -> Self { Hc128Rng(BlockRng::::from_seed(seed)) } fn from_rng(rng: R) -> Result { BlockRng::::from_rng(rng).map(Hc128Rng) } } impl CryptoRng for Hc128Rng {} /// The core of `Hc128Rng`, used with `BlockRng`. #[derive(Clone)] pub struct Hc128Core { t: [u32; 1024], counter1024: usize, } // Custom Debug implementation that does not expose the internal state impl fmt::Debug for Hc128Core { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Hc128Core {{}}") } } impl BlockRngCore for Hc128Core { type Item = u32; type Results = [u32; 16]; fn generate(&mut self, results: &mut Self::Results) { assert!(self.counter1024 % 16 == 0); let cc = self.counter1024 % 512; let dd = (cc + 16) % 512; let ee = cc.wrapping_sub(16) % 512; if self.counter1024 & 512 == 0 { // P block results[0] = self.step_p(cc+0, cc+1, ee+13, ee+6, ee+4); results[1] = self.step_p(cc+1, cc+2, ee+14, ee+7, ee+5); results[2] = self.step_p(cc+2, cc+3, ee+15, ee+8, ee+6); results[3] = self.step_p(cc+3, cc+4, cc+0, ee+9, ee+7); results[4] = self.step_p(cc+4, cc+5, cc+1, ee+10, ee+8); results[5] = self.step_p(cc+5, cc+6, cc+2, ee+11, ee+9); results[6] = self.step_p(cc+6, cc+7, cc+3, ee+12, ee+10); results[7] = self.step_p(cc+7, cc+8, cc+4, ee+13, ee+11); results[8] = self.step_p(cc+8, cc+9, cc+5, ee+14, ee+12); results[9] = self.step_p(cc+9, cc+10, cc+6, ee+15, ee+13); results[10] = self.step_p(cc+10, cc+11, cc+7, cc+0, ee+14); results[11] = self.step_p(cc+11, cc+12, cc+8, cc+1, ee+15); results[12] = self.step_p(cc+12, cc+13, cc+9, cc+2, cc+0); results[13] = self.step_p(cc+13, cc+14, cc+10, cc+3, cc+1); results[14] = self.step_p(cc+14, cc+15, cc+11, cc+4, cc+2); results[15] = self.step_p(cc+15, dd+0, cc+12, cc+5, cc+3); } else { // Q block results[0] = self.step_q(cc+0, cc+1, ee+13, ee+6, ee+4); results[1] = self.step_q(cc+1, cc+2, ee+14, ee+7, ee+5); results[2] = self.step_q(cc+2, cc+3, ee+15, ee+8, ee+6); results[3] = self.step_q(cc+3, cc+4, cc+0, ee+9, ee+7); results[4] = self.step_q(cc+4, cc+5, cc+1, ee+10, ee+8); results[5] = self.step_q(cc+5, cc+6, cc+2, ee+11, ee+9); results[6] = self.step_q(cc+6, cc+7, cc+3, ee+12, ee+10); results[7] = self.step_q(cc+7, cc+8, cc+4, ee+13, ee+11); results[8] = self.step_q(cc+8, cc+9, cc+5, ee+14, ee+12); results[9] = self.step_q(cc+9, cc+10, cc+6, ee+15, ee+13); results[10] = self.step_q(cc+10, cc+11, cc+7, cc+0, ee+14); results[11] = self.step_q(cc+11, cc+12, cc+8, cc+1, ee+15); results[12] = self.step_q(cc+12, cc+13, cc+9, cc+2, cc+0); results[13] = self.step_q(cc+13, cc+14, cc+10, cc+3, cc+1); results[14] = self.step_q(cc+14, cc+15, cc+11, cc+4, cc+2); results[15] = self.step_q(cc+15, dd+0, cc+12, cc+5, cc+3); } self.counter1024 = self.counter1024.wrapping_add(16); } } impl Hc128Core { // One step of HC-128, update P and generate 32 bits keystream #[inline(always)] fn step_p(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) -> u32 { let (p, q) = self.t.split_at_mut(512); // FIXME: it would be great if we the bounds checks here could be // optimized out, and we would not need unsafe. // This improves performance by about 7%. unsafe { let temp0 = p.get_unchecked(i511).rotate_right(23); let temp1 = p.get_unchecked(i3).rotate_right(10); let temp2 = p.get_unchecked(i10).rotate_right(8); *p.get_unchecked_mut(i) = p.get_unchecked(i) .wrapping_add(temp2) .wrapping_add(temp0 ^ temp1); let temp3 = { // The h1 function in HC-128 let a = *p.get_unchecked(i12) as u8; let c = (p.get_unchecked(i12) >> 16) as u8; q[a as usize].wrapping_add(q[256 + c as usize]) }; temp3 ^ p.get_unchecked(i) } } // One step of HC-128, update Q and generate 32 bits keystream // Similar to `step_p`, but `p` and `q` are swapped, and the rotates are to // the left instead of to the right. #[inline(always)] fn step_q(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) -> u32 { let (p, q) = self.t.split_at_mut(512); unsafe { let temp0 = q.get_unchecked(i511).rotate_left(23); let temp1 = q.get_unchecked(i3).rotate_left(10); let temp2 = q.get_unchecked(i10).rotate_left(8); *q.get_unchecked_mut(i) = q.get_unchecked(i) .wrapping_add(temp2) .wrapping_add(temp0 ^ temp1); let temp3 = { // The h2 function in HC-128 let a = *q.get_unchecked(i12) as u8; let c = (q.get_unchecked(i12) >> 16) as u8; p[a as usize].wrapping_add(p[256 + c as usize]) }; temp3 ^ q.get_unchecked(i) } } fn sixteen_steps(&mut self) { assert!(self.counter1024 % 16 == 0); let cc = self.counter1024 % 512; let dd = (cc + 16) % 512; let ee = cc.wrapping_sub(16) % 512; if self.counter1024 < 512 { // P block self.t[cc+0] = self.step_p(cc+0, cc+1, ee+13, ee+6, ee+4); self.t[cc+1] = self.step_p(cc+1, cc+2, ee+14, ee+7, ee+5); self.t[cc+2] = self.step_p(cc+2, cc+3, ee+15, ee+8, ee+6); self.t[cc+3] = self.step_p(cc+3, cc+4, cc+0, ee+9, ee+7); self.t[cc+4] = self.step_p(cc+4, cc+5, cc+1, ee+10, ee+8); self.t[cc+5] = self.step_p(cc+5, cc+6, cc+2, ee+11, ee+9); self.t[cc+6] = self.step_p(cc+6, cc+7, cc+3, ee+12, ee+10); self.t[cc+7] = self.step_p(cc+7, cc+8, cc+4, ee+13, ee+11); self.t[cc+8] = self.step_p(cc+8, cc+9, cc+5, ee+14, ee+12); self.t[cc+9] = self.step_p(cc+9, cc+10, cc+6, ee+15, ee+13); self.t[cc+10] = self.step_p(cc+10, cc+11, cc+7, cc+0, ee+14); self.t[cc+11] = self.step_p(cc+11, cc+12, cc+8, cc+1, ee+15); self.t[cc+12] = self.step_p(cc+12, cc+13, cc+9, cc+2, cc+0); self.t[cc+13] = self.step_p(cc+13, cc+14, cc+10, cc+3, cc+1); self.t[cc+14] = self.step_p(cc+14, cc+15, cc+11, cc+4, cc+2); self.t[cc+15] = self.step_p(cc+15, dd+0, cc+12, cc+5, cc+3); } else { // Q block self.t[cc+512+0] = self.step_q(cc+0, cc+1, ee+13, ee+6, ee+4); self.t[cc+512+1] = self.step_q(cc+1, cc+2, ee+14, ee+7, ee+5); self.t[cc+512+2] = self.step_q(cc+2, cc+3, ee+15, ee+8, ee+6); self.t[cc+512+3] = self.step_q(cc+3, cc+4, cc+0, ee+9, ee+7); self.t[cc+512+4] = self.step_q(cc+4, cc+5, cc+1, ee+10, ee+8); self.t[cc+512+5] = self.step_q(cc+5, cc+6, cc+2, ee+11, ee+9); self.t[cc+512+6] = self.step_q(cc+6, cc+7, cc+3, ee+12, ee+10); self.t[cc+512+7] = self.step_q(cc+7, cc+8, cc+4, ee+13, ee+11); self.t[cc+512+8] = self.step_q(cc+8, cc+9, cc+5, ee+14, ee+12); self.t[cc+512+9] = self.step_q(cc+9, cc+10, cc+6, ee+15, ee+13); self.t[cc+512+10] = self.step_q(cc+10, cc+11, cc+7, cc+0, ee+14); self.t[cc+512+11] = self.step_q(cc+11, cc+12, cc+8, cc+1, ee+15); self.t[cc+512+12] = self.step_q(cc+12, cc+13, cc+9, cc+2, cc+0); self.t[cc+512+13] = self.step_q(cc+13, cc+14, cc+10, cc+3, cc+1); self.t[cc+512+14] = self.step_q(cc+14, cc+15, cc+11, cc+4, cc+2); self.t[cc+512+15] = self.step_q(cc+15, dd+0, cc+12, cc+5, cc+3); } self.counter1024 += 16; } // Initialize an HC-128 random number generator. The seed has to be // 256 bits in length (`[u32; 8]`), matching the 128 bit `key` followed by // 128 bit `iv` when HC-128 where to be used as a stream cipher. fn init(seed: [u32; SEED_WORDS]) -> Self { #[inline] fn f1(x: u32) -> u32 { x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) } #[inline] fn f2(x: u32) -> u32 { x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) } let mut t = [0u32; 1024]; // Expand the key and iv into P and Q let (key, iv) = seed.split_at(4); t[..4].copy_from_slice(key); t[4..8].copy_from_slice(key); t[8..12].copy_from_slice(iv); t[12..16].copy_from_slice(iv); // Generate the 256 intermediate values W[16] ... W[256+16-1], and // copy the last 16 generated values to the start op P. for i in 16..256+16 { t[i] = f2(t[i-2]).wrapping_add(t[i-7]).wrapping_add(f1(t[i-15])) .wrapping_add(t[i-16]).wrapping_add(i as u32); } { let (p1, p2) = t.split_at_mut(256); p1[0..16].copy_from_slice(&p2[0..16]); } // Generate both the P and Q tables for i in 16..1024 { t[i] = f2(t[i-2]).wrapping_add(t[i-7]).wrapping_add(f1(t[i-15])) .wrapping_add(t[i-16]).wrapping_add(256 + i as u32); } let mut core = Self { t, counter1024: 0 }; // run the cipher 1024 steps for _ in 0..64 { core.sixteen_steps() }; core.counter1024 = 0; core } } impl SeedableRng for Hc128Core { type Seed = [u8; SEED_WORDS*4]; /// Create an HC-128 random number generator with a seed. The seed has to be /// 256 bits in length, matching the 128 bit `key` followed by 128 bit `iv` /// when HC-128 where to be used as a stream cipher. fn from_seed(seed: Self::Seed) -> Self { let mut seed_u32 = [0u32; SEED_WORDS]; le::read_u32_into(&seed, &mut seed_u32); Self::init(seed_u32) } } impl CryptoRng for Hc128Core {} #[cfg(test)] mod test { use {RngCore, SeedableRng}; use super::Hc128Rng; #[test] // Test vector 1 from the paper "The Stream Cipher HC-128" fn test_hc128_true_values_a() { let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0x73150082, 0x3bfd03a0, 0xfb2fd77f, 0xaa63af0e, 0xde122fc6, 0xa7dc29b6, 0x62a68527, 0x8b75ec68, 0x9036db1e, 0x81896005, 0x00ade078, 0x491fbf9a, 0x1cdc3013, 0x6c3d6e24, 0x90f664b2, 0x9cd57102]; assert_eq!(results, expected); } #[test] // Test vector 2 from the paper "The Stream Cipher HC-128" fn test_hc128_true_values_b() { let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0xc01893d5, 0xb7dbe958, 0x8f65ec98, 0x64176604, 0x36fc6724, 0xc82c6eec, 0x1b1c38a7, 0xc9b42a95, 0x323ef123, 0x0a6a908b, 0xce757b68, 0x9f14f7bb, 0xe4cde011, 0xaeb5173f, 0x89608c94, 0xb5cf46ca]; assert_eq!(results, expected); } #[test] // Test vector 3 from the paper "The Stream Cipher HC-128" fn test_hc128_true_values_c() { let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected = [0x518251a4, 0x04b4930a, 0xb02af931, 0x0639f032, 0xbcb4a47a, 0x5722480b, 0x2bf99f72, 0xcdc0e566, 0x310f0c56, 0xd3cc83e8, 0x663db8ef, 0x62dfe07f, 0x593e1790, 0xc5ceaa9c, 0xab03806f, 0xc9a6e5a0]; assert_eq!(results, expected); } #[test] fn test_hc128_true_values_u64() { let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u64; 8]; for i in results.iter_mut() { *i = rng.next_u64(); } let expected = [0x3bfd03a073150082, 0xaa63af0efb2fd77f, 0xa7dc29b6de122fc6, 0x8b75ec6862a68527, 0x818960059036db1e, 0x491fbf9a00ade078, 0x6c3d6e241cdc3013, 0x9cd5710290f664b2]; assert_eq!(results, expected); // The RNG operates in a P block of 512 results and next a Q block. // After skipping 2*800 u32 results we end up somewhere in the Q block // of the second round for _ in 0..800 { rng.next_u64(); } for i in results.iter_mut() { *i = rng.next_u64(); } let expected = [0xd8c4d6ca84d0fc10, 0xf16a5d91dc66e8e7, 0xd800de5bc37a8653, 0x7bae1f88c0dfbb4c, 0x3bfe1f374e6d4d14, 0x424b55676be3fa06, 0xe3a1e8758cbff579, 0x417f7198c5652bcd]; assert_eq!(results, expected); } #[test] fn test_hc128_true_values_bytes() { let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let expected = [0x31, 0xf9, 0x2a, 0xb0, 0x32, 0xf0, 0x39, 0x06, 0x7a, 0xa4, 0xb4, 0xbc, 0x0b, 0x48, 0x22, 0x57, 0x72, 0x9f, 0xf9, 0x2b, 0x66, 0xe5, 0xc0, 0xcd, 0x56, 0x0c, 0x0f, 0x31, 0xe8, 0x83, 0xcc, 0xd3, 0xef, 0xb8, 0x3d, 0x66, 0x7f, 0xe0, 0xdf, 0x62, 0x90, 0x17, 0x3e, 0x59, 0x9c, 0xaa, 0xce, 0xc5, 0x6f, 0x80, 0x03, 0xab, 0xa0, 0xe5, 0xa6, 0xc9, 0x60, 0x95, 0x84, 0x7a, 0xa5, 0x68, 0x5a, 0x84, 0xea, 0xd5, 0xf3, 0xea, 0x73, 0xa9, 0xad, 0x01, 0x79, 0x7d, 0xbe, 0x9f, 0xea, 0xe3, 0xf9, 0x74, 0x0e, 0xda, 0x2f, 0xa0, 0xe4, 0x7b, 0x4b, 0x1b, 0xdd, 0x17, 0x69, 0x4a, 0xfe, 0x9f, 0x56, 0x95, 0xad, 0x83, 0x6b, 0x9d, 0x60, 0xa1, 0x99, 0x96, 0x90, 0x00, 0x66, 0x7f, 0xfa, 0x7e, 0x65, 0xe9, 0xac, 0x8b, 0x92, 0x34, 0x77, 0xb4, 0x23, 0xd0, 0xb9, 0xab, 0xb1, 0x47, 0x7d, 0x4a, 0x13, 0x0a]; // Pick a somewhat large buffer so we can test filling with the // remainder from `state.results`, directly filling the buffer, and // filling the remainder of the buffer. let mut buffer = [0u8; 16*4*2]; // Consume a value so that we have a remainder. assert!(rng.next_u64() == 0x04b4930a518251a4); rng.fill_bytes(&mut buffer); // [u8; 128] doesn't implement PartialEq assert_eq!(buffer.len(), expected.len()); for (b, e) in buffer.iter().zip(expected.iter()) { assert_eq!(b, e); } } #[test] fn test_hc128_clone() { let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng1 = Hc128Rng::from_seed(seed); let mut rng2 = rng1.clone(); for _ in 0..16 { assert_eq!(rng1.next_u32(), rng2.next_u32()); } } } rand-0.5.5/src/prng/isaac.rs010064400017500001750000000445631333210603300140570ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 ISAAC random number generator. use core::{fmt, slice}; use core::num::Wrapping as w; use rand_core::{RngCore, SeedableRng, Error, le}; use rand_core::block::{BlockRngCore, BlockRng}; use prng::isaac_array::IsaacArray; #[allow(non_camel_case_types)] type w32 = w; const RAND_SIZE_LEN: usize = 8; const RAND_SIZE: usize = 1 << RAND_SIZE_LEN; /// A random number generator that uses the ISAAC algorithm. /// /// ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are /// the principal bitwise operations employed. It is the most advanced of a /// series of array based random number generator designed by Robert Jenkins /// in 1996[^1][^2]. /// /// ISAAC is notably fast and produces excellent quality random numbers for /// non-cryptographic applications. /// /// In spite of being designed with cryptographic security in mind, ISAAC hasn't /// been stringently cryptanalyzed and thus cryptographers do not not /// consensually trust it to be secure. When looking for a secure RNG, prefer /// [`Hc128Rng`] instead, which, like ISAAC, is an array-based RNG and one of /// the stream-ciphers selected the by eSTREAM contest. /// /// In 2006 an improvement to ISAAC was suggested by Jean-Philippe Aumasson, /// named ISAAC+[^3]. But because the specification is not complete, because /// there is no good implementation, and because the suggested bias may not /// exist, it is not implemented here. /// /// ## Overview of the ISAAC algorithm: /// (in pseudo-code) /// /// ```text /// Input: a, b, c, s[256] // state /// Output: r[256] // results /// /// mix(a,i) = a ^ a << 13 if i = 0 mod 4 /// a ^ a >> 6 if i = 1 mod 4 /// a ^ a << 2 if i = 2 mod 4 /// a ^ a >> 16 if i = 3 mod 4 /// /// c = c + 1 /// b = b + c /// /// for i in 0..256 { /// x = s_[i] /// a = f(a,i) + s[i+128 mod 256] /// y = a + b + s[x>>2 mod 256] /// s[i] = y /// b = x + s[y>>10 mod 256] /// r[i] = b /// } /// ``` /// /// Numbers are generated in blocks of 256. This means the function above only /// runs once every 256 times you ask for a next random number. In all other /// circumstances the last element of the results array is returned. /// /// ISAAC therefore needs a lot of memory, relative to other non-crypto RNGs. /// 2 * 256 * 4 = 2 kb to hold the state and results. /// /// This implementation uses [`BlockRng`] to implement the [`RngCore`] methods. /// /// ## References /// [^1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number generator*]( /// http://burtleburtle.net/bob/rand/isaacafa.html) /// /// [^2]: Bob Jenkins, [*ISAAC and RC4*]( /// http://burtleburtle.net/bob/rand/isaac.html) /// /// [^3]: Jean-Philippe Aumasson, [*On the pseudo-random generator ISAAC*]( /// https://eprint.iacr.org/2006/438) /// /// [`Hc128Rng`]: ../hc128/struct.Hc128Rng.html /// [`BlockRng`]: ../../../rand_core/block/struct.BlockRng.html /// [`RngCore`]: ../../trait.RngCore.html #[derive(Clone, Debug)] #[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] pub struct IsaacRng(BlockRng); impl RngCore for IsaacRng { #[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 SeedableRng for IsaacRng { type Seed = ::Seed; fn from_seed(seed: Self::Seed) -> Self { IsaacRng(BlockRng::::from_seed(seed)) } fn from_rng(rng: S) -> Result { BlockRng::::from_rng(rng).map(|rng| IsaacRng(rng)) } } impl IsaacRng { /// Create an ISAAC random number generator using the default /// fixed seed. /// /// DEPRECATED. `IsaacRng::new_from_u64(0)` will produce identical results. #[deprecated(since="0.5.0", note="use the FromEntropy or SeedableRng trait")] pub fn new_unseeded() -> Self { Self::new_from_u64(0) } /// Create an ISAAC random number generator using an `u64` as seed. /// If `seed == 0` this will produce the same stream of random numbers as /// the reference implementation when used unseeded. pub fn new_from_u64(seed: u64) -> Self { IsaacRng(BlockRng::new(IsaacCore::new_from_u64(seed))) } } /// The core of `IsaacRng`, used with `BlockRng`. #[derive(Clone)] #[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] pub struct IsaacCore { #[cfg_attr(feature="serde1",serde(with="super::isaac_array::isaac_array_serde"))] mem: [w32; RAND_SIZE], a: w32, b: w32, c: w32, } // Custom Debug implementation that does not expose the internal state impl fmt::Debug for IsaacCore { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "IsaacCore {{}}") } } impl BlockRngCore for IsaacCore { type Item = u32; type Results = IsaacArray; /// Refills the output buffer, `results`. See also the pseudocode desciption /// of the algorithm in the [`IsaacRng`] documentation. /// /// Optimisations used (similar to the reference implementation): /// /// - The loop is unrolled 4 times, once for every constant of mix(). /// - The contents of the main loop are moved to a function `rngstep`, to /// reduce code duplication. /// - We use local variables for a and b, which helps with optimisations. /// - We split the main loop in two, one that operates over 0..128 and one /// over 128..256. This way we can optimise out the addition and modulus /// from `s[i+128 mod 256]`. /// - We maintain one index `i` and add `m` or `m2` as base (m2 for the /// `s[i+128 mod 256]`), relying on the optimizer to turn it into pointer /// arithmetic. /// - We fill `results` backwards. The reference implementation reads values /// from `results` in reverse. We read them in the normal direction, to /// make `fill_bytes` a memcopy. To maintain compatibility we fill in /// reverse. /// /// [`IsaacRng`]: struct.IsaacRng.html fn generate(&mut self, results: &mut IsaacArray) { self.c += w(1); // abbreviations let mut a = self.a; let mut b = self.b + self.c; const MIDPOINT: usize = RAND_SIZE / 2; #[inline] fn ind(mem:&[w32; RAND_SIZE], v: w32, amount: usize) -> w32 { let index = (v >> amount).0 as usize % RAND_SIZE; mem[index] } #[inline] fn rngstep(mem: &mut [w32; RAND_SIZE], results: &mut [u32; RAND_SIZE], mix: w32, a: &mut w32, b: &mut w32, base: usize, m: usize, m2: usize) { let x = mem[base + m]; *a = mix + mem[base + m2]; let y = *a + *b + ind(&mem, x, 2); mem[base + m] = y; *b = x + ind(&mem, y, 2 + RAND_SIZE_LEN); results[RAND_SIZE - 1 - base - m] = (*b).0; } let mut m = 0; let mut m2 = MIDPOINT; for i in (0..MIDPOINT/4).map(|i| i * 4) { rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 6 ), &mut a, &mut b, i + 1, m, m2); rngstep(&mut self.mem, results, a ^ (a << 2 ), &mut a, &mut b, i + 2, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 16), &mut a, &mut b, i + 3, m, m2); } m = MIDPOINT; m2 = 0; for i in (0..MIDPOINT/4).map(|i| i * 4) { rngstep(&mut self.mem, results, a ^ (a << 13), &mut a, &mut b, i + 0, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 6 ), &mut a, &mut b, i + 1, m, m2); rngstep(&mut self.mem, results, a ^ (a << 2 ), &mut a, &mut b, i + 2, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 16), &mut a, &mut b, i + 3, m, m2); } self.a = a; self.b = b; } } impl IsaacCore { /// Create a new ISAAC random number generator. /// /// The author Bob Jenkins describes how to best initialize ISAAC here: /// /// The answer is included here just in case: /// /// "No, you don't need a full 8192 bits of seed data. Normal key sizes will /// do fine, and they should have their expected strength (eg a 40-bit key /// will take as much time to brute force as 40-bit keys usually will). You /// could fill the remainder with 0, but set the last array element to the /// length of the key provided (to distinguish keys that differ only by /// different amounts of 0 padding). You do still need to call `randinit()` /// to make sure the initial state isn't uniform-looking." /// "After publishing ISAAC, I wanted to limit the key to half the size of /// `r[]`, and repeat it twice. That would have made it hard to provide a /// key that sets the whole internal state to anything convenient. But I'd /// already published it." /// /// And his answer to the question "For my code, would repeating the key /// over and over to fill 256 integers be a better solution than /// zero-filling, or would they essentially be the same?": /// "If the seed is under 32 bytes, they're essentially the same, otherwise /// repeating the seed would be stronger. randinit() takes a chunk of 32 /// bytes, mixes it, and combines that with the next 32 bytes, et cetera. /// Then loops over all the elements the same way a second time." #[inline] fn init(mut mem: [w32; RAND_SIZE], rounds: u32) -> Self { fn mix(a: &mut w32, b: &mut w32, c: &mut w32, d: &mut w32, e: &mut w32, f: &mut w32, g: &mut w32, h: &mut w32) { *a ^= *b << 11; *d += *a; *b += *c; *b ^= *c >> 2; *e += *b; *c += *d; *c ^= *d << 8; *f += *c; *d += *e; *d ^= *e >> 16; *g += *d; *e += *f; *e ^= *f << 10; *h += *e; *f += *g; *f ^= *g >> 4; *a += *f; *g += *h; *g ^= *h << 8; *b += *g; *h += *a; *h ^= *a >> 9; *c += *h; *a += *b; } // These numbers are the result of initializing a...h with the // fractional part of the golden ratio in binary (0x9e3779b9) // and applying mix() 4 times. let mut a = w(0x1367df5a); let mut b = w(0x95d90059); let mut c = w(0xc3163e4b); let mut d = w(0x0f421ad8); let mut e = w(0xd92a4a78); let mut f = w(0xa51a3c49); let mut g = w(0xc4efea1b); let mut h = w(0x30609119); // Normally this should do two passes, to make all of the seed effect // all of `mem` for _ in 0..rounds { for i in (0..RAND_SIZE/8).map(|i| i * 8) { a += mem[i ]; b += mem[i+1]; c += mem[i+2]; d += mem[i+3]; e += mem[i+4]; f += mem[i+5]; g += mem[i+6]; h += mem[i+7]; mix(&mut a, &mut b, &mut c, &mut d, &mut e, &mut f, &mut g, &mut h); mem[i ] = a; mem[i+1] = b; mem[i+2] = c; mem[i+3] = d; mem[i+4] = e; mem[i+5] = f; mem[i+6] = g; mem[i+7] = h; } } Self { mem, a: w(0), b: w(0), c: w(0) } } /// Create an ISAAC random number generator using an `u64` as seed. /// If `seed == 0` this will produce the same stream of random numbers as /// the reference implementation when used unseeded. fn new_from_u64(seed: u64) -> Self { let mut key = [w(0); RAND_SIZE]; key[0] = w(seed as u32); key[1] = w((seed >> 32) as u32); // Initialize with only one pass. // A second pass does not improve the quality here, because all of the // seed was already available in the first round. // Not doing the second pass has the small advantage that if // `seed == 0` this method produces exactly the same state as the // reference implementation when used unseeded. Self::init(key, 1) } } impl SeedableRng for IsaacCore { type Seed = [u8; 32]; fn from_seed(seed: Self::Seed) -> Self { let mut seed_u32 = [0u32; 8]; le::read_u32_into(&seed, &mut seed_u32); // Convert the seed to `Wrapping` and zero-extend to `RAND_SIZE`. let mut seed_extended = [w(0); RAND_SIZE]; for (x, y) in seed_extended.iter_mut().zip(seed_u32.iter()) { *x = w(*y); } Self::init(seed_extended, 2) } fn from_rng(mut rng: R) -> Result { // Custom `from_rng` implementation that fills a seed with the same size // as the entire state. let mut seed = [w(0u32); RAND_SIZE]; unsafe { let ptr = seed.as_mut_ptr() as *mut u8; let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 4); rng.try_fill_bytes(slice)?; } for i in seed.iter_mut() { *i = w(i.0.to_le()); } Ok(Self::init(seed, 2)) } } #[cfg(test)] mod test { use {RngCore, SeedableRng}; use super::IsaacRng; #[test] fn test_isaac_construction() { // Test that various construction techniques produce a working RNG. 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]; let mut rng1 = IsaacRng::from_seed(seed); assert_eq!(rng1.next_u32(), 2869442790); let mut rng2 = IsaacRng::from_rng(rng1).unwrap(); assert_eq!(rng2.next_u32(), 3094074039); } #[test] fn test_isaac_true_values_32() { let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng1 = IsaacRng::from_seed(seed); let mut results = [0u32; 10]; for i in results.iter_mut() { *i = rng1.next_u32(); } let expected = [ 2558573138, 873787463, 263499565, 2103644246, 3595684709, 4203127393, 264982119, 2765226902, 2737944514, 3900253796]; assert_eq!(results, expected); let seed = [57,48,0,0, 50,9,1,0, 49,212,0,0, 148,38,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng2 = IsaacRng::from_seed(seed); // skip forward to the 10000th number for _ in 0..10000 { rng2.next_u32(); } for i in results.iter_mut() { *i = rng2.next_u32(); } let expected = [ 3676831399, 3183332890, 2834741178, 3854698763, 2717568474, 1576568959, 3507990155, 179069555, 141456972, 2478885421]; assert_eq!(results, expected); } #[test] fn test_isaac_true_values_64() { // As above, using little-endian versions of above values let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng = IsaacRng::from_seed(seed); let mut results = [0u64; 5]; for i in results.iter_mut() { *i = rng.next_u64(); } let expected = [ 3752888579798383186, 9035083239252078381,18052294697452424037, 11876559110374379111, 16751462502657800130]; assert_eq!(results, expected); } #[test] fn test_isaac_true_bytes() { let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng = IsaacRng::from_seed(seed); let mut results = [0u8; 32]; rng.fill_bytes(&mut results); // Same as first values in test_isaac_true_values as bytes in LE order let expected = [82, 186, 128, 152, 71, 240, 20, 52, 45, 175, 180, 15, 86, 16, 99, 125, 101, 203, 81, 214, 97, 162, 134, 250, 103, 78, 203, 15, 150, 3, 210, 164]; assert_eq!(results, expected); } #[test] fn test_isaac_new_uninitialized() { // Compare the results from initializing `IsaacRng` with // `new_from_u64(0)`, to make sure it is the same as the reference // implementation when used uninitialized. // Note: We only test the first 16 integers, not the full 256 of the // first block. let mut rng = IsaacRng::new_from_u64(0); let mut results = [0u32; 16]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected: [u32; 16] = [ 0x71D71FD2, 0xB54ADAE7, 0xD4788559, 0xC36129FA, 0x21DC1EA9, 0x3CB879CA, 0xD83B237F, 0xFA3CE5BD, 0x8D048509, 0xD82E9489, 0xDB452848, 0xCA20E846, 0x500F972E, 0x0EEFF940, 0x00D6B993, 0xBC12C17F]; assert_eq!(results, expected); } #[test] fn test_isaac_clone() { let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng1 = IsaacRng::from_seed(seed); let mut rng2 = rng1.clone(); for _ in 0..16 { assert_eq!(rng1.next_u32(), rng2.next_u32()); } } #[test] #[cfg(all(feature="serde1", feature="std"))] fn test_isaac_serde() { use bincode; use std::io::{BufWriter, BufReader}; let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng = IsaacRng::from_seed(seed); let buf: Vec = Vec::new(); let mut buf = BufWriter::new(buf); bincode::serialize_into(&mut buf, &rng).expect("Could not serialize"); let buf = buf.into_inner().unwrap(); let mut read = BufReader::new(&buf[..]); let mut deserialized: IsaacRng = bincode::deserialize_from(&mut read).expect("Could not deserialize"); for _ in 0..300 { // more than the 256 buffered results assert_eq!(rng.next_u32(), deserialized.next_u32()); } } } rand-0.5.5/src/prng/isaac64.rs010064400017500001750000000436301333210603300142230ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 ISAAC-64 random number generator. use core::{fmt, slice}; use core::num::Wrapping as w; use rand_core::{RngCore, SeedableRng, Error, le}; use rand_core::block::{BlockRngCore, BlockRng64}; use prng::isaac_array::IsaacArray; #[allow(non_camel_case_types)] type w64 = w; const RAND_SIZE_LEN: usize = 8; const RAND_SIZE: usize = 1 << RAND_SIZE_LEN; /// A random number generator that uses ISAAC-64, the 64-bit variant of the /// ISAAC algorithm. /// /// ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are /// the principal bitwise operations employed. It is the most advanced of a /// series of array based random number generator designed by Robert Jenkins /// in 1996[^1]. /// /// ISAAC-64 is mostly similar to ISAAC. Because it operates on 64-bit integers /// instead of 32-bit, it uses twice as much memory to hold its state and /// results. Also it uses different constants for shifts and indirect indexing, /// optimized to give good results for 64bit arithmetic. /// /// ISAAC-64 is notably fast and produces excellent quality random numbers for /// non-cryptographic applications. /// /// In spite of being designed with cryptographic security in mind, ISAAC hasn't /// been stringently cryptanalyzed and thus cryptographers do not not /// consensually trust it to be secure. When looking for a secure RNG, prefer /// [`Hc128Rng`] instead, which, like ISAAC, is an array-based RNG and one of /// the stream-ciphers selected the by eSTREAM contest. /// /// ## Overview of the ISAAC-64 algorithm: /// (in pseudo-code) /// /// ```text /// Input: a, b, c, s[256] // state /// Output: r[256] // results /// /// mix(a,i) = !(a ^ a << 21) if i = 0 mod 4 /// a ^ a >> 5 if i = 1 mod 4 /// a ^ a << 12 if i = 2 mod 4 /// a ^ a >> 33 if i = 3 mod 4 /// /// c = c + 1 /// b = b + c /// /// for i in 0..256 { /// x = s_[i] /// a = mix(a,i) + s[i+128 mod 256] /// y = a + b + s[x>>3 mod 256] /// s[i] = y /// b = x + s[y>>11 mod 256] /// r[i] = b /// } /// ``` /// /// This implementation uses [`BlockRng64`] to implement the [`RngCore`] methods. /// /// See for more information the documentation of [`IsaacRng`]. /// /// [^1]: Bob Jenkins, [*ISAAC and RC4*]( /// http://burtleburtle.net/bob/rand/isaac.html) /// /// [`IsaacRng`]: ../isaac/struct.IsaacRng.html /// [`Hc128Rng`]: ../hc128/struct.Hc128Rng.html /// [`BlockRng64`]: ../../../rand_core/block/struct.BlockRng64.html /// [`RngCore`]: ../../trait.RngCore.html #[derive(Clone, Debug)] #[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] pub struct Isaac64Rng(BlockRng64); impl RngCore for Isaac64Rng { #[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 SeedableRng for Isaac64Rng { type Seed = ::Seed; fn from_seed(seed: Self::Seed) -> Self { Isaac64Rng(BlockRng64::::from_seed(seed)) } fn from_rng(rng: S) -> Result { BlockRng64::::from_rng(rng).map(|rng| Isaac64Rng(rng)) } } impl Isaac64Rng { /// Create a 64-bit ISAAC random number generator using the /// default fixed seed. /// /// DEPRECATED. `Isaac64Rng::new_from_u64(0)` will produce identical results. #[deprecated(since="0.5.0", note="use the FromEntropy or SeedableRng trait")] pub fn new_unseeded() -> Self { Self::new_from_u64(0) } /// Create an ISAAC-64 random number generator using an `u64` as seed. /// If `seed == 0` this will produce the same stream of random numbers as /// the reference implementation when used unseeded. pub fn new_from_u64(seed: u64) -> Self { Isaac64Rng(BlockRng64::new(Isaac64Core::new_from_u64(seed))) } } /// The core of `Isaac64Rng`, used with `BlockRng`. #[derive(Clone)] #[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] pub struct Isaac64Core { #[cfg_attr(feature="serde1",serde(with="super::isaac_array::isaac_array_serde"))] mem: [w64; RAND_SIZE], a: w64, b: w64, c: w64, } // Custom Debug implementation that does not expose the internal state impl fmt::Debug for Isaac64Core { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Isaac64Core {{}}") } } impl BlockRngCore for Isaac64Core { type Item = u64; type Results = IsaacArray; /// Refills the output buffer, `results`. See also the pseudocode desciption /// of the algorithm in the [`Isaac64Rng`] documentation. /// /// Optimisations used (similar to the reference implementation): /// /// - The loop is unrolled 4 times, once for every constant of mix(). /// - The contents of the main loop are moved to a function `rngstep`, to /// reduce code duplication. /// - We use local variables for a and b, which helps with optimisations. /// - We split the main loop in two, one that operates over 0..128 and one /// over 128..256. This way we can optimise out the addition and modulus /// from `s[i+128 mod 256]`. /// - We maintain one index `i` and add `m` or `m2` as base (m2 for the /// `s[i+128 mod 256]`), relying on the optimizer to turn it into pointer /// arithmetic. /// - We fill `results` backwards. The reference implementation reads values /// from `results` in reverse. We read them in the normal direction, to /// make `fill_bytes` a memcopy. To maintain compatibility we fill in /// reverse. /// /// [`Isaac64Rng`]: struct.Isaac64Rng.html fn generate(&mut self, results: &mut IsaacArray) { self.c += w(1); // abbreviations let mut a = self.a; let mut b = self.b + self.c; const MIDPOINT: usize = RAND_SIZE / 2; #[inline] fn ind(mem:&[w64; RAND_SIZE], v: w64, amount: usize) -> w64 { let index = (v >> amount).0 as usize % RAND_SIZE; mem[index] } #[inline] fn rngstep(mem: &mut [w64; RAND_SIZE], results: &mut [u64; RAND_SIZE], mix: w64, a: &mut w64, b: &mut w64, base: usize, m: usize, m2: usize) { let x = mem[base + m]; *a = mix + mem[base + m2]; let y = *a + *b + ind(&mem, x, 3); mem[base + m] = y; *b = x + ind(&mem, y, 3 + RAND_SIZE_LEN); results[RAND_SIZE - 1 - base - m] = (*b).0; } let mut m = 0; let mut m2 = MIDPOINT; for i in (0..MIDPOINT/4).map(|i| i * 4) { rngstep(&mut self.mem, results, !(a ^ (a << 21)), &mut a, &mut b, i + 0, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 5 ), &mut a, &mut b, i + 1, m, m2); rngstep(&mut self.mem, results, a ^ (a << 12), &mut a, &mut b, i + 2, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 33), &mut a, &mut b, i + 3, m, m2); } m = MIDPOINT; m2 = 0; for i in (0..MIDPOINT/4).map(|i| i * 4) { rngstep(&mut self.mem, results, !(a ^ (a << 21)), &mut a, &mut b, i + 0, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 5 ), &mut a, &mut b, i + 1, m, m2); rngstep(&mut self.mem, results, a ^ (a << 12), &mut a, &mut b, i + 2, m, m2); rngstep(&mut self.mem, results, a ^ (a >> 33), &mut a, &mut b, i + 3, m, m2); } self.a = a; self.b = b; } } impl Isaac64Core { /// Create a new ISAAC-64 random number generator. fn init(mut mem: [w64; RAND_SIZE], rounds: u32) -> Self { fn mix(a: &mut w64, b: &mut w64, c: &mut w64, d: &mut w64, e: &mut w64, f: &mut w64, g: &mut w64, h: &mut w64) { *a -= *e; *f ^= *h >> 9; *h += *a; *b -= *f; *g ^= *a << 9; *a += *b; *c -= *g; *h ^= *b >> 23; *b += *c; *d -= *h; *a ^= *c << 15; *c += *d; *e -= *a; *b ^= *d >> 14; *d += *e; *f -= *b; *c ^= *e << 20; *e += *f; *g -= *c; *d ^= *f >> 17; *f += *g; *h -= *d; *e ^= *g << 14; *g += *h; } // These numbers are the result of initializing a...h with the // fractional part of the golden ratio in binary (0x9e3779b97f4a7c13) // and applying mix() 4 times. let mut a = w(0x647c4677a2884b7c); let mut b = w(0xb9f8b322c73ac862); let mut c = w(0x8c0ea5053d4712a0); let mut d = w(0xb29b2e824a595524); let mut e = w(0x82f053db8355e0ce); let mut f = w(0x48fe4a0fa5a09315); let mut g = w(0xae985bf2cbfc89ed); let mut h = w(0x98f5704f6c44c0ab); // Normally this should do two passes, to make all of the seed effect // all of `mem` for _ in 0..rounds { for i in (0..RAND_SIZE/8).map(|i| i * 8) { a += mem[i ]; b += mem[i+1]; c += mem[i+2]; d += mem[i+3]; e += mem[i+4]; f += mem[i+5]; g += mem[i+6]; h += mem[i+7]; mix(&mut a, &mut b, &mut c, &mut d, &mut e, &mut f, &mut g, &mut h); mem[i ] = a; mem[i+1] = b; mem[i+2] = c; mem[i+3] = d; mem[i+4] = e; mem[i+5] = f; mem[i+6] = g; mem[i+7] = h; } } Self { mem, a: w(0), b: w(0), c: w(0) } } /// Create an ISAAC-64 random number generator using an `u64` as seed. /// If `seed == 0` this will produce the same stream of random numbers as /// the reference implementation when used unseeded. pub fn new_from_u64(seed: u64) -> Self { let mut key = [w(0); RAND_SIZE]; key[0] = w(seed); // Initialize with only one pass. // A second pass does not improve the quality here, because all of the // seed was already available in the first round. // Not doing the second pass has the small advantage that if // `seed == 0` this method produces exactly the same state as the // reference implementation when used unseeded. Self::init(key, 1) } } impl SeedableRng for Isaac64Core { type Seed = [u8; 32]; fn from_seed(seed: Self::Seed) -> Self { let mut seed_u64 = [0u64; 4]; le::read_u64_into(&seed, &mut seed_u64); // Convert the seed to `Wrapping` and zero-extend to `RAND_SIZE`. let mut seed_extended = [w(0); RAND_SIZE]; for (x, y) in seed_extended.iter_mut().zip(seed_u64.iter()) { *x = w(*y); } Self::init(seed_extended, 2) } fn from_rng(mut rng: R) -> Result { // Custom `from_rng` implementation that fills a seed with the same size // as the entire state. let mut seed = [w(0u64); RAND_SIZE]; unsafe { let ptr = seed.as_mut_ptr() as *mut u8; let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE * 8); rng.try_fill_bytes(slice)?; } for i in seed.iter_mut() { *i = w(i.0.to_le()); } Ok(Self::init(seed, 2)) } } #[cfg(test)] mod test { use {RngCore, SeedableRng}; use super::Isaac64Rng; #[test] fn test_isaac64_construction() { // Test that various construction techniques produce a working RNG. 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]; let mut rng1 = Isaac64Rng::from_seed(seed); assert_eq!(rng1.next_u64(), 14964555543728284049); let mut rng2 = Isaac64Rng::from_rng(rng1).unwrap(); assert_eq!(rng2.next_u64(), 919595328260451758); } #[test] fn test_isaac64_true_values_64() { let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0, 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0]; let mut rng1 = Isaac64Rng::from_seed(seed); let mut results = [0u64; 10]; for i in results.iter_mut() { *i = rng1.next_u64(); } let expected = [ 15071495833797886820, 7720185633435529318, 10836773366498097981, 5414053799617603544, 12890513357046278984, 17001051845652595546, 9240803642279356310, 12558996012687158051, 14673053937227185542, 1677046725350116783]; assert_eq!(results, expected); let seed = [57,48,0,0, 0,0,0,0, 50,9,1,0, 0,0,0,0, 49,212,0,0, 0,0,0,0, 148,38,0,0, 0,0,0,0]; let mut rng2 = Isaac64Rng::from_seed(seed); // skip forward to the 10000th number for _ in 0..10000 { rng2.next_u64(); } for i in results.iter_mut() { *i = rng2.next_u64(); } let expected = [ 18143823860592706164, 8491801882678285927, 2699425367717515619, 17196852593171130876, 2606123525235546165, 15790932315217671084, 596345674630742204, 9947027391921273664, 11788097613744130851, 10391409374914919106]; assert_eq!(results, expected); } #[test] fn test_isaac64_true_values_32() { let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0, 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0]; let mut rng = Isaac64Rng::from_seed(seed); let mut results = [0u32; 12]; for i in results.iter_mut() { *i = rng.next_u32(); } // Subset of above values, as an LE u32 sequence let expected = [ 3477963620, 3509106075, 687845478, 1797495790, 227048253, 2523132918, 4044335064, 1260557630, 4079741768, 3001306521, 69157722, 3958365844]; assert_eq!(results, expected); } #[test] fn test_isaac64_true_values_mixed() { let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0, 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0]; let mut rng = Isaac64Rng::from_seed(seed); // Test alternating between `next_u64` and `next_u32` works as expected. // Values are the same as `test_isaac64_true_values` and // `test_isaac64_true_values_32`. assert_eq!(rng.next_u64(), 15071495833797886820); assert_eq!(rng.next_u32(), 687845478); assert_eq!(rng.next_u32(), 1797495790); assert_eq!(rng.next_u64(), 10836773366498097981); assert_eq!(rng.next_u32(), 4044335064); // Skip one u32 assert_eq!(rng.next_u64(), 12890513357046278984); assert_eq!(rng.next_u32(), 69157722); } #[test] fn test_isaac64_true_bytes() { let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0, 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0]; let mut rng = Isaac64Rng::from_seed(seed); let mut results = [0u8; 32]; rng.fill_bytes(&mut results); // Same as first values in test_isaac64_true_values as bytes in LE order let expected = [100, 131, 77, 207, 155, 181, 40, 209, 102, 176, 255, 40, 238, 155, 35, 107, 61, 123, 136, 13, 246, 243, 99, 150, 216, 167, 15, 241, 62, 149, 34, 75]; assert_eq!(results, expected); } #[test] fn test_isaac64_new_uninitialized() { // Compare the results from initializing `IsaacRng` with // `new_from_u64(0)`, to make sure it is the same as the reference // implementation when used uninitialized. // Note: We only test the first 16 integers, not the full 256 of the // first block. let mut rng = Isaac64Rng::new_from_u64(0); let mut results = [0u64; 16]; for i in results.iter_mut() { *i = rng.next_u64(); } let expected: [u64; 16] = [ 0xF67DFBA498E4937C, 0x84A5066A9204F380, 0xFEE34BD5F5514DBB, 0x4D1664739B8F80D6, 0x8607459AB52A14AA, 0x0E78BC5A98529E49, 0xFE5332822AD13777, 0x556C27525E33D01A, 0x08643CA615F3149F, 0xD0771FAF3CB04714, 0x30E86F68A37B008D, 0x3074EBC0488A3ADF, 0x270645EA7A2790BC, 0x5601A0A8D3763C6A, 0x2F83071F53F325DD, 0xB9090F3D42D2D2EA]; assert_eq!(results, expected); } #[test] fn test_isaac64_clone() { let seed = [1,0,0,0, 0,0,0,0, 23,0,0,0, 0,0,0,0, 200,1,0,0, 0,0,0,0, 210,30,0,0, 0,0,0,0]; let mut rng1 = Isaac64Rng::from_seed(seed); let mut rng2 = rng1.clone(); for _ in 0..16 { assert_eq!(rng1.next_u64(), rng2.next_u64()); } } #[test] #[cfg(all(feature="serde1", feature="std"))] fn test_isaac64_serde() { use bincode; use std::io::{BufWriter, BufReader}; let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 57,48,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng = Isaac64Rng::from_seed(seed); let buf: Vec = Vec::new(); let mut buf = BufWriter::new(buf); bincode::serialize_into(&mut buf, &rng).expect("Could not serialize"); let buf = buf.into_inner().unwrap(); let mut read = BufReader::new(&buf[..]); let mut deserialized: Isaac64Rng = bincode::deserialize_from(&mut read).expect("Could not deserialize"); for _ in 0..300 { // more than the 256 buffered results assert_eq!(rng.next_u64(), deserialized.next_u64()); } } } rand-0.5.5/src/prng/isaac_array.rs010064400017500001750000000075141333210603300152500ustar0000000000000000// Copyright 2017-2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! ISAAC helper functions for 256-element arrays. // Terrible workaround because arrays with more than 32 elements do not // implement `AsRef`, `Default`, `Serialize`, `Deserialize`, or any other // traits for that matter. #[cfg(feature="serde1")] use serde::{Serialize, Deserialize}; const RAND_SIZE_LEN: usize = 8; const RAND_SIZE: usize = 1 << RAND_SIZE_LEN; #[derive(Copy, Clone)] #[allow(missing_debug_implementations)] #[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] pub struct IsaacArray { #[cfg_attr(feature="serde1",serde(with="isaac_array_serde"))] #[cfg_attr(feature="serde1", serde(bound( serialize = "T: Serialize", deserialize = "T: Deserialize<'de> + Copy + Default")))] inner: [T; RAND_SIZE] } impl ::core::convert::AsRef<[T]> for IsaacArray { #[inline(always)] fn as_ref(&self) -> &[T] { &self.inner[..] } } impl ::core::convert::AsMut<[T]> for IsaacArray { #[inline(always)] fn as_mut(&mut self) -> &mut [T] { &mut self.inner[..] } } impl ::core::ops::Deref for IsaacArray { type Target = [T; RAND_SIZE]; #[inline(always)] fn deref(&self) -> &Self::Target { &self.inner } } impl ::core::ops::DerefMut for IsaacArray { #[inline(always)] fn deref_mut(&mut self) -> &mut [T; RAND_SIZE] { &mut self.inner } } impl ::core::default::Default for IsaacArray where T: Copy + Default { fn default() -> IsaacArray { IsaacArray { inner: [T::default(); RAND_SIZE] } } } #[cfg(feature="serde1")] pub(super) mod isaac_array_serde { const RAND_SIZE_LEN: usize = 8; const RAND_SIZE: usize = 1 << RAND_SIZE_LEN; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::de::{Visitor,SeqAccess}; use serde::de; use core::fmt; pub fn serialize(arr: &[T;RAND_SIZE], ser: S) -> Result where T: Serialize, S: Serializer { use serde::ser::SerializeTuple; let mut seq = ser.serialize_tuple(RAND_SIZE)?; for e in arr.iter() { seq.serialize_element(&e)?; } seq.end() } #[inline] pub fn deserialize<'de, T, D>(de: D) -> Result<[T;RAND_SIZE], D::Error> where T: Deserialize<'de>+Default+Copy, D: Deserializer<'de>, { use core::marker::PhantomData; struct ArrayVisitor { _pd: PhantomData, }; impl<'de,T> Visitor<'de> for ArrayVisitor where T: Deserialize<'de>+Default+Copy { type Value = [T; RAND_SIZE]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Isaac state array") } #[inline] fn visit_seq(self, mut seq: A) -> Result<[T; RAND_SIZE], A::Error> where A: SeqAccess<'de>, { let mut out = [Default::default();RAND_SIZE]; for i in 0..RAND_SIZE { match seq.next_element()? { Some(val) => out[i] = val, None => return Err(de::Error::invalid_length(i, &self)), }; } Ok(out) } } de.deserialize_tuple(RAND_SIZE, ArrayVisitor{_pd: PhantomData}) } } rand-0.5.5/src/prng/mod.rs010064400017500001750000000375231333210603300135540ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! Pseudo-random number generators. //! //! Pseudo-random number generators are algorithms to produce apparently random //! numbers deterministically, and usually fairly quickly. See the documentation //! of the [`rngs` module] for some introduction to PRNGs. //! //! As mentioned there, PRNGs fall in two broad categories: //! //! - [basic PRNGs], primarily designed for simulations //! - [CSPRNGs], primarily designed for cryptography //! //! In simple terms, the basic PRNGs are often predictable; CSPRNGs should not //! be predictable *when used correctly*. //! //! Contents of this documentation: //! //! 1. [The generators](#the-generators) //! 1. [Performance and size](#performance) //! 1. [Quality and cycle length](#quality) //! 1. [Security](#security) //! 1. [Extra features](#extra-features) //! 1. [Further reading](#further-reading) //! //! //! # The generators //! //! ## Basic pseudo-random number generators (PRNGs) //! //! The goal of regular, non-cryptographic PRNGs is usually to find a good //! balance between simplicity, quality, memory usage and performance. These //! algorithms are very important to Monte Carlo simulations, and also suitable //! for several other problems such as randomized algorithms and games (except //! where there is a risk of players predicting the next output value from //! previous values, in which case a CSPRNG should be used). //! //! Currently Rand provides only one PRNG, and not a very good one at that: //! //! | name | full name | performance | memory | quality | period | features | //! |------|-----------|-------------|--------|---------|--------|----------| //! | [`XorShiftRng`] | Xorshift 32/128 | ★★★☆☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2128 - 1 | — | //! // Quality stars [not rendered in documentation]: // 5. reserved for crypto-level (e.g. ChaCha8, ISAAC) // 4. good performance on TestU01 and PractRand, good theory // (e.g. PCG, truncated Xorshift*) // 3. good performance on TestU01 and PractRand, but "falling through the // cracks" or insufficient theory (e.g. SFC, Xoshiro) // 2. imperfect performance on tests or other limiting properties, but not // terrible (e.g. Xoroshiro128+) // 1. clear deficiencies in test results, cycle length, theory, or other // properties (e.g. Xorshift) // // Performance stars [not rendered in documentation]: // Meant to give an indication of relative performance. Roughly follows a log // scale, based on the performance of `next_u64` on a current i5/i7: // - 5. 8000 MB/s+ // - 4. 4000 MB/s+ // - 3. 2000 MB/s+ // - 2. 1000 MB/s+ // - 1. < 1000 MB/s // //! ## Cryptographically secure pseudo-random number generators (CSPRNGs) //! //! CSPRNGs have much higher requirements than basic PRNGs. The primary //! consideration is security. Performance and simplicity are also important, //! but in general CSPRNGs are more complex and slower than regular PRNGs. //! Quality is no longer a concern, as it is a requirement for a //! CSPRNG that the output is basically indistinguishable from true randomness //! since any bias or correlation makes the output more predictable. //! //! There is a close relationship between CSPRNGs and cryptographic ciphers. //! Any block cipher can be turned into a CSPRNG by encrypting a counter. Stream //! ciphers are basically a CSPRNG and a combining operation, usually XOR. This //! means that we can easily use any stream cipher as a CSPRNG. //! //! Rand currently provides two trustworthy CSPRNGs and two CSPRNG-like PRNGs: //! //! | name | full name | performance | initialization | memory | predictability | forward secrecy | //! |------|-----------|--------------|--------------|----------|----------------|-------------------------| //! | [`ChaChaRng`] | ChaCha20 | ★☆☆☆☆ | fast | 136 bytes | secure | no | //! | [`Hc128Rng`] | HC-128 | ★★☆☆☆ | slow | 4176 bytes | secure | no | //! | [`IsaacRng`] | ISAAC | ★★☆☆☆ | slow | 2072 bytes | unknown | unknown | //! | [`Isaac64Rng`] | ISAAC-64 | ★★☆☆☆ | slow | 4136 bytes| unknown | unknown | //! //! It should be noted that the ISAAC generators are only included for //! historical reasons, they have been with the Rust language since the very //! beginning. They have good quality output and no attacks are known, but have //! received little attention from cryptography experts. //! //! //! # Performance //! //! First it has to be said most PRNGs are very fast, and will rarely be a //! performance bottleneck. //! //! Performance of basic PRNGs is a bit of a subtle thing. It depends a lot on //! the CPU architecture (32 vs. 64 bits), inlining, and also on the number of //! available registers. This often causes the performance to be affected by //! surrounding code due to inlining and other usage of registers. //! //! When choosing a PRNG for performance it is important to benchmark your own //! application due to interactions between PRNGs and surrounding code and //! dependence on the CPU architecture as well as the impact of the size of //! data requested. Because of all this, we do not include performance numbers //! here but merely a qualitative rating. //! //! CSPRNGs are a little different in that they typically generate a block of //! output in a cache, and pull outputs from the cache. This allows them to have //! good amortised performance, and reduces or completely removes the influence //! of surrounding code on the CSPRNG performance. //! //! ### Worst-case performance //! Because CSPRNGs usually produce a block of values into a cache, they have //! poor worst case performance (in contrast to basic PRNGs, where the //! performance is usually quite regular). //! //! ## State size //! //! Simple PRNGs often use very little memory, commonly only a few words, where //! a *word* is usually either `u32` or `u64`. This is not true for all //! non-cryptographic PRNGs however, for example the historically popular //! Mersenne Twister MT19937 algorithm requires 2.5 kB of state. //! //! CSPRNGs typically require more memory; since the seed size is recommended //! to be at least 192 bits and some more may be required for the algorithm, //! 256 bits would be approximately the minimum secure size. In practice, //! CSPRNGs tend to use quite a bit more, [`ChaChaRng`] is relatively small with //! 136 bytes of state. //! //! ## Initialization time //! //! The time required to initialize new generators varies significantly. Many //! simple PRNGs and even some cryptographic ones (including [`ChaChaRng`]) //! only need to copy the seed value and some constants into their state, and //! thus can be constructed very quickly. In contrast, CSPRNGs with large state //! require an expensive key-expansion. //! //! # Quality //! //! Many basic PRNGs are not much more than a couple of bitwise and arithmetic //! operations. Their simplicity gives good performance, but also means there //! are small regularities hidden in the generated random number stream. //! //! How much do those hidden regularities matter? That is hard to say, and //! depends on how the RNG gets used. If there happen to be correlations between //! the random numbers and the algorithm they are used in, the results can be //! wrong or misleading. //! //! A random number generator can be considered good if it gives the correct //! results in as many applications as possible. The quality of PRNG //! algorithms can be evaluated to some extend analytically, to determine the //! cycle length and to rule out some correlations. Then there are empirical //! test suites designed to test how well a PRNG performs on a wide range of //! possible uses, the latest and most complete of which are [TestU01] and //! [PractRand]. //! //! CSPRNGs tend to be more complex, and have an explicit requirement to be //! unpredictable. This implies there must be no obvious correlations between //! output values. //! //! ### Quality stars: //! PRNGs with 3 stars or more should be good enough for any purpose. //! 1 or 2 stars may be good enough for typical apps and games, but do not work //! well with all algorithms. //! //! ## Period //! //! The *period* or *cycle length* of a PRNG is the number of values that can be //! generated after which it starts repeating the same random number stream. //! Many PRNGs have a fixed-size period, but for some only an expected average //! cycle length can be given, where the exact length depends on the seed. //! //! On today's hardware, even a fast RNG with a cycle length of *only* //! 264 can be used for centuries before cycling. Yet we recommend a //! period of 2128 or more, which most modern PRNGs satisfy. //! Alternatively a PRNG with shorter period but support for multiple streams //! may be chosen. There are two reasons for this, as follows. //! //! If we see the entire period of an RNG as one long random number stream, //! every independently seeded RNG returns a slice of that stream. When multiple //! RNG are seeded randomly, there is an increasingly large chance to end up //! with a partially overlapping slice of the stream. //! //! If the period of the RNG is 2128, and an application consumes //! 248 values, it then takes about 232 random //! initializations to have a chance of 1 in a million to repeat part of an //! already used stream. This seems good enough for common usage of //! non-cryptographic generators, hence the recommendation of at least //! 2128. As an estimate, the chance of any overlap in a period of //! size `p` with `n` independent seeds and `u` values used per seed is //! approximately `1 - e^(-u * n^2 / (2 * p))`. //! //! Further, it is not recommended to use the full period of an RNG. Many //! PRNGs have a property called *k-dimensional equidistribution*, meaning that //! for values of some size (potentially larger than the output size), all //! possible values are produced the same number of times over the generator's //! period. This is not a property of true randomness. This is known as the //! generalized birthday problem, see the [PCG paper] for a good explanation. //! This results in a noticable bias on output after generating more values //! than the square root of the period (after 264 values for a //! period of 2128). //! //! //! # Security //! //! ## Predictability //! //! From the context of any PRNG, one can ask the question *given some previous //! output from the PRNG, is it possible to predict the next output value?* //! This is an important property in any situation where there might be an //! adversary. //! //! Regular PRNGs tend to be predictable, although with varying difficulty. In //! some cases prediction is trivial, for example plain Xorshift outputs part of //! its state without mutation, and prediction is as simple as seeding a new //! Xorshift generator from four `u32` outputs. Other generators, like //! [PCG](http://www.pcg-random.org/predictability.html) and truncated Xorshift* //! are harder to predict, but not outside the realm of common mathematics and a //! desktop PC. //! //! The basic security that CSPRNGs must provide is the infeasibility to predict //! output. This requirement is formalized as the [next-bit test]; this is //! roughly stated as: given the first *k* bits of a random sequence, the //! sequence satisfies the next-bit test if there is no algorithm able to //! predict the next bit using reasonable computing power. //! //! A further security that *some* CSPRNGs provide is forward secrecy: //! in the event that the CSPRNGs state is revealed at some point, it must be //! infeasible to reconstruct previous states or output. Note that many CSPRNGs //! *do not* have forward secrecy in their usual formulations. //! //! As an outsider it is hard to get a good idea about the security of an //! algorithm. People in the field of cryptography spend a lot of effort //! analyzing existing designs, and what was once considered good may now turn //! out to be weaker. Generally it is best to use algorithms well-analyzed by //! experts, such as those recommended by NIST or ECRYPT. //! //! ## State and seeding //! //! It is worth noting that a CSPRNG's security relies absolutely on being //! seeded with a secure random key. Should the key be known or guessable, all //! output of the CSPRNG is easy to guess. This implies that the seed should //! come from a trusted source; usually either the OS or another CSPRNG. Our //! seeding helper trait, [`FromEntropy`], and the source it uses //! ([`EntropyRng`]), should be secure. Additionally, [`ThreadRng`] is a CSPRNG, //! thus it is acceptable to seed from this (although for security applications //! fresh/external entropy should be preferred). //! //! Further, it should be obvious that the internal state of a CSPRNG must be //! kept secret. With that in mind, our implementations do not provide direct //! access to most of their internal state, and `Debug` implementations do not //! print any internal state. This does not fully protect CSPRNG state; code //! within the same process may read this memory (and we allow cloning and //! serialisation of CSPRNGs for convenience). Further, a running process may be //! forked by the operating system, which may leave both processes with a copy //! of the same generator. //! //! ## Not a crypto library //! //! It should be emphasised that this is not a cryptography library; although //! Rand does take some measures to provide secure random numbers, it does not //! necessarily take all recommended measures. Further, cryptographic processes //! such as encryption and authentication are complex and must be implemented //! very carefully to avoid flaws and resist known attacks. It is therefore //! recommended to use specialized libraries where possible, for example //! [openssl], [ring] and the [RustCrypto libraries]. //! //! //! # Extra features //! //! Some PRNGs may provide extra features, like: //! //! - Support for multiple streams, which can help with parallel tasks. //! - The ability to jump or seek around in the random number stream; //! with large periood this can be used as an alternative to streams. //! //! //! # Further reading //! //! There is quite a lot that can be said about PRNGs. The [PCG paper] is a //! very approachable explaining more concepts. //! //! A good paper about RNG quality is //! ["Good random number generators are (not so) easy to find"]( //! http://random.mat.sbg.ac.at/results/peter/A19final.pdf) by P. Hellekalek. //! //! //! [`rngs` module]: ../rngs/index.html //! [basic PRNGs]: #basic-pseudo-random-number-generators-prngs //! [CSPRNGs]: #cryptographically-secure-pseudo-random-number-generators-csprngs //! [`XorShiftRng`]: struct.XorShiftRng.html //! [`ChaChaRng`]: chacha/struct.ChaChaRng.html //! [`Hc128Rng`]: hc128/struct.Hc128Rng.html //! [`IsaacRng`]: isaac/struct.IsaacRng.html //! [`Isaac64Rng`]: isaac64/struct.Isaac64Rng.html //! [`ThreadRng`]: ../rngs/struct.ThreadRng.html //! [`FromEntropy`]: ../trait.FromEntropy.html //! [`EntropyRng`]: ../rngs/struct.EntropyRng.html //! [TestU01]: http://simul.iro.umontreal.ca/testu01/tu01.html //! [PractRand]: http://pracrand.sourceforge.net/ //! [PCG paper]: http://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf //! [openssl]: https://crates.io/crates/openssl //! [ring]: https://crates.io/crates/ring //! [RustCrypto libraries]: https://github.com/RustCrypto //! [next-bit test]: https://en.wikipedia.org/wiki/Next-bit_test pub mod chacha; pub mod hc128; pub mod isaac; pub mod isaac64; mod xorshift; mod isaac_array; pub use self::chacha::ChaChaRng; pub use self::hc128::Hc128Rng; pub use self::isaac::IsaacRng; pub use self::isaac64::Isaac64Rng; pub use self::xorshift::XorShiftRng; rand-0.5.5/src/prng/xorshift.rs010064400017500001750000000163421333210603300146370ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! Xorshift generators use core::num::Wrapping as w; use core::{fmt, slice}; use rand_core::{RngCore, SeedableRng, Error, impls, le}; /// An Xorshift random number generator. /// /// The Xorshift[^1] algorithm is not suitable for cryptographic purposes /// but is very fast. If you do not know for sure that it fits your /// requirements, use a more secure one such as `IsaacRng` or `OsRng`. /// /// [^1]: Marsaglia, George (July 2003). /// ["Xorshift RNGs"](https://www.jstatsoft.org/v08/i14/paper). /// *Journal of Statistical Software*. Vol. 8 (Issue 14). #[derive(Clone)] #[cfg_attr(feature="serde1", derive(Serialize,Deserialize))] pub struct XorShiftRng { x: w, y: w, z: w, w: w, } // Custom Debug implementation that does not expose the internal state impl fmt::Debug for XorShiftRng { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XorShiftRng {{}}") } } impl XorShiftRng { /// Creates a new XorShiftRng instance which is not seeded. /// /// The initial values of this RNG are constants, so all generators created /// by this function will yield the same stream of random numbers. It is /// highly recommended that this is created through `SeedableRng` instead of /// this function #[deprecated(since="0.5.0", note="use the FromEntropy or SeedableRng trait")] pub fn new_unseeded() -> XorShiftRng { XorShiftRng { x: w(0x193a6754), y: w(0xa8a7d469), z: w(0x97830e05), w: w(0x113ba7bb), } } } impl RngCore for XorShiftRng { #[inline] fn next_u32(&mut self) -> u32 { let x = self.x; let t = x ^ (x << 11); self.x = self.y; self.y = self.z; self.z = self.w; let w_ = self.w; self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); self.w.0 } #[inline] fn next_u64(&mut self) -> u64 { impls::next_u64_via_u32(self) } #[inline] fn fill_bytes(&mut self, dest: &mut [u8]) { impls::fill_bytes_via_next(self, dest) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { Ok(self.fill_bytes(dest)) } } impl SeedableRng for XorShiftRng { type Seed = [u8; 16]; fn from_seed(seed: Self::Seed) -> Self { let mut seed_u32 = [0u32; 4]; le::read_u32_into(&seed, &mut seed_u32); // Xorshift cannot be seeded with 0 and we cannot return an Error, but // also do not wish to panic (because a random seed can legitimately be // 0); our only option is therefore to use a preset value. if seed_u32.iter().all(|&x| x == 0) { seed_u32 = [0xBAD_5EED, 0xBAD_5EED, 0xBAD_5EED, 0xBAD_5EED]; } XorShiftRng { x: w(seed_u32[0]), y: w(seed_u32[1]), z: w(seed_u32[2]), w: w(seed_u32[3]), } } fn from_rng(mut rng: R) -> Result { let mut seed_u32 = [0u32; 4]; loop { unsafe { let ptr = seed_u32.as_mut_ptr() as *mut u8; let slice = slice::from_raw_parts_mut(ptr, 4 * 4); rng.try_fill_bytes(slice)?; } if !seed_u32.iter().all(|&x| x == 0) { break; } } Ok(XorShiftRng { x: w(seed_u32[0]), y: w(seed_u32[1]), z: w(seed_u32[2]), w: w(seed_u32[3]), }) } } #[cfg(test)] mod tests { use {RngCore, SeedableRng}; use super::XorShiftRng; #[test] fn test_xorshift_construction() { // Test that various construction techniques produce a working RNG. let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; let mut rng1 = XorShiftRng::from_seed(seed); assert_eq!(rng1.next_u64(), 4325440999699518727); let _rng2 = XorShiftRng::from_rng(rng1).unwrap(); // Note: we cannot test the state of _rng2 because from_rng does not // fix Endianness. This is allowed in the trait specification. } #[test] fn test_xorshift_true_values() { let seed = [16,15,14,13, 12,11,10,9, 8,7,6,5, 4,3,2,1]; let mut rng = XorShiftRng::from_seed(seed); let mut results = [0u32; 9]; for i in results.iter_mut() { *i = rng.next_u32(); } let expected: [u32; 9] = [ 2081028795, 620940381, 269070770, 16943764, 854422573, 29242889, 1550291885, 1227154591, 271695242]; assert_eq!(results, expected); let mut results = [0u64; 9]; for i in results.iter_mut() { *i = rng.next_u64(); } let expected: [u64; 9] = [ 9247529084182843387, 8321512596129439293, 14104136531997710878, 6848554330849612046, 343577296533772213, 17828467390962600268, 9847333257685787782, 7717352744383350108, 1133407547287910111]; assert_eq!(results, expected); let mut results = [0u8; 32]; rng.fill_bytes(&mut results); let expected = [102, 57, 212, 16, 233, 130, 49, 183, 158, 187, 44, 203, 63, 149, 45, 17, 117, 129, 131, 160, 70, 121, 158, 155, 224, 209, 192, 53, 10, 62, 57, 72]; assert_eq!(results, expected); } #[test] fn test_xorshift_zero_seed() { // Xorshift does not work with an all zero seed. // Assert it does not panic. let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; let mut rng = XorShiftRng::from_seed(seed); let a = rng.next_u64(); let b = rng.next_u64(); assert!(a != 0); assert!(b != a); } #[test] fn test_xorshift_clone() { let seed = [1,2,3,4, 5,5,7,8, 8,7,6,5, 4,3,2,1]; let mut rng1 = XorShiftRng::from_seed(seed); let mut rng2 = rng1.clone(); for _ in 0..16 { assert_eq!(rng1.next_u64(), rng2.next_u64()); } } #[cfg(all(feature="serde1", feature="std"))] #[test] fn test_xorshift_serde() { use bincode; use std::io::{BufWriter, BufReader}; let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; let mut rng = XorShiftRng::from_seed(seed); let buf: Vec = Vec::new(); let mut buf = BufWriter::new(buf); bincode::serialize_into(&mut buf, &rng).expect("Could not serialize"); let buf = buf.into_inner().unwrap(); let mut read = BufReader::new(&buf[..]); let mut deserialized: XorShiftRng = bincode::deserialize_from(&mut read).expect("Could not deserialize"); assert_eq!(rng.x, deserialized.x); assert_eq!(rng.y, deserialized.y); assert_eq!(rng.z, deserialized.z); assert_eq!(rng.w, deserialized.w); for _ in 0..16 { assert_eq!(rng.next_u64(), deserialized.next_u64()); } } } rand-0.5.5/src/rngs/adapter/mod.rs010064400017500001750000000012311331042026600151650ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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")] #[doc(hidden)] pub mod read; mod reseeding; #[cfg(feature="std")] pub use self::read::ReadRng; pub use self::reseeding::ReseedingRng; rand-0.5.5/src/rngs/adapter/read.rs010064400017500001750000000101361333210603300153220ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 rand_core::{RngCore, Error, ErrorKind, 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_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::{read, Rng}; /// /// let data = vec![1, 2, 3, 4, 5, 6, 7, 8]; /// let mut rng = read::ReadRng::new(&data[..]); /// println!("{:x}", rng.gen::()); /// ``` /// /// [`OsRng`]: ../struct.OsRng.html /// [`RngCore`]: ../../trait.RngCore.html /// [`try_fill_bytes`]: ../../trait.RngCore.html#method.tymethod.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.len() == 0 { return Ok(()); } // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. self.reader.read_exact(dest).map_err(|err| { match err.kind() { ::std::io::ErrorKind::UnexpectedEof => Error::with_cause( ErrorKind::Unavailable, "not enough bytes available, reached end of source", err), _ => Error::with_cause(ErrorKind::Unavailable, "error reading from Read source", err) } }) } } #[cfg(test)] mod test { use super::ReadRng; use {RngCore, ErrorKind}; #[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[..]); assert!(rng.try_fill_bytes(&mut w).err().unwrap().kind == ErrorKind::Unavailable); } } rand-0.5.5/src/rngs/adapter/reseeding.rs010064400017500001750000000221761333210603300163630ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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, ErrorKind}; use rand_core::block::{BlockRngCore, BlockRng}; /// A wrapper around any PRNG which reseeds the underlying PRNG after it has /// generated a certain number of random bytes. /// /// When the RNG gets cloned, the clone is reseeded on first use. /// /// Reseeding 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'. /// /// Some small non-cryptographic PRNGs can have very small periods, for /// example less than 264. Would reseeding help to ensure that you do /// not wrap around at the end of the period? A period of 264 still /// takes several centuries of CPU-years on current hardware. Reseeding will /// actually make things worse, because the reseeded PRNG will just continue /// somewhere else *in the same period*, with a high chance of overlapping with /// previously used parts of it. /// /// # When should you use `ReseedingRng`? /// /// - 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, /// occasionally reseeding should make exploiting it much more difficult or /// even impossible. /// - It can be used as a poor man's cryptography (not recommended, just use a /// good CSPRNG). Previous implementations of `thread_rng` for example used /// `ReseedingRng` with the ISAAC RNG. That algorithm, although apparently /// strong and with no known attack, does not come with any proof of security /// and does not meet the current standards for a cryptographically secure /// PRNG. By reseeding it frequently (every 32 kiB) it seems safe to assume /// there is no attack that can operate on the tiny window between reseeds. /// /// # Error handling /// /// Although extremely 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. #[derive(Debug)] pub struct ReseedingRng(BlockRng>) where R: BlockRngCore + SeedableRng, Rsdr: RngCore; impl ReseedingRng where R: BlockRngCore + SeedableRng, Rsdr: RngCore { /// Create a new `ReseedingRng` with the given parameters. /// /// # Arguments /// /// * `rng`: the random number generator to use. /// * `threshold`: the number of generated bytes after which to reseed the RNG. /// * `reseeder`: the RNG to use for reseeding. 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, } impl BlockRngCore for ReseedingCore where R: BlockRngCore + SeedableRng, Rsdr: RngCore { type Item = ::Item; type Results = ::Results; fn generate(&mut self, results: &mut Self::Results) { if self.bytes_until_reseed <= 0 { // We get better performance by not calling only `auto_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); } 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` with the given parameters. /// /// # Arguments /// /// * `rng`: the random number generator to use. /// * `threshold`: the number of generated bytes after which to reseed the RNG. /// * `reseeder`: the RNG to use for reseeding. pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { assert!(threshold <= ::core::i64::MAX as u64); ReseedingCore { inner: rng, reseeder, threshold: threshold as i64, bytes_until_reseed: threshold as i64, } } /// 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 }) } #[inline(never)] fn reseed_and_generate(&mut self, results: &mut ::Results) { trace!("Reseeding RNG after {} generated bytes", self.threshold - self.bytes_until_reseed); let threshold = if let Err(e) = self.reseed() { let delay = match e.kind { ErrorKind::Transient => 0, kind @ _ if kind.should_retry() => self.threshold >> 8, _ => self.threshold, }; warn!("Reseeding RNG delayed reseeding by {} bytes due to \ error from source: {}", delay, e); delay } else { self.threshold }; let num_bytes = results.as_ref().len() * size_of::<::Item>(); self.bytes_until_reseed = 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 } } } impl CryptoRng for ReseedingCore where R: BlockRngCore + SeedableRng + CryptoRng, Rsdr: RngCore + CryptoRng {} #[cfg(test)] mod test { use {Rng, SeedableRng}; use prng::chacha::ChaChaCore; use rngs::mock::StepRng; use super::ReseedingRng; #[test] fn test_reseeding() { let mut zero = StepRng::new(0, 0); let rng = ChaChaCore::from_rng(&mut zero).unwrap(); let mut reseeding = ReseedingRng::new(rng, 32*4, zero); // Currently we only support for arrays up to length 32. // TODO: cannot generate seq via Rng::gen because it uses different alg let mut buf = [0u32; 32]; // Needs to be a multiple of the RNGs result // size to test exactly. reseeding.fill(&mut buf); let seq = buf; for _ in 0..10 { reseeding.fill(&mut buf); assert_eq!(buf, seq); } } #[test] fn test_clone_reseeding() { let mut zero = StepRng::new(0, 0); let rng = ChaChaCore::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.5.5/src/rngs/entropy.rs010064400017500001750000000227521333210603300144760ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 use rand_core::{RngCore, CryptoRng, Error, ErrorKind, impls}; #[allow(unused)] use rngs; /// An interface returning random data from external source(s), provided /// specifically for securely seeding algorithmic generators (PRNGs). /// /// Where possible, `EntropyRng` retrieves random data from the operating /// system's interface for random numbers ([`OsRng`]); if that fails it will /// fall back to the [`JitterRng`] entropy collector. In the latter case it will /// still try to use [`OsRng`] on the next usage. /// /// If no secure source of entropy is available `EntropyRng` will panic on use; /// i.e. it should never output predictable data. /// /// This is either a little slow ([`OsRng`] requires a system call) or extremely /// slow ([`JitterRng`] must use significant CPU time to generate sufficient /// jitter); for better performance it is common to seed a local PRNG from /// external entropy then primarily use the local PRNG ([`thread_rng`] is /// provided as a convenient, local, automatically-seeded CSPRNG). /// /// # Panics /// /// On most systems, like Windows, Linux, macOS and *BSD on common hardware, it /// is highly unlikely for both [`OsRng`] and [`JitterRng`] to fail. But on /// combinations like webassembly without Emscripten or stdweb both sources are /// unavailable. If both sources fail, only [`try_fill_bytes`] is able to /// report the error, and only the one from `OsRng`. The other [`RngCore`] /// methods will panic in case of an error. /// /// [`OsRng`]: struct.OsRng.html /// [`JitterRng`]: jitter/struct.JitterRng.html /// [`thread_rng`]: ../fn.thread_rng.html /// [`RngCore`]: ../trait.RngCore.html /// [`try_fill_bytes`]: ../trait.RngCore.html#method.tymethod.try_fill_bytes #[derive(Debug)] pub struct EntropyRng { source: Source, } #[derive(Debug)] enum Source { Os(Os), Custom(Custom), Jitter(Jitter), None, } 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: Source::None } } } impl Default for EntropyRng { fn default() -> Self { EntropyRng::new() } } impl RngCore for EntropyRng { 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!("all entropy sources failed; first error: {}", err)) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { let mut reported_error = None; if let Source::Os(ref mut os_rng) = self.source { match os_rng.fill(dest) { Ok(()) => return Ok(()), Err(err) => { warn!("EntropyRng: OsRng failed \ [trying other entropy sources]: {}", err); reported_error = Some(err); }, } } else if Os::is_supported() { match Os::new_and_fill(dest) { Ok(os_rng) => { debug!("EntropyRng: using OsRng"); self.source = Source::Os(os_rng); return Ok(()); }, Err(err) => { reported_error = reported_error.or(Some(err)) }, } } if let Source::Custom(ref mut rng) = self.source { match rng.fill(dest) { Ok(()) => return Ok(()), Err(err) => { warn!("EntropyRng: custom entropy source failed \ [trying other entropy sources]: {}", err); reported_error = Some(err); }, } } else if Custom::is_supported() { match Custom::new_and_fill(dest) { Ok(custom) => { debug!("EntropyRng: using custom entropy source"); self.source = Source::Custom(custom); return Ok(()); }, Err(err) => { reported_error = reported_error.or(Some(err)) }, } } if let Source::Jitter(ref mut jitter_rng) = self.source { match jitter_rng.fill(dest) { Ok(()) => return Ok(()), Err(err) => { warn!("EntropyRng: JitterRng failed: {}", err); reported_error = Some(err); }, } } else if Jitter::is_supported() { match Jitter::new_and_fill(dest) { Ok(jitter_rng) => { debug!("EntropyRng: using JitterRng"); self.source = Source::Jitter(jitter_rng); return Ok(()); }, Err(err) => { reported_error = reported_error.or(Some(err)) }, } } if let Some(err) = reported_error { Err(Error::with_cause(ErrorKind::Unavailable, "All entropy sources failed", err)) } else { Err(Error::new(ErrorKind::Unavailable, "No entropy sources available")) } } } impl CryptoRng for EntropyRng {} trait EntropySource { fn new_and_fill(dest: &mut [u8]) -> Result where Self: Sized; fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error>; fn is_supported() -> bool { true } } #[allow(unused)] #[derive(Clone, Debug)] struct NoSource; #[allow(unused)] impl EntropySource for NoSource { fn new_and_fill(dest: &mut [u8]) -> Result { Err(Error::new(ErrorKind::Unavailable, "Source not supported")) } fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> { unreachable!() } fn is_supported() -> bool { false } } #[cfg(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") )))] #[derive(Clone, Debug)] pub struct Os(rngs::OsRng); #[cfg(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") )))] impl EntropySource for Os { fn new_and_fill(dest: &mut [u8]) -> Result { let mut rng = rngs::OsRng::new()?; rng.try_fill_bytes(dest)?; Ok(Os(rng)) } fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.0.try_fill_bytes(dest) } } #[cfg(not(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") ))))] type Os = NoSource; type Custom = NoSource; #[cfg(not(target_arch = "wasm32"))] #[derive(Clone, Debug)] pub struct Jitter(rngs::JitterRng); #[cfg(not(target_arch = "wasm32"))] impl EntropySource for Jitter { fn new_and_fill(dest: &mut [u8]) -> Result { let mut rng = rngs::JitterRng::new()?; rng.try_fill_bytes(dest)?; Ok(Jitter(rng)) } fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.0.try_fill_bytes(dest) } } #[cfg(target_arch = "wasm32")] type Jitter = NoSource; #[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.5.5/src/rngs/jitter.rs010064400017500001750000001052561333210603300143000ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. // // Based on jitterentropy-library, http://www.chronox.de/jent.html. // Copyright Stephan Mueller , 2014 - 2017. // // With permission from Stephan Mueller to relicense the Rust translation under // the MIT license. //! Non-physical true random number generator based on timing jitter. // Note: the C implementation of `Jitterentropy` relies on being compiled // without optimizations. This implementation goes through lengths to make the // compiler not optimize out code which does influence timing jitter, but is // technically dead code. use rand_core::{RngCore, CryptoRng, Error, ErrorKind, impls}; use core::{fmt, mem, ptr}; #[cfg(all(feature="std", not(target_arch = "wasm32")))] use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; const MEMORY_BLOCKS: usize = 64; const MEMORY_BLOCKSIZE: usize = 32; const MEMORY_SIZE: usize = MEMORY_BLOCKS * MEMORY_BLOCKSIZE; /// A true random number generator based on jitter in the CPU execution time, /// and jitter in memory access time. /// /// This is a true random number generator, as opposed to pseudo-random /// generators. Random numbers generated by `JitterRng` can be seen as fresh /// entropy. A consequence is that is orders of magnitude slower than [`OsRng`] /// and PRNGs (about 103..106 slower). /// /// There are very few situations where using this RNG is appropriate. Only very /// few applications require true entropy. A normal PRNG can be statistically /// indistinguishable, and a cryptographic PRNG should also be as impossible to /// predict. /// /// Use of `JitterRng` is recommended for initializing cryptographic PRNGs when /// [`OsRng`] is not available. /// /// `JitterRng` can be used without the standard library, but not conveniently, /// you must provide a high-precision timer and carefully have to follow the /// instructions of [`new_with_timer`]. /// /// This implementation is based on /// [Jitterentropy](http://www.chronox.de/jent.html) version 2.1.0. /// /// Note: There is no accurate timer available on Wasm platforms, to help /// prevent fingerprinting or timing side-channel attacks. Therefore /// [`JitterRng::new()`] is not available on Wasm. /// /// # Quality testing /// /// [`JitterRng::new()`] has build-in, but limited, quality testing, however /// before using `JitterRng` on untested hardware, or after changes that could /// effect how the code is optimized (such as a new LLVM version), it is /// recommend to run the much more stringent /// [NIST SP 800-90B Entropy Estimation Suite]( /// https://github.com/usnistgov/SP800-90B_EntropyAssessment). /// /// Use the following code using [`timer_stats`] to collect the data: /// /// ```no_run /// use rand::jitter::JitterRng; /// # /// # use std::error::Error; /// # use std::fs::File; /// # use std::io::Write; /// # /// # fn try_main() -> Result<(), Box> { /// let mut rng = JitterRng::new()?; /// /// // 1_000_000 results are required for the /// // NIST SP 800-90B Entropy Estimation Suite /// const ROUNDS: usize = 1_000_000; /// let mut deltas_variable: Vec = Vec::with_capacity(ROUNDS); /// let mut deltas_minimal: Vec = Vec::with_capacity(ROUNDS); /// /// for _ in 0..ROUNDS { /// deltas_variable.push(rng.timer_stats(true) as u8); /// deltas_minimal.push(rng.timer_stats(false) as u8); /// } /// /// // Write out after the statistics collection loop, to not disturb the /// // test results. /// File::create("jitter_rng_var.bin")?.write(&deltas_variable)?; /// File::create("jitter_rng_min.bin")?.write(&deltas_minimal)?; /// # /// # Ok(()) /// # } /// # /// # fn main() { /// # try_main().unwrap(); /// # } /// ``` /// /// This will produce two files: `jitter_rng_var.bin` and `jitter_rng_min.bin`. /// Run the Entropy Estimation Suite in three configurations, as outlined below. /// Every run has two steps. One step to produce an estimation, another to /// validate the estimation. /// /// 1. Estimate the expected amount of entropy that is at least available with /// each round of the entropy collector. This number should be greater than /// the amount estimated with `64 / test_timer()`. /// ```sh /// python noniid_main.py -v jitter_rng_var.bin 8 /// restart.py -v jitter_rng_var.bin 8 /// ``` /// 2. Estimate the expected amount of entropy that is available in the last 4 /// bits of the timer delta after running noice sources. Note that a value of /// `3.70` is the minimum estimated entropy for true randomness. /// ```sh /// python noniid_main.py -v -u 4 jitter_rng_var.bin 4 /// restart.py -v -u 4 jitter_rng_var.bin 4 /// ``` /// 3. Estimate the expected amount of entropy that is available to the entropy /// collector if both noice sources only run their minimal number of times. /// This measures the absolute worst-case, and gives a lower bound for the /// available entropy. /// ```sh /// python noniid_main.py -v -u 4 jitter_rng_min.bin 4 /// restart.py -v -u 4 jitter_rng_min.bin 4 /// ``` /// /// [`OsRng`]: struct.OsRng.html /// [`JitterRng::new()`]: struct.JitterRng.html#method.new /// [`new_with_timer`]: struct.JitterRng.html#method.new_with_timer /// [`timer_stats`]: struct.JitterRng.html#method.timer_stats pub struct JitterRng { data: u64, // Actual random number // Number of rounds to run the entropy collector per 64 bits rounds: u8, // Timer used by `measure_jitter` timer: fn() -> u64, // Memory for the Memory Access noise source mem_prev_index: u16, // Make `next_u32` not waste 32 bits data_half_used: bool, } // Note: `JitterRng` maintains a small 64-bit entropy pool. With every // `generate` 64 new bits should be integrated in the pool. If a round of // `generate` were to collect less than the expected 64 bit, then the returned // value, and the new state of the entropy pool, would be in some way related to // the initial state. It is therefore better if the initial state of the entropy // pool is different on each call to `generate`. This has a few implications: // - `generate` should be called once before using `JitterRng` to produce the // first usable value (this is done by default in `new`); // - We do not zero the entropy pool after generating a result. The reference // implementation also does not support zeroing, but recommends generating a // new value without using it if you want to protect a previously generated // 'secret' value from someone inspecting the memory; // - Implementing `Clone` seems acceptable, as it would not cause the systematic // bias a constant might cause. Only instead of one value that could be // potentially related to the same initial state, there are now two. // Entropy collector state. // These values are not necessary to preserve across runs. struct EcState { // Previous time stamp to determine the timer delta prev_time: u64, // Deltas used for the stuck test last_delta: i32, last_delta2: i32, // Memory for the Memory Access noise source mem: [u8; MEMORY_SIZE], } impl EcState { // Stuck test by checking the: // - 1st derivation of the jitter measurement (time delta) // - 2nd derivation of the jitter measurement (delta of time deltas) // - 3rd derivation of the jitter measurement (delta of delta of time // deltas) // // All values must always be non-zero. // This test is a heuristic to see whether the last measurement holds // entropy. fn stuck(&mut self, current_delta: i32) -> bool { let delta2 = self.last_delta - current_delta; let delta3 = delta2 - self.last_delta2; self.last_delta = current_delta; self.last_delta2 = delta2; current_delta == 0 || delta2 == 0 || delta3 == 0 } } // Custom Debug implementation that does not expose the internal state impl fmt::Debug for JitterRng { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "JitterRng {{}}") } } impl Clone for JitterRng { fn clone(&self) -> JitterRng { JitterRng { data: self.data, rounds: self.rounds, timer: self.timer, mem_prev_index: self.mem_prev_index, // The 32 bits that may still be unused from the previous round are // for the original to use, not for the clone. data_half_used: false, } } } /// An error that can occur when [`JitterRng::test_timer`] fails. /// /// [`JitterRng::test_timer`]: struct.JitterRng.html#method.test_timer #[derive(Debug, Clone, PartialEq, Eq)] pub enum TimerError { /// No timer available. NoTimer, /// Timer too coarse to use as an entropy source. CoarseTimer, /// Timer is not monotonically increasing. NotMonotonic, /// Variations of deltas of time too small. TinyVariantions, /// Too many stuck results (indicating no added entropy). TooManyStuck, #[doc(hidden)] __Nonexhaustive, } impl TimerError { fn description(&self) -> &'static str { match *self { TimerError::NoTimer => "no timer available", TimerError::CoarseTimer => "coarse timer", TimerError::NotMonotonic => "timer not monotonic", TimerError::TinyVariantions => "time delta variations too small", TimerError::TooManyStuck => "too many stuck results", TimerError::__Nonexhaustive => unreachable!(), } } } impl fmt::Display for TimerError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) } } #[cfg(feature="std")] impl ::std::error::Error for TimerError { fn description(&self) -> &str { self.description() } } impl From for Error { fn from(err: TimerError) -> Error { // Timer check is already quite permissive of failures so we don't // expect false-positive failures, i.e. any error is irrecoverable. Error::with_cause(ErrorKind::Unavailable, "timer jitter failed basic quality tests", err) } } // Initialise to zero; must be positive #[cfg(all(feature="std", not(target_arch = "wasm32")))] static JITTER_ROUNDS: AtomicUsize = ATOMIC_USIZE_INIT; impl JitterRng { /// Create a new `JitterRng`. Makes use of `std::time` for a timer, or a /// platform-specific function with higher accuracy if necessary and /// available. /// /// During initialization CPU execution timing jitter is measured a few /// hundred times. If this does not pass basic quality tests, an error is /// returned. The test result is cached to make subsequent calls faster. #[cfg(all(feature="std", not(target_arch = "wasm32")))] pub fn new() -> Result { let mut state = JitterRng::new_with_timer(platform::get_nstime); let mut rounds = JITTER_ROUNDS.load(Ordering::Relaxed) as u8; if rounds == 0 { // No result yet: run test. // This allows the timer test to run multiple times; we don't care. rounds = state.test_timer()?; JITTER_ROUNDS.store(rounds as usize, Ordering::Relaxed); info!("JitterRng: using {} rounds per u64 output", rounds); } state.set_rounds(rounds); // Fill `data` with a non-zero value. state.gen_entropy(); Ok(state) } /// Create a new `JitterRng`. /// A custom timer can be supplied, making it possible to use `JitterRng` in /// `no_std` environments. /// /// The timer must have nanosecond precision. /// /// This method is more low-level than `new()`. It is the responsibility of /// the caller to run [`test_timer`] before using any numbers generated with /// `JitterRng`, and optionally call [`set_rounds`]. Also it is important to /// consume at least one `u64` before using the first result to initialize /// the entropy collection pool. /// /// # Example /// /// ``` /// # use rand::{Rng, Error}; /// use rand::jitter::JitterRng; /// /// # fn try_inner() -> Result<(), Error> { /// fn get_nstime() -> u64 { /// use std::time::{SystemTime, UNIX_EPOCH}; /// /// let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); /// // The correct way to calculate the current time is /// // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64` /// // But this is faster, and the difference in terms of entropy is /// // negligible (log2(10^9) == 29.9). /// dur.as_secs() << 30 | dur.subsec_nanos() as u64 /// } /// /// let mut rng = JitterRng::new_with_timer(get_nstime); /// let rounds = rng.test_timer()?; /// rng.set_rounds(rounds); // optional /// let _ = rng.gen::(); /// /// // Ready for use /// let v: u64 = rng.gen(); /// # Ok(()) /// # } /// /// # let _ = try_inner(); /// ``` /// /// [`test_timer`]: struct.JitterRng.html#method.test_timer /// [`set_rounds`]: struct.JitterRng.html#method.set_rounds pub fn new_with_timer(timer: fn() -> u64) -> JitterRng { JitterRng { data: 0, rounds: 64, timer, mem_prev_index: 0, data_half_used: false, } } /// Configures how many rounds are used to generate each 64-bit value. /// This must be greater than zero, and has a big impact on performance /// and output quality. /// /// [`new_with_timer`] conservatively uses 64 rounds, but often less rounds /// can be used. The `test_timer()` function returns the minimum number of /// rounds required for full strength (platform dependent), so one may use /// `rng.set_rounds(rng.test_timer()?);` or cache the value. /// /// [`new_with_timer`]: struct.JitterRng.html#method.new_with_timer pub fn set_rounds(&mut self, rounds: u8) { assert!(rounds > 0); self.rounds = rounds; } // Calculate a random loop count used for the next round of an entropy // collection, based on bits from a fresh value from the timer. // // The timer is folded to produce a number that contains at most `n_bits` // bits. // // Note: A constant should be added to the resulting random loop count to // prevent loops that run 0 times. #[inline(never)] fn random_loop_cnt(&mut self, n_bits: u32) -> u32 { let mut rounds = 0; let mut time = (self.timer)(); // Mix with the current state of the random number balance the random // loop counter a bit more. time ^= self.data; // We fold the time value as much as possible to ensure that as many // bits of the time stamp are included as possible. let folds = (64 + n_bits - 1) / n_bits; let mask = (1 << n_bits) - 1; for _ in 0..folds { rounds ^= time & mask; time >>= n_bits; } rounds as u32 } // CPU jitter noise source // Noise source based on the CPU execution time jitter // // This function injects the individual bits of the time value into the // entropy pool using an LFSR. // // The code is deliberately inefficient with respect to the bit shifting. // This function not only acts as folding operation, but this function's // execution is used to measure the CPU execution time jitter. Any change to // the loop in this function implies that careful retesting must be done. #[inline(never)] fn lfsr_time(&mut self, time: u64, var_rounds: bool) { fn lfsr(mut data: u64, time: u64) -> u64{ for i in 1..65 { let mut tmp = time << (64 - i); tmp >>= 64 - 1; // Fibonacci LSFR with polynomial of // x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is // primitive according to // http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf // (the shift values are the polynomial values minus one // due to counting bits from 0 to 63). As the current // position is always the LSB, the polynomial only needs // to shift data in from the left without wrap. data ^= tmp; data ^= (data >> 63) & 1; data ^= (data >> 60) & 1; data ^= (data >> 55) & 1; data ^= (data >> 30) & 1; data ^= (data >> 27) & 1; data ^= (data >> 22) & 1; data = data.rotate_left(1); } data } // Note: in the reference implementation only the last round effects // `self.data`, all the other results are ignored. To make sure the // other rounds are not optimised out, we first run all but the last // round on a throw-away value instead of the real `self.data`. let mut lfsr_loop_cnt = 0; if var_rounds { lfsr_loop_cnt = self.random_loop_cnt(4) }; let mut throw_away: u64 = 0; for _ in 0..lfsr_loop_cnt { throw_away = lfsr(throw_away, time); } black_box(throw_away); self.data = lfsr(self.data, time); } // Memory Access noise source // This is a noise source based on variations in memory access times // // This function performs memory accesses which will add to the timing // variations due to an unknown amount of CPU wait states that need to be // added when accessing memory. The memory size should be larger than the L1 // caches as outlined in the documentation and the associated testing. // // The L1 cache has a very high bandwidth, albeit its access rate is usually // slower than accessing CPU registers. Therefore, L1 accesses only add // minimal variations as the CPU has hardly to wait. Starting with L2, // significant variations are added because L2 typically does not belong to // the CPU any more and therefore a wider range of CPU wait states is // necessary for accesses. L3 and real memory accesses have even a wider // range of wait states. However, to reliably access either L3 or memory, // the `self.mem` memory must be quite large which is usually not desirable. #[inline(never)] fn memaccess(&mut self, mem: &mut [u8; MEMORY_SIZE], var_rounds: bool) { let mut acc_loop_cnt = 128; if var_rounds { acc_loop_cnt += self.random_loop_cnt(4) }; let mut index = self.mem_prev_index as usize; for _ in 0..acc_loop_cnt { // Addition of memblocksize - 1 to index with wrap around logic to // ensure that every memory location is hit evenly. // The modulus also allows the compiler to remove the indexing // bounds check. index = (index + MEMORY_BLOCKSIZE - 1) % MEMORY_SIZE; // memory access: just add 1 to one byte // memory access implies read from and write to memory location mem[index] = mem[index].wrapping_add(1); } self.mem_prev_index = index as u16; } // This is the heart of the entropy generation: calculate time deltas and // use the CPU jitter in the time deltas. The jitter is injected into the // entropy pool. // // Ensure that `ec.prev_time` is primed before using the output of this // function. This can be done by calling this function and not using its // result. fn measure_jitter(&mut self, ec: &mut EcState) -> Option<()> { // Invoke one noise source before time measurement to add variations self.memaccess(&mut ec.mem, true); // Get time stamp and calculate time delta to previous // invocation to measure the timing variations let time = (self.timer)(); // Note: wrapping_sub combined with a cast to `i64` generates a correct // delta, even in the unlikely case this is a timer that is not strictly // monotonic. let current_delta = time.wrapping_sub(ec.prev_time) as i64 as i32; ec.prev_time = time; // Call the next noise source which also injects the data self.lfsr_time(current_delta as u64, true); // Check whether we have a stuck measurement (i.e. does the last // measurement holds entropy?). if ec.stuck(current_delta) { return None }; // Rotate the data buffer by a prime number (any odd number would // do) to ensure that every bit position of the input time stamp // has an even chance of being merged with a bit position in the // entropy pool. We do not use one here as the adjacent bits in // successive time deltas may have some form of dependency. The // chosen value of 7 implies that the low 7 bits of the next // time delta value is concatenated with the current time delta. self.data = self.data.rotate_left(7); Some(()) } // Shuffle the pool a bit by mixing some value with a bijective function // (XOR) into the pool. // // The function generates a mixer value that depends on the bits set and // the location of the set bits in the random number generated by the // entropy source. Therefore, based on the generated random number, this // mixer value can have 2^64 different values. That mixer value is // initialized with the first two SHA-1 constants. After obtaining the // mixer value, it is XORed into the random number. // // The mixer value is not assumed to contain any entropy. But due to the // XOR operation, it can also not destroy any entropy present in the // entropy pool. #[inline(never)] fn stir_pool(&mut self) { // This constant is derived from the first two 32 bit initialization // vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1 // The order does not really matter as we do not rely on the specific // numbers. We just pick the SHA-1 constants as they have a good mix of // bit set and unset. const CONSTANT: u64 = 0x67452301efcdab89; // The start value of the mixer variable is derived from the third // and fourth 32 bit initialization vector of SHA-1 as defined in // FIPS 180-4 section 5.3.1 let mut mixer = 0x98badcfe10325476; // This is a constant time function to prevent leaking timing // information about the random number. // The normal code is: // ``` // for i in 0..64 { // if ((self.data >> i) & 1) == 1 { mixer ^= CONSTANT; } // } // ``` // This is a bit fragile, as LLVM really wants to use branches here, and // we rely on it to not recognise the opportunity. for i in 0..64 { let apply = (self.data >> i) & 1; let mask = !apply.wrapping_sub(1); mixer ^= CONSTANT & mask; mixer = mixer.rotate_left(1); } self.data ^= mixer; } fn gen_entropy(&mut self) -> u64 { trace!("JitterRng: collecting entropy"); // Prime `ec.prev_time`, and run the noice sources to make sure the // first loop round collects the expected entropy. let mut ec = EcState { prev_time: (self.timer)(), last_delta: 0, last_delta2: 0, mem: [0; MEMORY_SIZE], }; let _ = self.measure_jitter(&mut ec); for _ in 0..self.rounds { // If a stuck measurement is received, repeat measurement // Note: we do not guard against an infinite loop, that would mean // the timer suddenly became broken. while self.measure_jitter(&mut ec).is_none() {} } // Do a single read from `self.mem` to make sure the Memory Access noise // source is not optimised out. black_box(ec.mem[0]); self.stir_pool(); self.data } /// Basic quality tests on the timer, by measuring CPU timing jitter a few /// hundred times. /// /// If succesful, this will return the estimated number of rounds necessary /// to collect 64 bits of entropy. Otherwise a [`TimerError`] with the cause /// of the failure will be returned. /// /// [`TimerError`]: enum.TimerError.html pub fn test_timer(&mut self) -> Result { debug!("JitterRng: testing timer ..."); // We could add a check for system capabilities such as `clock_getres` // or check for `CONFIG_X86_TSC`, but it does not make much sense as the // following sanity checks verify that we have a high-resolution timer. let mut delta_sum = 0; let mut old_delta = 0; let mut time_backwards = 0; let mut count_mod = 0; let mut count_stuck = 0; let mut ec = EcState { prev_time: (self.timer)(), last_delta: 0, last_delta2: 0, mem: [0; MEMORY_SIZE], }; // TESTLOOPCOUNT needs some loops to identify edge systems. // 100 is definitely too little. const TESTLOOPCOUNT: u64 = 300; const CLEARCACHE: u64 = 100; for i in 0..(CLEARCACHE + TESTLOOPCOUNT) { // Measure time delta of core entropy collection logic let time = (self.timer)(); self.memaccess(&mut ec.mem, true); self.lfsr_time(time, true); let time2 = (self.timer)(); // Test whether timer works if time == 0 || time2 == 0 { return Err(TimerError::NoTimer); } let delta = time2.wrapping_sub(time) as i64 as i32; // Test whether timer is fine grained enough to provide delta even // when called shortly after each other -- this implies that we also // have a high resolution timer if delta == 0 { return Err(TimerError::CoarseTimer); } // Up to here we did not modify any variable that will be // evaluated later, but we already performed some work. Thus we // already have had an impact on the caches, branch prediction, // etc. with the goal to clear it to get the worst case // measurements. if i < CLEARCACHE { continue; } if ec.stuck(delta) { count_stuck += 1; } // Test whether we have an increasing timer. if !(time2 > time) { time_backwards += 1; } // Count the number of times the counter increases in steps of 100ns // or greater. if (delta % 100) == 0 { count_mod += 1; } // Ensure that we have a varying delta timer which is necessary for // the calculation of entropy -- perform this check only after the // first loop is executed as we need to prime the old_delta value delta_sum += (delta - old_delta).abs() as u64; old_delta = delta; } // Do a single read from `self.mem` to make sure the Memory Access noise // source is not optimised out. black_box(ec.mem[0]); // We allow the time to run backwards for up to three times. // This can happen if the clock is being adjusted by NTP operations. // If such an operation just happens to interfere with our test, it // should not fail. The value of 3 should cover the NTP case being // performed during our test run. if time_backwards > 3 { return Err(TimerError::NotMonotonic); } // Test that the available amount of entropy per round does not get to // low. We expect 1 bit of entropy per round as a reasonable minimum // (although less is possible, it means the collector loop has to run // much more often). // `assert!(delta_average >= log2(1))` // `assert!(delta_sum / TESTLOOPCOUNT >= 1)` // `assert!(delta_sum >= TESTLOOPCOUNT)` if delta_sum < TESTLOOPCOUNT { return Err(TimerError::TinyVariantions); } // Ensure that we have variations in the time stamp below 100 for at // least 10% of all checks -- on some platforms, the counter increments // in multiples of 100, but not always if count_mod > (TESTLOOPCOUNT * 9 / 10) { return Err(TimerError::CoarseTimer); } // If we have more than 90% stuck results, then this Jitter RNG is // likely to not work well. if count_stuck > (TESTLOOPCOUNT * 9 / 10) { return Err(TimerError::TooManyStuck); } // Estimate the number of `measure_jitter` rounds necessary for 64 bits // of entropy. // // We don't try very hard to come up with a good estimate of the // available bits of entropy per round here for two reasons: // 1. Simple estimates of the available bits (like Shannon entropy) are // too optimistic. // 2. Unless we want to waste a lot of time during intialization, there // only a small number of samples are available. // // Therefore we use a very simple and conservative estimate: // `let bits_of_entropy = log2(delta_average) / 2`. // // The number of rounds `measure_jitter` should run to collect 64 bits // of entropy is `64 / bits_of_entropy`. let delta_average = delta_sum / TESTLOOPCOUNT; if delta_average >= 16 { let log2 = 64 - delta_average.leading_zeros(); // Do something similar to roundup(64/(log2/2)): Ok( ((64u32 * 2 + log2 - 1) / log2) as u8) } else { // For values < 16 the rounding error becomes too large, use a // lookup table. // Values 0 and 1 are invalid, and filtered out by the // `delta_sum < TESTLOOPCOUNT` test above. let log2_lookup = [0, 0, 128, 81, 64, 56, 50, 46, 43, 41, 39, 38, 36, 35, 34, 33]; Ok(log2_lookup[delta_average as usize]) } } /// Statistical test: return the timer delta of one normal run of the /// `JitterRng` entropy collector. /// /// Setting `var_rounds` to `true` will execute the memory access and the /// CPU jitter noice sources a variable amount of times (just like a real /// `JitterRng` round). /// /// Setting `var_rounds` to `false` will execute the noice sources the /// minimal number of times. This can be used to measure the minimum amount /// of entropy one round of the entropy collector can collect in the worst /// case. /// /// See [Quality testing](struct.JitterRng.html#quality-testing) on how to /// use `timer_stats` to test the quality of `JitterRng`. pub fn timer_stats(&mut self, var_rounds: bool) -> i64 { let mut mem = [0; MEMORY_SIZE]; let time = (self.timer)(); self.memaccess(&mut mem, var_rounds); self.lfsr_time(time, var_rounds); let time2 = (self.timer)(); time2.wrapping_sub(time) as i64 } } #[cfg(feature="std")] mod platform { #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows", target_arch = "wasm32")))] pub fn get_nstime() -> u64 { use std::time::{SystemTime, UNIX_EPOCH}; let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); // The correct way to calculate the current time is // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64` // But this is faster, and the difference in terms of entropy is // negligible (log2(10^9) == 29.9). dur.as_secs() << 30 | dur.subsec_nanos() as u64 } #[cfg(any(target_os = "macos", target_os = "ios"))] pub fn get_nstime() -> u64 { extern crate libc; // On Mac OS and iOS std::time::SystemTime only has 1000ns resolution. // We use `mach_absolute_time` instead. This provides a CPU dependent // unit, to get real nanoseconds the result should by multiplied by // numer/denom from `mach_timebase_info`. // But we are not interested in the exact nanoseconds, just entropy. So // we use the raw result. unsafe { libc::mach_absolute_time() } } #[cfg(target_os = "windows")] pub fn get_nstime() -> u64 { extern crate winapi; unsafe { let mut t = super::mem::zeroed(); winapi::um::profileapi::QueryPerformanceCounter(&mut t); *t.QuadPart() as u64 } } } // A function that is opaque to the optimizer to assist in avoiding dead-code // elimination. Taken from `bencher`. fn black_box(dummy: T) -> T { unsafe { let ret = ptr::read_volatile(&dummy); mem::forget(dummy); ret } } impl RngCore for JitterRng { fn next_u32(&mut self) -> u32 { // We want to use both parts of the generated entropy if self.data_half_used { self.data_half_used = false; (self.data >> 32) as u32 } else { self.data = self.next_u64(); self.data_half_used = true; self.data as u32 } } fn next_u64(&mut self) -> u64 { self.data_half_used = false; self.gen_entropy() } fn fill_bytes(&mut self, dest: &mut [u8]) { // Fill using `next_u32`. This is faster for filling small slices (four // bytes or less), while the overhead is negligible. // // This is done especially for wrappers that implement `next_u32` // themselves via `fill_bytes`. impls::fill_bytes_via_next(self, dest) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { Ok(self.fill_bytes(dest)) } } impl CryptoRng for JitterRng {} #[cfg(test)] mod test_jitter_init { use jitter::JitterRng; #[cfg(all(feature="std", not(target_arch = "wasm32")))] #[test] fn test_jitter_init() { use RngCore; // Because this is a debug build, measurements here are not representive // of the final release build. // Don't fail this test if initializing `JitterRng` fails because of a // bad timer (the timer from the standard library may not have enough // accuracy on all platforms). match JitterRng::new() { Ok(ref mut rng) => { // false positives are possible, but extremely unlikely assert!(rng.next_u32() | rng.next_u32() != 0); }, Err(_) => {}, } } #[test] fn test_jitter_bad_timer() { fn bad_timer() -> u64 { 0 } let mut rng = JitterRng::new_with_timer(bad_timer); assert!(rng.test_timer().is_err()); } } rand-0.5.5/src/rngs/mock.rs010064400017500001750000000033621331042026600137260ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 { fn next_u32(&mut self) -> u32 { self.next_u64() as u32 } fn next_u64(&mut self) -> u64 { let result = self.v; self.v = self.v.wrapping_add(self.a); result } fn fill_bytes(&mut self, dest: &mut [u8]) { impls::fill_bytes_via_next(self, dest); } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { Ok(self.fill_bytes(dest)) } } rand-0.5.5/src/rngs/mod.rs010064400017500001750000000217611333210603300135540ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 for common usage: //! //! - [`ThreadRng`], a fast, secure, auto-seeded thread-local generator //! - [`StdRng`] and [`SmallRng`], algorithms to cover typical usage //! - [`EntropyRng`], [`OsRng`] and [`JitterRng`] as entropy sources //! - [`mock::StepRng`] as a simple counter for tests //! - [`adapter::ReadRng`] to read from a file/stream //! //! # Background — Random number generators (RNGs) //! //! Computers are inherently deterministic, so to get *random* numbers one //! either has to use a hardware generator or collect bits of *entropy* from //! various sources (e.g. event timestamps, or jitter). This is a relatively //! slow and complicated operation. //! //! Generally the operating system will collect some entropy, remove bias, and //! use that to seed its own PRNG; [`OsRng`] provides an interface to this. //! [`JitterRng`] is an entropy collector included with Rand that measures //! jitter in the CPU execution time, and jitter in memory access time. //! [`EntropyRng`] is a wrapper that uses the best entropy source that is //! available. //! //! ## Pseudo-random number generators //! //! What is commonly used instead of "true" random number renerators, are //! *pseudo-random number generators* (PRNGs), deterministic algorithms that //! produce an infinite stream of pseudo-random numbers from a small random //! seed. PRNGs are faster, and have better provable properties. The numbers //! produced can be statistically of very high quality and can be impossible to //! predict. (They can also have obvious correlations and be trivial to predict; //! quality varies.) //! //! There are two different types of PRNGs: those developed for simulations //! and statistics, and those developed for use in cryptography; the latter are //! called Cryptographically Secure PRNGs (CSPRNG or CPRNG). Both types can //! have good statistical quality but the latter also have to be impossible to //! predict, even after seeing many previous output values. Rand provides a good //! default algorithm from each class: //! //! - [`SmallRng`] is a PRNG chosen for low memory usage, high performance and //! good statistical quality. //! The current algorithm (plain Xorshift) unfortunately performs //! poorly in statistical quality test suites (TestU01 and PractRand) and will //! be replaced in the next major release. //! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security //! (based on reviews, maturity and usage). The current algorithm is HC-128, //! which is one of the recommendations by ECRYPT's eSTREAM project. //! //! The above PRNGs do not cover all use-cases; more algorithms can be found in //! the [`prng` module], as well as in several other crates. For example, you //! may wish a CSPRNG with significantly lower memory usage than [`StdRng`] //! while being less concerned about performance, in which case [`ChaChaRng`] //! is a good choice. //! //! One complexity is that the internal state of a PRNG must change with every //! generated number. For APIs this generally means a mutable reference to the //! state of the PRNG has to be passed around. //! //! A solution is [`ThreadRng`]. This is a thread-local implementation of //! [`StdRng`] with automatic seeding on first use. It is the best choice if you //! "just" want a convenient, secure, fast random number source. Use via the //! [`thread_rng`] function, which gets a reference to the current thread's //! local instance. //! //! ## Seeding //! //! As mentioned above, PRNGs require a random seed in order to produce random //! output. This is especially important for CSPRNGs, which are still //! deterministic algorithms, thus can only be secure if their seed value is //! also secure. To seed a PRNG, use one of: //! //! - [`FromEntropy::from_entropy`]; this is the most convenient way to seed //! with fresh, secure random data. //! - [`SeedableRng::from_rng`]; this allows seeding from another PRNG or //! from an entropy source such as [`EntropyRng`]. //! - [`SeedableRng::from_seed`]; this is mostly useful if you wish to be able //! to reproduce the output sequence by using a fixed seed. (Don't use //! [`StdRng`] or [`SmallRng`] in this case since different algorithms may be //! used by future versions of Rand; use an algorithm from the //! [`prng` module].) //! //! ## Conclusion //! //! - [`thread_rng`] is what you often want to use. //! - If you want more control, flexibility, or better performance, use //! [`StdRng`], [`SmallRng`] or an algorithm from the [`prng` module]. //! - Use [`FromEntropy::from_entropy`] to seed new PRNGs. //! - If you need reproducibility, use [`SeedableRng::from_seed`] combined with //! a named PRNG. //! //! More information and notes on cryptographic security can be found //! in the [`prng` module]. //! //! ## Examples //! //! Examples of seeding PRNGs: //! //! ``` //! use rand::prelude::*; //! # use rand::Error; //! //! // StdRng seeded securely by the OS or local entropy collector: //! let mut rng = StdRng::from_entropy(); //! # let v: u32 = rng.gen(); //! //! // SmallRng seeded from thread_rng: //! # fn try_inner() -> Result<(), Error> { //! let mut rng = SmallRng::from_rng(thread_rng())?; //! # let v: u32 = rng.gen(); //! # Ok(()) //! # } //! # try_inner().unwrap(); //! //! // SmallRng seeded by a constant, for deterministic results: //! let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; // byte array //! let mut rng = SmallRng::from_seed(seed); //! # let v: u32 = rng.gen(); //! ``` //! //! //! # Implementing custom RNGs //! //! If you want to implement custom RNG, see the [`rand_core`] crate. The RNG //! will have to implement the [`RngCore`] trait, where the [`Rng`] trait is //! build on top of. //! //! If the RNG needs seeding, also implement the [`SeedableRng`] trait. //! //! [`CryptoRng`] is a marker trait cryptographically secure PRNGs can //! implement. //! //! // This module: //! [`ThreadRng`]: struct.ThreadRng.html //! [`StdRng`]: struct.StdRng.html //! [`SmallRng`]: struct.SmallRng.html //! [`EntropyRng`]: struct.EntropyRng.html //! [`OsRng`]: struct.OsRng.html //! [`JitterRng`]: struct.JitterRng.html // Other traits and functions: //! [`rand_core`]: https://crates.io/crates/rand_core //! [`prng` module]: ../prng/index.html //! [`CryptoRng`]: ../trait.CryptoRng.html //! [`FromEntropy`]: ../trait.FromEntropy.html //! [`FromEntropy::from_entropy`]: ../trait.FromEntropy.html#tymethod.from_entropy //! [`RngCore`]: ../trait.RngCore.html //! [`Rng`]: ../trait.Rng.html //! [`SeedableRng`]: ../trait.SeedableRng.html //! [`SeedableRng::from_rng`]: ../trait.SeedableRng.html#tymethod.from_rng //! [`SeedableRng::from_seed`]: ../trait.SeedableRng.html#tymethod.from_seed //! [`thread_rng`]: ../fn.thread_rng.html //! [`mock::StepRng`]: mock/struct.StepRng.html //! [`adapter::ReadRng`]: adapter/struct.ReadRng.html //! [`ChaChaRng`]: ../prng/chacha/struct.ChaChaRng.html pub mod adapter; #[cfg(feature="std")] mod entropy; #[doc(hidden)] pub mod jitter; pub mod mock; // Public so we don't export `StepRng` directly, making it a bit // more clear it is intended for testing. mod small; mod std; #[cfg(feature="std")] pub(crate) mod thread; pub use self::jitter::{JitterRng, TimerError}; #[cfg(feature="std")] pub use self::entropy::EntropyRng; pub use self::small::SmallRng; pub use self::std::StdRng; #[cfg(feature="std")] pub use self::thread::ThreadRng; #[cfg(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") )))] mod os; #[cfg(all(feature="std", any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "haiku", target_os = "emscripten", target_os = "solaris", target_os = "cloudabi", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "bitrig", target_os = "redox", target_os = "fuchsia", windows, all(target_arch = "wasm32", feature = "stdweb") )))] pub use self::os::OsRng; rand-0.5.5/src/rngs/os.rs010064400017500001750000001156221333210603300134160ustar0000000000000000// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! Interface to the random number generator of the operating system. use std::fmt; use rand_core::{CryptoRng, RngCore, Error, impls}; /// A random number generator that retrieves randomness straight from the /// operating system. /// /// This is the preferred external source of entropy for most applications. /// Commonly it is used to initialize a user-space RNG, which can then be used /// to generate random values with much less overhead than `OsRng`. /// /// You may prefer to use [`EntropyRng`] instead of `OsRng`. It is unlikely, but /// not entirely theoretical, for `OsRng` to fail. In such cases [`EntropyRng`] /// falls back on a good alternative entropy source. /// /// `OsRng::new()` is guaranteed to be very cheap (after the first successful /// call), and will never consume more than one file handle per process. /// /// # Platform sources /// /// | OS | interface /// |------------------|--------------------------------------------------------- /// | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after reading from `/dev/random` once /// | Windows | [`RtlGenRandom`][3] /// | macOS, iOS | [`SecRandomCopyBytes`][4] /// | FreeBSD | [`kern.arandom`][5] /// | OpenBSD, Bitrig | [`getentropy`][6] /// | NetBSD | [`/dev/urandom`][7] after reading from `/dev/random` once /// | Dragonfly BSD | [`/dev/random`][8] /// | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10] /// | Fuchsia OS | [`cprng_draw`][11] /// | Redox | [`rand:`][12] /// | CloudABI | [`random_get`][13] /// | Haiku | `/dev/random` (identical to `/dev/urandom`) /// | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14]) /// | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16]) /// /// Rand doesn't have a blanket implementation for all Unix-like operating /// systems that reads from `/dev/urandom`. This ensures all supported operating /// systems are using the recommended interface and respect maximum buffer /// sizes. /// /// ## Support for WebAssembly and ams.js /// /// The three Emscripten targets `asmjs-unknown-emscripten`, /// `wasm32-unknown-emscripten` and `wasm32-experimental-emscripten` use /// Emscripten's emulation of `/dev/random` on web browsers and Node.js. /// Unfortunately it falls back to the insecure `Math.random()` if a browser /// doesn't support [`Crypto.getRandomValues`][12]. /// /// The bare Wasm target `wasm32-unknown-unknown` tries to call the javascript /// methods directly, using `stdweb` in combination with `cargo-web`. /// `wasm-bindgen` is not yet supported. /// /// ## Early boot /// /// It is possible that early in the boot process the OS hasn't had enough time /// yet to collect entropy to securely seed its RNG, especially on virtual /// machines. /// /// Some operating systems always block the thread until the RNG is securely /// seeded. This can take anywhere from a few seconds to more than a minute. /// Others make a best effort to use a seed from before the shutdown and don't /// document much. /// /// A few, Linux, NetBSD and Solaris, offer a choice between blocking, and /// getting an error. With `try_fill_bytes` we choose to get the error /// ([`ErrorKind::NotReady`]), while the other methods use a blocking interface. /// /// On Linux (when the `genrandom` system call is not available) and on NetBSD /// reading from `/dev/urandom` never blocks, even when the OS hasn't collected /// enough entropy yet. As a countermeasure we try to do a single read from /// `/dev/random` until we know the OS RNG is initialized (and store this in a /// global static). /// /// # Panics /// /// `OsRng` is extremely unlikely to fail if `OsRng::new()`, and one read from /// it, where succesfull. But in case it does fail, only [`try_fill_bytes`] is /// able to report the cause. Depending on the error the other [`RngCore`] /// methods will retry several times, and panic in case the error remains. /// /// [`EntropyRng`]: struct.EntropyRng.html /// [`RngCore`]: ../trait.RngCore.html /// [`try_fill_bytes`]: ../trait.RngCore.html#method.tymethod.try_fill_bytes /// [`ErrorKind::NotReady`]: ../enum.ErrorKind.html#variant.NotReady /// /// [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html /// [2]: http://man7.org/linux/man-pages/man4/urandom.4.html /// [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx /// [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc /// [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 /// [6]: https://man.openbsd.org/getentropy.2 /// [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current /// [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4 /// [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html /// [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html /// [11]: https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md /// [12]: https://github.com/redox-os/randd/blob/master/src/main.rs /// [13]: https://github.com/NuxiNL/cloudabi/blob/v0.20/cloudabi.txt#L1826 /// [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues /// [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback /// [16]: #support-for-webassembly-and-amsjs #[derive(Clone)] pub struct OsRng(imp::OsRng); impl fmt::Debug for OsRng { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } impl OsRng { /// Create a new `OsRng`. pub fn new() -> Result { imp::OsRng::new().map(OsRng) } } impl CryptoRng for OsRng {} impl RngCore for OsRng { 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]) { use std::{time, thread}; // We cannot return Err(..), so we try to handle before panicking. const MAX_RETRY_PERIOD: u32 = 10; // max 10s const WAIT_DUR_MS: u32 = 100; // retry every 100ms let wait_dur = time::Duration::from_millis(WAIT_DUR_MS as u64); const RETRY_LIMIT: u32 = (MAX_RETRY_PERIOD * 1000) / WAIT_DUR_MS; const TRANSIENT_RETRIES: u32 = 8; let mut err_count = 0; let mut error_logged = false; // Maybe block until the OS RNG is initialized let mut read = 0; if let Ok(n) = self.0.test_initialized(dest, true) { read = n }; let dest = &mut dest[read..]; loop { if let Err(e) = self.try_fill_bytes(dest) { if err_count >= RETRY_LIMIT { error!("OsRng failed too many times; last error: {}", e); panic!("OsRng failed too many times; last error: {}", e); } if e.kind.should_wait() { if !error_logged { warn!("OsRng failed; waiting up to {}s and retrying. Error: {}", MAX_RETRY_PERIOD, e); error_logged = true; } err_count += 1; thread::sleep(wait_dur); continue; } else if e.kind.should_retry() { if !error_logged { warn!("OsRng failed; retrying up to {} times. Error: {}", TRANSIENT_RETRIES, e); error_logged = true; } err_count += (RETRY_LIMIT + TRANSIENT_RETRIES - 1) / TRANSIENT_RETRIES; // round up continue; } else { error!("OsRng failed: {}", e); panic!("OsRng fatal error: {}", e); } } break; } } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { // Some systems do not support reading 0 random bytes. // (And why waste a system call?) if dest.len() == 0 { return Ok(()); } let read = self.0.test_initialized(dest, false)?; let dest = &mut dest[read..]; let max = self.0.max_chunk_size(); if dest.len() <= max { trace!("OsRng: reading {} bytes via {}", dest.len(), self.0.method_str()); } else { trace!("OsRng: reading {} bytes via {} in {} chunks of {} bytes", dest.len(), self.0.method_str(), (dest.len() + max) / max, max); } for slice in dest.chunks_mut(max) { self.0.fill_chunk(slice)?; } Ok(()) } } trait OsRngImpl where Self: Sized { // Create a new `OsRng` platform interface. fn new() -> Result; // Fill a chunk with random bytes. fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error>; // Test whether the OS RNG is initialized. This method may not be possible // to support cheaply (or at all) on all operating systems. // // If `blocking` is set, this will cause the OS the block execution until // its RNG is initialized. // // Random values that are read while this are stored in `dest`, the amount // of read bytes is returned. fn test_initialized(&mut self, _dest: &mut [u8], _blocking: bool) -> Result { Ok(0) } // Maximum chunk size supported. fn max_chunk_size(&self) -> usize { ::core::usize::MAX } // Name of the OS interface (used for logging). fn method_str(&self) -> &'static str; } // Helper functions to read from a random device such as `/dev/urandom`. // // All instances use a single internal file handle, to prevent possible // exhaustion of file descriptors. #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd", target_os = "dragonfly", target_os = "solaris", target_os = "redox", target_os = "haiku", target_os = "emscripten"))] mod random_device { use {Error, ErrorKind}; use std::fs::File; use std::io; use std::io::Read; use std::sync::{Once, Mutex, ONCE_INIT}; // TODO: remove outer Option when `Mutex::new(None)` is a constant expression static mut READ_RNG_FILE: Option>> = None; static READ_RNG_ONCE: Once = ONCE_INIT; #[allow(unused)] pub fn open(path: &'static str, open_fn: F) -> Result<(), Error> where F: Fn(&'static str) -> Result { READ_RNG_ONCE.call_once(|| { unsafe { READ_RNG_FILE = Some(Mutex::new(None)) } }); // We try opening the file outside the `call_once` fn because we cannot // clone the error, thus we must retry on failure. let mutex = unsafe { READ_RNG_FILE.as_ref().unwrap() }; let mut guard = mutex.lock().unwrap(); if (*guard).is_none() { info!("OsRng: opening random device {}", path); let file = open_fn(path).map_err(map_err)?; *guard = Some(file); }; Ok(()) } pub fn read(dest: &mut [u8]) -> Result<(), Error> { // We expect this function only to be used after `random_device::open` // was succesful. Therefore we can assume that our memory was set with a // valid object. let mutex = unsafe { READ_RNG_FILE.as_ref().unwrap() }; let mut guard = mutex.lock().unwrap(); let file = (*guard).as_mut().unwrap(); // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. file.read_exact(dest).map_err(|err| { Error::with_cause(ErrorKind::Unavailable, "error reading random device", err) }) } pub fn map_err(err: io::Error) -> Error { match err.kind() { io::ErrorKind::Interrupted => Error::new(ErrorKind::Transient, "interrupted"), io::ErrorKind::WouldBlock => Error::with_cause(ErrorKind::NotReady, "OS RNG not yet seeded", err), _ => Error::with_cause(ErrorKind::Unavailable, "error while opening random device", err) } } } #[cfg(any(target_os = "linux", target_os = "android"))] mod imp { extern crate libc; use {Error, ErrorKind}; use super::random_device; use super::OsRngImpl; use std::io; use std::io::Read; use std::fs::{File, OpenOptions}; use std::os::unix::fs::OpenOptionsExt; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use std::sync::{Once, ONCE_INIT}; #[derive(Clone, Debug)] pub struct OsRng { method: OsRngMethod, initialized: bool, } #[derive(Clone, Debug)] enum OsRngMethod { GetRandom, RandomDevice, } impl OsRngImpl for OsRng { fn new() -> Result { if is_getrandom_available() { return Ok(OsRng { method: OsRngMethod::GetRandom, initialized: false }); } random_device::open("/dev/urandom", &|p| File::open(p))?; Ok(OsRng { method: OsRngMethod::RandomDevice, initialized: false }) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { match self.method { OsRngMethod::GetRandom => getrandom_try_fill(dest, false), OsRngMethod::RandomDevice => random_device::read(dest), } } fn test_initialized(&mut self, dest: &mut [u8], blocking: bool) -> Result { static OS_RNG_INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT; if !self.initialized { self.initialized = OS_RNG_INITIALIZED.load(Ordering::Relaxed); } if self.initialized { return Ok(0); } let result = match self.method { OsRngMethod::GetRandom => { getrandom_try_fill(dest, blocking)?; Ok(dest.len()) } OsRngMethod::RandomDevice => { info!("OsRng: testing random device /dev/random"); let mut file = OpenOptions::new() .read(true) .custom_flags(if blocking { 0 } else { libc::O_NONBLOCK }) .open("/dev/random") .map_err(random_device::map_err)?; file.read(&mut dest[..1]).map_err(random_device::map_err)?; Ok(1) } }; OS_RNG_INITIALIZED.store(true, Ordering::Relaxed); self.initialized = true; result } fn method_str(&self) -> &'static str { match self.method { OsRngMethod::GetRandom => "getrandom", OsRngMethod::RandomDevice => "/dev/urandom", } } } #[cfg(target_arch = "x86_64")] const NR_GETRANDOM: libc::c_long = 318; #[cfg(target_arch = "x86")] const NR_GETRANDOM: libc::c_long = 355; #[cfg(target_arch = "arm")] const NR_GETRANDOM: libc::c_long = 384; #[cfg(target_arch = "aarch64")] const NR_GETRANDOM: libc::c_long = 278; #[cfg(target_arch = "s390x")] const NR_GETRANDOM: libc::c_long = 349; #[cfg(target_arch = "powerpc")] const NR_GETRANDOM: libc::c_long = 359; #[cfg(target_arch = "mips")] // old ABI const NR_GETRANDOM: libc::c_long = 4353; #[cfg(target_arch = "mips64")] const NR_GETRANDOM: libc::c_long = 5313; #[cfg(not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm", target_arch = "aarch64", target_arch = "s390x", target_arch = "powerpc", target_arch = "mips", target_arch = "mips64")))] const NR_GETRANDOM: libc::c_long = 0; fn getrandom(buf: &mut [u8], blocking: bool) -> libc::c_long { extern "C" { fn syscall(number: libc::c_long, ...) -> libc::c_long; } const GRND_NONBLOCK: libc::c_uint = 0x0001; if NR_GETRANDOM == 0 { return -1 }; unsafe { syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), if blocking { 0 } else { GRND_NONBLOCK }) } } fn getrandom_try_fill(dest: &mut [u8], blocking: bool) -> Result<(), Error> { let mut read = 0; while read < dest.len() { let result = getrandom(&mut dest[read..], blocking); if result == -1 { let err = io::Error::last_os_error(); let kind = err.kind(); if kind == io::ErrorKind::Interrupted { continue; } else if kind == io::ErrorKind::WouldBlock { return Err(Error::with_cause( ErrorKind::NotReady, "getrandom not ready", err, )); } else { return Err(Error::with_cause( ErrorKind::Unavailable, "unexpected getrandom error", err, )); } } else { read += result as usize; } } Ok(()) } fn is_getrandom_available() -> bool { static CHECKER: Once = ONCE_INIT; static AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT; if NR_GETRANDOM == 0 { return false }; CHECKER.call_once(|| { debug!("OsRng: testing getrandom"); let mut buf: [u8; 0] = []; let result = getrandom(&mut buf, false); let available = if result == -1 { let err = io::Error::last_os_error().raw_os_error(); err != Some(libc::ENOSYS) } else { true }; AVAILABLE.store(available, Ordering::Relaxed); info!("OsRng: using {}", if available { "getrandom" } else { "/dev/urandom" }); }); AVAILABLE.load(Ordering::Relaxed) } } #[cfg(target_os = "netbsd")] mod imp { use Error; use super::random_device; use super::OsRngImpl; use std::fs::File; use std::io::Read; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; #[derive(Clone, Debug)] pub struct OsRng { initialized: bool } impl OsRngImpl for OsRng { fn new() -> Result { random_device::open("/dev/urandom", &|p| File::open(p))?; Ok(OsRng { initialized: false }) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { random_device::read(dest) } // Read a single byte from `/dev/random` to determine if the OS RNG is // already seeded. NetBSD always blocks if not yet ready. fn test_initialized(&mut self, dest: &mut [u8], _blocking: bool) -> Result { static OS_RNG_INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT; if !self.initialized { self.initialized = OS_RNG_INITIALIZED.load(Ordering::Relaxed); } if self.initialized { return Ok(0); } info!("OsRng: testing random device /dev/random"); let mut file = File::open("/dev/random").map_err(random_device::map_err)?; file.read(&mut dest[..1]).map_err(random_device::map_err)?; OS_RNG_INITIALIZED.store(true, Ordering::Relaxed); self.initialized = true; Ok(1) } fn method_str(&self) -> &'static str { "/dev/urandom" } } } #[cfg(any(target_os = "dragonfly", target_os = "haiku", target_os = "emscripten"))] mod imp { use Error; use super::random_device; use super::OsRngImpl; use std::fs::File; #[derive(Clone, Debug)] pub struct OsRng(); impl OsRngImpl for OsRng { fn new() -> Result { random_device::open("/dev/random", &|p| File::open(p))?; Ok(OsRng()) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { random_device::read(dest) } #[cfg(target_os = "emscripten")] fn max_chunk_size(&self) -> usize { // `Crypto.getRandomValues` documents `dest` should be at most 65536 // bytes. `crypto.randomBytes` documents: "To minimize threadpool // task length variation, partition large randomBytes requests when // doing so as part of fulfilling a client request. 65536 } fn method_str(&self) -> &'static str { "/dev/random" } } } // Read from `/dev/random`, with chunks of limited size (1040 bytes). // `/dev/random` uses the Hash_DRBG with SHA512 algorithm from NIST SP 800-90A. // `/dev/urandom` uses the FIPS 186-2 algorithm, which is considered less // secure. We choose to read from `/dev/random`. // // Since Solaris 11.3 the `getrandom` syscall is available. To make sure we can // compile on both Solaris and on OpenSolaris derivatives, that do not have the // function, we do a direct syscall instead of calling a library function. // // We have no way to differentiate between Solaris, illumos, SmartOS, etc. #[cfg(target_os = "solaris")] mod imp { extern crate libc; use {Error, ErrorKind}; use super::random_device; use super::OsRngImpl; use std::io; use std::io::Read; use std::fs::{File, OpenOptions}; use std::os::unix::fs::OpenOptionsExt; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; #[derive(Clone, Debug)] pub struct OsRng { method: OsRngMethod, initialized: bool, } #[derive(Clone, Debug)] enum OsRngMethod { GetRandom, RandomDevice, } impl OsRngImpl for OsRng { fn new() -> Result { if is_getrandom_available() { return Ok(OsRng { method: OsRngMethod::GetRandom, initialized: false }); } let open = |p| OpenOptions::new() .read(true) .custom_flags(libc::O_NONBLOCK) .open(p); random_device::open("/dev/random", &open)?; Ok(OsRng { method: OsRngMethod::RandomDevice, initialized: false }) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { match self.method { OsRngMethod::GetRandom => getrandom_try_fill(dest, false), OsRngMethod::RandomDevice => random_device::read(dest), } } fn test_initialized(&mut self, dest: &mut [u8], blocking: bool) -> Result { static OS_RNG_INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT; if !self.initialized { self.initialized = OS_RNG_INITIALIZED.load(Ordering::Relaxed); } if self.initialized { return Ok(0); } let chunk_len = ::core::cmp::min(1024, dest.len()); let dest = &mut dest[..chunk_len]; match self.method { OsRngMethod::GetRandom => getrandom_try_fill(dest, blocking)?, OsRngMethod::RandomDevice => { if blocking { info!("OsRng: testing random device /dev/random"); // We already have a non-blocking handle, but now need a // blocking one. Not much choice except opening it twice let mut file = File::open("/dev/random") .map_err(random_device::map_err)?; file.read(dest).map_err(random_device::map_err)?; } else { self.fill_chunk(dest)?; } } }; OS_RNG_INITIALIZED.store(true, Ordering::Relaxed); self.initialized = true; Ok(chunk_len) } fn max_chunk_size(&self) -> usize { // The documentation says 1024 is the maximum for getrandom, but // 1040 for /dev/random. 1024 } fn method_str(&self) -> &'static str { match self.method { OsRngMethod::GetRandom => "getrandom", OsRngMethod::RandomDevice => "/dev/random", } } } fn getrandom(buf: &mut [u8], blocking: bool) -> libc::c_long { extern "C" { fn syscall(number: libc::c_long, ...) -> libc::c_long; } const SYS_GETRANDOM: libc::c_long = 143; const GRND_NONBLOCK: libc::c_uint = 0x0001; const GRND_RANDOM: libc::c_uint = 0x0002; unsafe { syscall(SYS_GETRANDOM, buf.as_mut_ptr(), buf.len(), if blocking { 0 } else { GRND_NONBLOCK } | GRND_RANDOM) } } fn getrandom_try_fill(dest: &mut [u8], blocking: bool) -> Result<(), Error> { let result = getrandom(dest, blocking); if result == -1 || result == 0 { let err = io::Error::last_os_error(); let kind = err.kind(); if kind == io::ErrorKind::WouldBlock { return Err(Error::with_cause( ErrorKind::NotReady, "getrandom not ready", err, )); } else { return Err(Error::with_cause( ErrorKind::Unavailable, "unexpected getrandom error", err, )); } } else if result != dest.len() as i64 { return Err(Error::new(ErrorKind::Unavailable, "unexpected getrandom error")); } Ok(()) } fn is_getrandom_available() -> bool { use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use std::sync::{Once, ONCE_INIT}; static CHECKER: Once = ONCE_INIT; static AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT; CHECKER.call_once(|| { debug!("OsRng: testing getrandom"); let mut buf: [u8; 0] = []; let result = getrandom(&mut buf, false); let available = if result == -1 { let err = io::Error::last_os_error().raw_os_error(); err != Some(libc::ENOSYS) } else { true }; AVAILABLE.store(available, Ordering::Relaxed); info!("OsRng: using {}", if available { "getrandom" } else { "/dev/random" }); }); AVAILABLE.load(Ordering::Relaxed) } } #[cfg(target_os = "cloudabi")] mod imp { extern crate cloudabi; use std::io; use {Error, ErrorKind}; use super::OsRngImpl; #[derive(Clone, Debug)] pub struct OsRng; impl OsRngImpl for OsRng { fn new() -> Result { Ok(OsRng) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { let errno = unsafe { cloudabi::random_get(dest) }; if errno == cloudabi::errno::SUCCESS { Ok(()) } else { // Cloudlibc provides its own `strerror` implementation so we // can use `from_raw_os_error` here. Err(Error::with_cause( ErrorKind::Unavailable, "random_get() system call failed", io::Error::from_raw_os_error(errno as i32), )) } } fn method_str(&self) -> &'static str { "cloudabi::random_get" } } } #[cfg(any(target_os = "macos", target_os = "ios"))] mod imp { extern crate libc; use {Error, ErrorKind}; use super::OsRngImpl; use std::io; use self::libc::{c_int, size_t}; #[derive(Clone, Debug)] pub struct OsRng; enum SecRandom {} #[allow(non_upper_case_globals)] const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom; #[link(name = "Security", kind = "framework")] extern { fn SecRandomCopyBytes(rnd: *const SecRandom, count: size_t, bytes: *mut u8) -> c_int; } impl OsRngImpl for OsRng { fn new() -> Result { Ok(OsRng) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, dest.len() as size_t, dest.as_mut_ptr()) }; if ret == -1 { Err(Error::with_cause( ErrorKind::Unavailable, "couldn't generate random bytes", io::Error::last_os_error())) } else { Ok(()) } } fn method_str(&self) -> &'static str { "SecRandomCopyBytes" } } } #[cfg(target_os = "freebsd")] mod imp { extern crate libc; use {Error, ErrorKind}; use super::OsRngImpl; use std::ptr; use std::io; #[derive(Clone, Debug)] pub struct OsRng; impl OsRngImpl for OsRng { fn new() -> Result { Ok(OsRng) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { let mib = [libc::CTL_KERN, libc::KERN_ARND]; let mut len = dest.len(); let ret = unsafe { libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint, dest.as_mut_ptr() as *mut _, &mut len, ptr::null(), 0) }; if ret == -1 || len != dest.len() { return Err(Error::with_cause( ErrorKind::Unavailable, "kern.arandom sysctl failed", io::Error::last_os_error())); } Ok(()) } fn max_chunk_size(&self) -> usize { 256 } fn method_str(&self) -> &'static str { "kern.arandom" } } } #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] mod imp { extern crate libc; use {Error, ErrorKind}; use super::OsRngImpl; use std::io; #[derive(Clone, Debug)] pub struct OsRng; impl OsRngImpl for OsRng { fn new() -> Result { Ok(OsRng) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { let ret = unsafe { libc::getentropy(dest.as_mut_ptr() as *mut libc::c_void, dest.len()) }; if ret == -1 { return Err(Error::with_cause( ErrorKind::Unavailable, "getentropy failed", io::Error::last_os_error())); } Ok(()) } fn max_chunk_size(&self) -> usize { 256 } fn method_str(&self) -> &'static str { "getentropy" } } } #[cfg(target_os = "redox")] mod imp { use Error; use super::random_device; use super::OsRngImpl; use std::fs::File; #[derive(Clone, Debug)] pub struct OsRng(); impl OsRngImpl for OsRng { fn new() -> Result { random_device::open("rand:", &|p| File::open(p))?; Ok(OsRng()) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { random_device::read(dest) } fn method_str(&self) -> &'static str { "'rand:'" } } } #[cfg(target_os = "fuchsia")] mod imp { extern crate fuchsia_zircon; use {Error, ErrorKind}; use super::OsRngImpl; #[derive(Clone, Debug)] pub struct OsRng; impl OsRngImpl for OsRng { fn new() -> Result { Ok(OsRng) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { let mut read = 0; while read < dest.len() { match fuchsia_zircon::cprng_draw(&mut dest[read..]) { Ok(actual) => read += actual, Err(e) => { return Err(Error::with_cause( ErrorKind::Unavailable, "cprng_draw failed", e.into_io_error())); } }; } Ok(()) } fn max_chunk_size(&self) -> usize { fuchsia_zircon::sys::ZX_CPRNG_DRAW_MAX_LEN } fn method_str(&self) -> &'static str { "cprng_draw" } } } #[cfg(windows)] mod imp { extern crate winapi; use {Error, ErrorKind}; use super::OsRngImpl; use std::io; use self::winapi::shared::minwindef::ULONG; use self::winapi::um::ntsecapi::RtlGenRandom; use self::winapi::um::winnt::PVOID; #[derive(Clone, Debug)] pub struct OsRng; impl OsRngImpl for OsRng { fn new() -> Result { Ok(OsRng) } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { let ret = unsafe { RtlGenRandom(dest.as_mut_ptr() as PVOID, dest.len() as ULONG) }; if ret == 0 { return Err(Error::with_cause( ErrorKind::Unavailable, "couldn't generate random bytes", io::Error::last_os_error())); } Ok(()) } fn max_chunk_size(&self) -> usize { ::max_value() as usize } fn method_str(&self) -> &'static str { "RtlGenRandom" } } } #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten"), feature = "stdweb"))] mod imp { use std::mem; use stdweb::unstable::TryInto; use stdweb::web::error::Error as WebError; use {Error, ErrorKind}; use super::OsRngImpl; #[derive(Clone, Debug)] enum OsRngMethod { Browser, Node } #[derive(Clone, Debug)] pub struct OsRng(OsRngMethod); impl OsRngImpl for OsRng { fn new() -> Result { let result = js! { try { if ( typeof self === "object" && typeof self.crypto === "object" && typeof self.crypto.getRandomValues === "function" ) { return { success: true, ty: 1 }; } if (typeof require("crypto").randomBytes === "function") { return { success: true, ty: 2 }; } return { success: false, error: new Error("not supported") }; } catch(err) { return { success: false, error: err }; } }; if js!{ return @{ result.as_ref() }.success } == true { let ty = js!{ return @{ result }.ty }; if ty == 1 { Ok(OsRng(OsRngMethod::Browser)) } else if ty == 2 { Ok(OsRng(OsRngMethod::Node)) } else { unreachable!() } } else { let err: WebError = js!{ return @{ result }.error }.try_into().unwrap(); Err(Error::with_cause(ErrorKind::Unavailable, "WASM Error", err)) } } fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> { assert_eq!(mem::size_of::(), 4); let len = dest.len() as u32; let ptr = dest.as_mut_ptr() as i32; let result = match self.0 { OsRngMethod::Browser => js! { try { let array = new Uint8Array(@{ len }); self.crypto.getRandomValues(array); HEAPU8.set(array, @{ ptr }); return { success: true }; } catch(err) { return { success: false, error: err }; } }, OsRngMethod::Node => js! { try { let bytes = require("crypto").randomBytes(@{ len }); HEAPU8.set(new Uint8Array(bytes), @{ ptr }); return { success: true }; } catch(err) { return { success: false, error: err }; } } }; if js!{ return @{ result.as_ref() }.success } == true { Ok(()) } else { let err: WebError = js!{ return @{ result }.error }.try_into().unwrap(); Err(Error::with_cause(ErrorKind::Unexpected, "WASM Error", err)) } } fn max_chunk_size(&self) -> usize { 65536 } fn method_str(&self) -> &'static str { match self.0 { OsRngMethod::Browser => "Crypto.getRandomValues", OsRngMethod::Node => "crypto.randomBytes", } } } } #[cfg(test)] mod test { use RngCore; use OsRng; #[test] fn test_os_rng() { let mut r = OsRng::new().unwrap(); r.next_u32(); r.next_u64(); let mut v1 = [0u8; 1000]; r.fill_bytes(&mut v1); let mut v2 = [0u8; 1000]; r.fill_bytes(&mut v2); let mut n_diff_bits = 0; for i in 0..v1.len() { n_diff_bits += (v1[i] ^ v2[i]).count_ones(); } // Check at least 1 bit per byte differs. p(failure) < 1e-1000 with random input. assert!(n_diff_bits >= v1.len() as u32); } #[test] fn test_os_rng_empty() { let mut r = OsRng::new().unwrap(); let mut empty = [0u8; 0]; r.fill_bytes(&mut empty); } #[test] fn test_os_rng_huge() { let mut r = OsRng::new().unwrap(); let mut huge = [0u8; 100_000]; r.fill_bytes(&mut huge); } #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] #[test] fn test_os_rng_tasks() { use std::sync::mpsc::channel; use std::thread; let mut txs = vec!(); for _ in 0..20 { let (tx, rx) = channel(); txs.push(tx); thread::spawn(move|| { // wait until all the tasks are ready to go. rx.recv().unwrap(); // deschedule to attempt to interleave things as much // as possible (XXX: is this a good test?) let mut r = OsRng::new().unwrap(); thread::yield_now(); let mut v = [0u8; 1000]; for _ in 0..100 { r.next_u32(); thread::yield_now(); r.next_u64(); thread::yield_now(); r.fill_bytes(&mut v); thread::yield_now(); } }); } // start all the tasks for tx in txs.iter() { tx.send(()).unwrap(); } } } rand-0.5.5/src/rngs/small.rs010064400017500001750000000064751333210603300141120ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 {RngCore, SeedableRng, Error}; use prng::XorShiftRng; /// An RNG recommended when small state, cheap initialization and good /// performance are required. 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 for [`StdRng`]. /// /// Reproducibility of output from this generator is however not required, thus /// future library versions may use a different internal generator with /// different output. Further, this generator may not be portable and can /// produce different output depending on the architecture. If you require /// reproducible output, use a named RNG, for example [`XorShiftRng`]. /// /// The current algorithm used on all platforms is [Xorshift]. /// /// # Examples /// /// Initializing `SmallRng` with a random seed can be done using [`FromEntropy`]: /// /// ``` /// # use rand::Rng; /// use rand::FromEntropy; /// 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(); /// ``` /// /// [`FromEntropy`]: ../trait.FromEntropy.html /// [`StdRng`]: struct.StdRng.html /// [`thread_rng`]: ../fn.thread_rng.html /// [Xorshift]: ../prng/struct.XorShiftRng.html /// [`XorShiftRng`]: ../prng/struct.XorShiftRng.html #[derive(Clone, Debug)] pub struct SmallRng(XorShiftRng); 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() } 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 SeedableRng for SmallRng { type Seed = ::Seed; fn from_seed(seed: Self::Seed) -> Self { SmallRng(XorShiftRng::from_seed(seed)) } fn from_rng(rng: R) -> Result { XorShiftRng::from_rng(rng).map(SmallRng) } } rand-0.5.5/src/rngs/std.rs010064400017500001750000000050121332655332100135670ustar0000000000000000// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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 {RngCore, CryptoRng, Error, SeedableRng}; use prng::Hc128Rng; /// 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 on all platforms is [HC-128]. /// /// Reproducibility of output from this generator is however not required, thus /// future library versions may use a different internal generator with /// different output. Further, this generator may not be portable and can /// produce different output depending on the architecture. If you require /// reproducible output, use a named RNG, for example [`ChaChaRng`]. /// /// [HC-128]: ../prng/hc128/struct.Hc128Rng.html /// [`ChaChaRng`]: ../prng/chacha/struct.ChaChaRng.html #[derive(Clone, Debug)] pub struct StdRng(Hc128Rng); 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() } 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 SeedableRng for StdRng { type Seed = ::Seed; fn from_seed(seed: Self::Seed) -> Self { StdRng(Hc128Rng::from_seed(seed)) } fn from_rng(rng: R) -> Result { Hc128Rng::from_rng(rng).map(StdRng) } } impl CryptoRng for StdRng {} #[cfg(test)] mod test { use {RngCore, SeedableRng}; use rngs::StdRng; #[test] fn test_stdrng_construction() { 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]; let mut rng1 = StdRng::from_seed(seed); assert_eq!(rng1.next_u64(), 15759097995037006553); let mut rng2 = StdRng::from_rng(rng1).unwrap(); assert_eq!(rng2.next_u64(), 6766915756997287454); } } rand-0.5.5/src/rngs/thread.rs010064400017500001750000000124331333210603300142400ustar0000000000000000// Copyright 2017-2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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::rc::Rc; use {RngCore, CryptoRng, SeedableRng, Error}; use rngs::adapter::ReseedingRng; use rngs::EntropyRng; use prng::hc128::Hc128Core; // 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. // // The additional `Rc` is not strictly neccesary, and could be removed. For now // it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`. // Number of generated bytes after which to reseed `TreadRng`. // // The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB. // We pick a treshold here that is large enough to not reduce the average // performance too much, but also small enough to not make reseeding something // that basically never happens. const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB /// The type returned by [`thread_rng`], essentially just a reference to the /// PRNG in thread-local memory. /// /// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`], /// which is reseeded after generating 32 MiB of random data. A single instance /// is cached per thread and the returned `ThreadRng` is a reference to this /// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use /// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`] /// as required. /// /// Note that the reseeding is done as an extra precaution against entropy /// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an /// attacker would have to either determine most of the RNG's seed or internal /// state, or crack the algorithm used. /// /// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current /// algorithm used is [HC-128], which is an array-based PRNG that trades memory /// usage for better performance. This makes it similar to ISAAC, the algorithm /// used in `ThreadRng` before rand 0.5. /// /// Cloning this handle just produces a new reference to the same thread-local /// generator. /// /// [`thread_rng`]: ../fn.thread_rng.html /// [`ReseedingRng`]: adapter/struct.ReseedingRng.html /// [`StdRng`]: struct.StdRng.html /// [`EntropyRng`]: struct.EntropyRng.html /// [HC-128]: ../prng/hc128/struct.Hc128Rng.html #[derive(Clone, Debug)] pub struct ThreadRng { rng: Rc>>, } thread_local!( static THREAD_RNG_KEY: Rc>> = { let mut entropy_source = EntropyRng::new(); let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err| panic!("could not initialize thread_rng: {}", err)); let rng = ReseedingRng::new(r, THREAD_RNG_RESEED_THRESHOLD, entropy_source); Rc::new(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();`. /// /// For more information see [`ThreadRng`]. /// /// [`ThreadRng`]: rngs/struct.ThreadRng.html pub fn thread_rng() -> ThreadRng { ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } } impl RngCore for ThreadRng { #[inline(always)] fn next_u32(&mut self) -> u32 { unsafe { (*self.rng.get()).next_u32() } } #[inline(always)] fn next_u64(&mut self) -> u64 { unsafe { (*self.rng.get()).next_u64() } } fn fill_bytes(&mut self, dest: &mut [u8]) { unsafe { (*self.rng.get()).fill_bytes(dest) } } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { unsafe { (*self.rng.get()).try_fill_bytes(dest) } } } impl CryptoRng for ThreadRng {} #[cfg(test)] mod test { #[test] #[cfg(not(feature="stdweb"))] fn test_thread_rng() { use Rng; let mut r = ::thread_rng(); r.gen::(); let mut v = [1, 1, 1]; r.shuffle(&mut v); let b: &[_] = &[1, 1, 1]; assert_eq!(v, b); assert_eq!(r.gen_range(0, 1), 0); } } rand-0.5.5/src/seq.rs010064400017500001750000000263221333210603300126120ustar0000000000000000// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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. //! Functions for randomly accessing and sampling sequences. use super::Rng; // This crate is only enabled when either std or alloc is available. #[cfg(all(feature="alloc", not(feature="std")))] use alloc::vec::Vec; // BTreeMap is not as fast in tests, but better than nothing. #[cfg(feature="std")] use std::collections::HashMap; #[cfg(all(feature="alloc", not(feature="std")))] use alloc::collections::BTreeMap; /// Randomly sample `amount` elements from a finite iterator. /// /// The following can be returned: /// /// - `Ok`: `Vec` of `amount` non-repeating randomly sampled elements. The order is not random. /// - `Err`: `Vec` of all the elements from `iterable` in sequential order. This happens when the /// length of `iterable` was less than `amount`. This is considered an error since exactly /// `amount` elements is typically expected. /// /// This implementation uses `O(len(iterable))` time and `O(amount)` memory. /// /// # Example /// /// ``` /// use rand::{thread_rng, seq}; /// /// let mut rng = thread_rng(); /// let sample = seq::sample_iter(&mut rng, 1..100, 5).unwrap(); /// println!("{:?}", sample); /// ``` pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result, Vec> where I: IntoIterator, R: Rng + ?Sized, { let mut iter = iterable.into_iter(); let mut reservoir = Vec::with_capacity(amount); reservoir.extend(iter.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 iter.enumerate() { let k = rng.gen_range(0, i + 1 + amount); if let Some(spot) = reservoir.get_mut(k) { *spot = elem; } } Ok(reservoir) } else { // Don't hang onto extra memory. There is a corner case where // `amount` was much less than `len(iterable)`. reservoir.shrink_to_fit(); Err(reservoir) } } /// Randomly sample exactly `amount` values from `slice`. /// /// The values are non-repeating and in random order. /// /// This implementation uses `O(amount)` time and memory. /// /// Panics if `amount > slice.len()` /// /// # Example /// /// ``` /// use rand::{thread_rng, seq}; /// /// let mut rng = thread_rng(); /// let values = vec![5, 6, 1, 3, 4, 6, 7]; /// println!("{:?}", seq::sample_slice(&mut rng, &values, 3)); /// ``` pub fn sample_slice(rng: &mut R, slice: &[T], amount: usize) -> Vec where R: Rng + ?Sized, T: Clone { let indices = sample_indices(rng, slice.len(), amount); let mut out = Vec::with_capacity(amount); out.extend(indices.iter().map(|i| slice[*i].clone())); out } /// Randomly sample exactly `amount` references from `slice`. /// /// The references are non-repeating and in random order. /// /// This implementation uses `O(amount)` time and memory. /// /// Panics if `amount > slice.len()` /// /// # Example /// /// ``` /// use rand::{thread_rng, seq}; /// /// let mut rng = thread_rng(); /// let values = vec![5, 6, 1, 3, 4, 6, 7]; /// println!("{:?}", seq::sample_slice_ref(&mut rng, &values, 3)); /// ``` pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> Vec<&'a T> where R: Rng + ?Sized { let indices = sample_indices(rng, slice.len(), amount); let mut out = Vec::with_capacity(amount); out.extend(indices.iter().map(|i| &slice[*i])); out } /// Randomly sample exactly `amount` indices from `0..length`. /// /// The values are non-repeating and in random order. /// /// This implementation uses `O(amount)` time and memory. /// /// 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. /// /// Panics if `amount > length` pub fn sample_indices(rng: &mut R, length: usize, amount: usize) -> Vec where R: Rng + ?Sized, { if amount > length { panic!("`amount` must be less than or equal to `slice.len()`"); } // We are going to have to allocate at least `amount` for the output no matter what. However, // if we use the `cached` version we will have to allocate `amount` as a HashMap as well since // it inserts an element for every loop. // // Therefore, if `amount >= length / 2` then inplace will be both faster and use less memory. // In fact, benchmarks show the inplace version is faster for length up to about 20 times // faster than amount. // // TODO: there is probably even more fine-tuning that can be done here since // `HashMap::with_capacity(amount)` probably allocates more than `amount` in practice, // and a trade off could probably be made between memory/cpu, since hashmap operations // are slower than array index swapping. if amount >= length / 20 { sample_indices_inplace(rng, length, amount) } else { sample_indices_cache(rng, length, amount) } } /// 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 is better than using a `HashMap` "cache" when `amount >= length / 2` /// since it does not require allocating an extra cache and is much faster. fn sample_indices_inplace(rng: &mut R, length: usize, amount: usize) -> Vec where R: Rng + ?Sized, { debug_assert!(amount <= length); let mut indices: Vec = Vec::with_capacity(length); indices.extend(0..length); for i in 0..amount { let j: usize = rng.gen_range(i, length); indices.swap(i, j); } indices.truncate(amount); debug_assert_eq!(indices.len(), amount); indices } /// This method performs a partial fisher-yates on a range of indices using a /// `HashMap` as a cache to record potential collisions. /// /// The cache avoids allocating the entire `length` of values. This is especially useful when /// `amount <<< length`, i.e. select 3 non-repeating from `1_000_000` fn sample_indices_cache( rng: &mut R, length: usize, amount: usize, ) -> Vec where R: Rng + ?Sized, { debug_assert!(amount <= length); #[cfg(feature="std")] let mut cache = HashMap::with_capacity(amount); #[cfg(not(feature="std"))] let mut cache = BTreeMap::new(); let mut out = Vec::with_capacity(amount); for i in 0..amount { let j: usize = rng.gen_range(i, length); // equiv: let tmp = slice[i]; let tmp = match cache.get(&i) { Some(e) => *e, None => i, }; // equiv: slice[i] = slice[j]; let x = match cache.get(&j) { Some(x) => *x, None => j, }; // equiv: slice[j] = tmp; cache.insert(j, tmp); // note that in the inplace version, slice[i] is automatically "returned" value out.push(x); } debug_assert_eq!(out.len(), amount); out } #[cfg(test)] mod test { use super::*; use {XorShiftRng, Rng, SeedableRng}; #[cfg(not(feature="std"))] use alloc::vec::Vec; #[test] fn test_sample_iter() { let min_val = 1; let max_val = 100; let mut r = ::test::rng(401); let vals = (min_val..max_val).collect::>(); let small_sample = sample_iter(&mut r, vals.iter(), 5).unwrap(); let large_sample = sample_iter(&mut r, vals.iter(), vals.len() + 5).unwrap_err(); 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] fn test_sample_slice_boundaries() { let empty: &[u8] = &[]; let mut r = ::test::rng(402); // sample 0 items assert_eq!(&sample_slice(&mut r, empty, 0)[..], [0u8; 0]); assert_eq!(&sample_slice(&mut r, &[42, 2, 42], 0)[..], [0u8; 0]); // sample 1 item assert_eq!(&sample_slice(&mut r, &[42], 1)[..], [42]); let v = sample_slice(&mut r, &[1, 42], 1)[0]; assert!(v == 1 || v == 42); // sample "all" the items let v = sample_slice(&mut r, &[42, 133], 2); assert!(&v[..] == [42, 133] || v[..] == [133, 42]); assert_eq!(&sample_indices_inplace(&mut r, 0, 0)[..], [0usize; 0]); assert_eq!(&sample_indices_inplace(&mut r, 1, 0)[..], [0usize; 0]); assert_eq!(&sample_indices_inplace(&mut r, 1, 1)[..], [0]); assert_eq!(&sample_indices_cache(&mut r, 0, 0)[..], [0usize; 0]); assert_eq!(&sample_indices_cache(&mut r, 1, 0)[..], [0usize; 0]); assert_eq!(&sample_indices_cache(&mut r, 1, 1)[..], [0]); // Make sure lucky 777's aren't lucky let slice = &[42, 777]; let mut num_42 = 0; let total = 1000; for _ in 0..total { let v = sample_slice(&mut r, slice, 1); assert_eq!(v.len(), 1); let v = v[0]; assert!(v == 42 || v == 777); if v == 42 { num_42 += 1; } } let ratio_42 = num_42 as f64 / 1000 as f64; assert!(0.4 <= ratio_42 || ratio_42 <= 0.6, "{}", ratio_42); } #[test] fn test_sample_slice() { let xor_rng = XorShiftRng::from_seed; let max_range = 100; let mut r = ::test::rng(403); for length in 1usize..max_range { let amount = r.gen_range(0, length); let mut seed = [0u8; 16]; r.fill(&mut seed); // assert that the two index methods give exactly the same result let inplace = sample_indices_inplace( &mut xor_rng(seed), length, amount); let cache = sample_indices_cache( &mut xor_rng(seed), length, amount); assert_eq!(inplace, cache); // assert the basics work let regular = sample_indices( &mut xor_rng(seed), length, amount); assert_eq!(regular.len(), amount); assert!(regular.iter().all(|e| *e < length)); assert_eq!(regular, inplace); // also test that sampling the slice works let vec: Vec = (0..length).collect(); { let result = sample_slice(&mut xor_rng(seed), &vec, amount); assert_eq!(result, regular); } { let result = sample_slice_ref(&mut xor_rng(seed), &vec, amount); let expected = regular.iter().map(|v| v).collect::>(); assert_eq!(result, expected); } } } } rand-0.5.5/tests/bool.rs010064400017500001750000000013141333210603300133220ustar0000000000000000#![no_std] extern crate rand; use rand::SeedableRng; use rand::rngs::SmallRng; use rand::distributions::{Distribution, Bernoulli}; /// This test should make sure that we don't accidentally have undefined /// behavior for large propabilties due to /// https://github.com/rust-lang/rust/issues/10184. /// Expressions like `1.0*(u64::MAX as f64) as u64` have to be avoided. #[test] fn large_probability() { let p = 1. - ::core::f64::EPSILON / 2.; assert!(p < 1.); let d = Bernoulli::new(p); let mut rng = SmallRng::from_seed( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); for _ in 0..10 { assert!(d.sample(&mut rng), "extremely unlikely to fail by accident"); } } rand-0.5.5/utils/ci/install.sh010064400017500001750000000025451324530212700144300ustar0000000000000000# From https://github.com/japaric/trust set -ex main() { local target= if [ $TRAVIS_OS_NAME = linux ]; then target=x86_64-unknown-linux-musl sort=sort else target=x86_64-apple-darwin sort=gsort # for `sort --sort-version`, from brew's coreutils. fi # Builds for iOS are done on OSX, but require the specific target to be # installed. case $TARGET in aarch64-apple-ios) rustup target install aarch64-apple-ios ;; armv7-apple-ios) rustup target install armv7-apple-ios ;; armv7s-apple-ios) rustup target install armv7s-apple-ios ;; i386-apple-ios) rustup target install i386-apple-ios ;; x86_64-apple-ios) rustup target install x86_64-apple-ios ;; esac # This fetches latest stable release local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \ | cut -d/ -f3 \ | grep -E '^v[0.1.0-9.]+$' \ | $sort --version-sort \ | tail -n1) curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- \ --force \ --git japaric/cross \ --tag $tag \ --target $target } main rand-0.5.5/utils/ci/script.sh010064400017500001750000000020171333210603300142530ustar0000000000000000# Derived from https://github.com/japaric/trust set -ex main() { if [ ! -z $DISABLE_TESTS ]; then # tests are disabled cross build --no-default-features --target $TARGET --release if [ -z $DISABLE_STD ]; then # std is enabled cross build --features log,serde1 --target $TARGET fi return fi if [ ! -z $NIGHTLY ]; then # have nightly Rust cross test --tests --no-default-features --features alloc --target $TARGET cross test --package rand_core --no-default-features --features alloc --target $TARGET cross test --features serde1,log,nightly,alloc --target $TARGET cross test --all --benches --target $TARGET else # have stable Rust cross test --tests --no-default-features --target $TARGET cross test --package rand_core --no-default-features --target $TARGET cross test --features serde1,log --target $TARGET fi } # we don't run the "test phase" when doing deploys if [ -z $TRAVIS_TAG ]; then main fi rand-0.5.5/utils/ziggurat_tables.py010075500017500001750000000077361323634522600156140ustar0000000000000000#!/usr/bin/env python # # Copyright 2013 The Rust Project Developers. See the COPYRIGHT # file at the top-level directory of this distribution and at # https://rust-lang.org/COPYRIGHT. # # 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. # This creates the tables used for distributions implemented using the # ziggurat algorithm in `rand::distributions;`. They are # (basically) the tables as used in the ZIGNOR variant (Doornik 2005). # They are changed rarely, so the generated file should be checked in # to git. # # It creates 3 tables: X as in the paper, F which is f(x_i), and # F_DIFF which is f(x_i) - f(x_{i-1}). The latter two are just cached # values which is not done in that paper (but is done in other # variants). Note that the adZigR table is unnecessary because of # algebra. # # It is designed to be compatible with Python 2 and 3. from math import exp, sqrt, log, floor import random # The order should match the return value of `tables` TABLE_NAMES = ['X', 'F'] # The actual length of the table is 1 more, to stop # index-out-of-bounds errors. This should match the bitwise operation # to find `i` in `zigurrat` in `libstd/rand/mod.rs`. Also the *_R and # *_V constants below depend on this value. TABLE_LEN = 256 # equivalent to `zigNorInit` in Doornik2005, but generalised to any # distribution. r = dR, v = dV, f = probability density function, # f_inv = inverse of f def tables(r, v, f, f_inv): # compute the x_i xvec = [0]*(TABLE_LEN+1) xvec[0] = v / f(r) xvec[1] = r for i in range(2, TABLE_LEN): last = xvec[i-1] xvec[i] = f_inv(v / last + f(last)) # cache the f's fvec = [0]*(TABLE_LEN+1) for i in range(TABLE_LEN+1): fvec[i] = f(xvec[i]) return xvec, fvec # Distributions # N(0, 1) def norm_f(x): return exp(-x*x/2.0) def norm_f_inv(y): return sqrt(-2.0*log(y)) NORM_R = 3.6541528853610088 NORM_V = 0.00492867323399 NORM = tables(NORM_R, NORM_V, norm_f, norm_f_inv) # Exp(1) def exp_f(x): return exp(-x) def exp_f_inv(y): return -log(y) EXP_R = 7.69711747013104972 EXP_V = 0.0039496598225815571993 EXP = tables(EXP_R, EXP_V, exp_f, exp_f_inv) # Output the tables/constants/types def render_static(name, type, value): # no space or return 'pub static %s: %s =%s;\n' % (name, type, value) # static `name`: [`type`, .. `len(values)`] = # [values[0], ..., values[3], # values[4], ..., values[7], # ... ]; def render_table(name, values): rows = [] # 4 values on each row for i in range(0, len(values), 4): row = values[i:i+4] rows.append(', '.join('%.18f' % f for f in row)) rendered = '\n [%s]' % ',\n '.join(rows) return render_static(name, '[f64, .. %d]' % len(values), rendered) with open('ziggurat_tables.rs', 'w') as f: f.write('''// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // https://rust-lang.org/COPYRIGHT. // // 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, .. %d]; ''' % (TABLE_LEN + 1)) for name, tables, r in [('NORM', NORM, NORM_R), ('EXP', EXP, EXP_R)]: f.write(render_static('ZIG_%s_R' % name, 'f64', ' %.18f' % r)) for (tabname, table) in zip(TABLE_NAMES, tables): f.write(render_table('ZIG_%s_%s' % (name, tabname), table))