├── .github ├── FUNDING.yml └── workflows │ ├── benches.yml │ ├── test.yml │ └── workspace.yml ├── .gitignore ├── COPYRIGHT ├── Cargo.lock.msrv ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches ├── Cargo.toml └── mod.rs ├── rand_hc ├── CHANGELOG.md ├── COPYRIGHT ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── hc128.rs │ └── lib.rs ├── rand_isaac ├── CHANGELOG.md ├── COPYRIGHT ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── isaac.rs │ ├── isaac64.rs │ ├── isaac_array.rs │ └── lib.rs ├── rand_jitter ├── CHANGELOG.md ├── COPYRIGHT ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src │ ├── error.rs │ ├── lib.rs │ └── platform.rs └── tests │ └── mod.rs ├── rand_xorshift ├── CHANGELOG.md ├── COPYRIGHT ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src │ └── lib.rs └── tests │ └── mod.rs └── rand_xoshiro ├── CHANGELOG.md ├── COPYRIGHT ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src ├── common.rs ├── lib.rs ├── splitmix64.rs ├── xoroshiro128plus.rs ├── xoroshiro128plusplus.rs ├── xoroshiro128starstar.rs ├── xoroshiro64star.rs ├── xoroshiro64starstar.rs ├── xoshiro128plus.rs ├── xoshiro128plusplus.rs ├── xoshiro128starstar.rs ├── xoshiro256plus.rs ├── xoshiro256plusplus.rs ├── xoshiro256starstar.rs ├── xoshiro512plus.rs ├── xoshiro512plusplus.rs └── xoshiro512starstar.rs └── tests └── serde.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: dhardy 2 | -------------------------------------------------------------------------------- /.github/workflows/benches.yml: -------------------------------------------------------------------------------- 1 | name: Benches 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/benches.yml" 7 | - "benches/**" 8 | 9 | jobs: 10 | benches: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | working-directory: ./benches 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: dtolnay/rust-toolchain@master 18 | with: 19 | toolchain: nightly 20 | components: clippy, rustfmt 21 | - name: Build 22 | run: RUSTFLAGS=-Dwarnings cargo build --all-targets 23 | - name: Rustfmt 24 | run: cargo fmt -- --check 25 | - name: Clippy 26 | run: cargo clippy --all-targets -- -D warnings 27 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | check-doc: 14 | name: Check doc 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Install toolchain 19 | uses: dtolnay/rust-toolchain@nightly 20 | - run: cargo install cargo-deadlinks 21 | - name: doc (rand) 22 | env: 23 | RUSTDOCFLAGS: --cfg doc_cfg 24 | # --all builds all crates, but with default features for other crates (okay in this case) 25 | run: cargo deadlinks --ignore-fragments -- --all --all-features 26 | 27 | test: 28 | runs-on: ${{ matrix.os }} 29 | strategy: 30 | fail-fast: false 31 | matrix: 32 | include: 33 | - os: ubuntu-latest 34 | target: x86_64-unknown-linux-gnu 35 | toolchain: stable 36 | - os: macos-latest 37 | target: x86_64-apple-darwin 38 | toolchain: stable 39 | # TODO: also aarch64 / M1 40 | - os: windows-latest 41 | target: x86_64-pc-windows-gnu 42 | toolchain: stable 43 | - os: windows-latest 44 | target: x86_64-pc-windows-msvc 45 | toolchain: beta 46 | # Test both windows-gnu and windows-msvc; use beta rust on one 47 | - os: ubuntu-latest 48 | target: x86_64-unknown-linux-gnu 49 | variant: MSRV 50 | toolchain: 1.63.0 51 | - os: ubuntu-latest 52 | deps: sudo apt-get update ; sudo apt install gcc-multilib 53 | target: i686-unknown-linux-gnu 54 | toolchain: nightly 55 | - os: ubuntu-latest 56 | target: x86_64-unknown-linux-gnu 57 | toolchain: nightly 58 | variant: minimal_versions 59 | 60 | steps: 61 | - uses: actions/checkout@v4 62 | - name: MSRV 63 | if: ${{ matrix.variant == 'MSRV' }} 64 | run: cp Cargo.lock.msrv Cargo.lock 65 | - name: Install toolchain 66 | uses: dtolnay/rust-toolchain@master 67 | with: 68 | targets: ${{ matrix.target }} 69 | toolchain: ${{ matrix.toolchain }} 70 | - run: ${{ matrix.deps }} 71 | - name: Maybe minimal versions 72 | if: ${{ matrix.variant == 'minimal_versions' }} 73 | run: | 74 | cargo generate-lockfile -Z minimal-versions 75 | - name: Maybe nightly 76 | if: ${{ matrix.toolchain == 'nightly' }} 77 | run: | 78 | cargo test --target ${{ matrix.target }} --benches 79 | - name: Test 80 | run: | 81 | cargo test --target ${{ matrix.target }} --manifest-path rand_hc/Cargo.toml --all-features 82 | cargo test --target ${{ matrix.target }} --manifest-path rand_isaac/Cargo.toml --all-features 83 | cargo test --target ${{ matrix.target }} --manifest-path rand_xorshift/Cargo.toml --all-features 84 | cargo test --target ${{ matrix.target }} --manifest-path rand_xoshiro/Cargo.toml --all-features 85 | cargo test --target ${{ matrix.target }} --manifest-path rand_jitter/Cargo.toml --all-features 86 | 87 | test-cross: 88 | runs-on: ubuntu-latest 89 | strategy: 90 | fail-fast: false 91 | matrix: 92 | target: [powerpc-unknown-linux-gnu] 93 | toolchain: [stable] 94 | 95 | steps: 96 | - uses: actions/checkout@v4 97 | - name: Install toolchain 98 | uses: dtolnay/rust-toolchain@master 99 | with: 100 | targets: ${{ matrix.target }} 101 | toolchain: ${{ matrix.toolchain }} 102 | - name: Cache cargo plugins 103 | uses: actions/cache@v1 104 | with: 105 | path: ~/.cargo/bin/ 106 | key: ${{ runner.os }}-cargo-plugins 107 | - name: Install cross 108 | run: cargo install cross || true 109 | - name: Test 110 | run: | 111 | cross test --no-fail-fast --target ${{ matrix.target }} --manifest-path rand_hc/Cargo.toml --all-features 112 | cross test --no-fail-fast --target ${{ matrix.target }} --manifest-path rand_isaac/Cargo.toml --all-features 113 | cross test --no-fail-fast --target ${{ matrix.target }} --manifest-path rand_xorshift/Cargo.toml --all-features 114 | cross test --no-fail-fast --target ${{ matrix.target }} --manifest-path rand_xoshiro/Cargo.toml --all-features 115 | cross test --no-fail-fast --target ${{ matrix.target }} --manifest-path rand_jitter/Cargo.toml --all-features 116 | 117 | test-miri: 118 | runs-on: ubuntu-latest 119 | steps: 120 | - uses: actions/checkout@v4 121 | - name: Install toolchain 122 | run: | 123 | MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) 124 | rustup default "$MIRI_NIGHTLY" 125 | rustup component add miri 126 | - name: Test rand 127 | run: | 128 | cargo miri test --manifest-path rand_hc/Cargo.toml --all-features 129 | cargo miri test --manifest-path rand_isaac/Cargo.toml --all-features 130 | cargo miri test --manifest-path rand_xorshift/Cargo.toml --all-features 131 | cargo miri test --manifest-path rand_xoshiro/Cargo.toml --all-features 132 | MIRIFLAGS="-Zmiri-disable-isolation" cargo miri test --manifest-path rand_jitter/Cargo.toml 133 | -------------------------------------------------------------------------------- /.github/workflows/workspace.yml: -------------------------------------------------------------------------------- 1 | name: Workspace 2 | 3 | on: 4 | pull_request: 5 | paths-ignore: 6 | - README.md 7 | push: 8 | branches: master 9 | paths-ignore: 10 | - README.md 11 | 12 | jobs: 13 | clippy: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: dtolnay/rust-toolchain@master 18 | with: 19 | toolchain: stable 20 | components: clippy, rustfmt 21 | - name: Clippy 22 | run: cargo clippy --all --all-targets -- -D warnings 23 | - name: Rustfmt 24 | run: cargo fmt --all -- --check 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .idea 4 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the Rand project are retained by their contributors. No 2 | copyright assignment is required to contribute to the Rand project. 3 | 4 | For full authorship information, see the version control history. 5 | 6 | Except as otherwise noted (below and/or in individual files), Rand is 7 | licensed under the Apache License, Version 2.0 or 8 | or the MIT license 9 | or , at your option. 10 | 11 | The Rand project includes code from the Rust project 12 | published under these same licenses. 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "rand_jitter", 4 | "rand_isaac", 5 | "rand_xorshift", 6 | "rand_xoshiro", 7 | "rand_hc", 8 | ] 9 | exclude = [ 10 | "benches", 11 | ] 12 | resolver = "2" 13 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | https://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2018 Developers of the Rand project 2 | Copyright (c) 2014 The Rust Project Developers 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rand 2 | 3 | [![Test Status](https://github.com/rust-random/rngs/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rngs/actions) 4 | [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) 5 | [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand) 6 | [![Minimum rustc version](https://img.shields.io/badge/rustc-1.63-lightgray.svg)](https://github.com/rust-random/rngs#rust-version-requirements) 7 | 8 | Extra random number generators provided by the Rust Random project. 9 | The main repository, [rust-random/rand](https://github.com/rust-random/rand), 10 | includes all generators which are a direct dependency of the `rand` crate. 11 | This repository houses extra generators maintained by the project. 12 | 13 | Documentation: 14 | - [Our generators](https://rust-random.github.io/book/guide-rngs.html) 15 | - [The Rust Rand Book](https://rust-random.github.io/book) 16 | - [API reference (master)](https://rust-random.github.io/rand) 17 | - [API reference (docs.rs)](https://docs.rs/rand) 18 | 19 | 20 | ### Rust version requirements 21 | 22 | All crates in this repository require **rustc version 1.63 or greater**. 23 | 24 | GitHub Actions always has a build with a pinned version of rustc matching the 25 | oldest supported Rust release. The current policy is that this can be updated in 26 | any Rand release if required, but the change must be noted in the changelog. 27 | 28 | # License 29 | 30 | Rand is distributed under the terms of both the MIT license and the 31 | Apache License (Version 2.0). 32 | 33 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and 34 | [COPYRIGHT](COPYRIGHT) for details. 35 | -------------------------------------------------------------------------------- /benches/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "benches" 3 | version = "0.1.0" 4 | edition = "2021" 5 | rust-version = "1.63" 6 | publish = false 7 | 8 | [dev-dependencies] 9 | criterion = "0.5.0" 10 | criterion-cycles-per-byte = "0.6" 11 | rand_core = { version = "0.9.0", features = ["os_rng"] } 12 | rand_xoshiro = { path = "../rand_xoshiro", version = "0.7" } 13 | rand_isaac = { path = "../rand_isaac", version = "0.4" } 14 | rand_xorshift = { path = "../rand_xorshift", version = "0.4" } 15 | rand_hc = { path = "../rand_hc", version = "0.4" } 16 | 17 | [[bench]] 18 | name = "mod" 19 | path = "mod.rs" 20 | harness = false 21 | 22 | [patch.crates-io.rand_core] 23 | git = "https://github.com/rust-random/rand.git" 24 | branch = "master" 25 | -------------------------------------------------------------------------------- /benches/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #![feature(test)] 10 | #![allow(non_snake_case)] 11 | 12 | extern crate test; 13 | 14 | use std::mem::size_of; 15 | use test::black_box; 16 | 17 | use criterion::{criterion_group, criterion_main, Criterion, Throughput}; 18 | use criterion_cycles_per_byte::CyclesPerByte; 19 | use rand_core::{RngCore, SeedableRng}; 20 | 21 | use rand_hc::Hc128Rng; 22 | use rand_isaac::{Isaac64Rng, IsaacRng}; 23 | use rand_xorshift::XorShiftRng; 24 | use rand_xoshiro::{ 25 | SplitMix64, Xoroshiro128Plus, Xoroshiro128StarStar, Xoroshiro64Star, Xoroshiro64StarStar, 26 | Xoshiro128Plus, Xoshiro128PlusPlus, Xoshiro128StarStar, Xoshiro256Plus, Xoshiro256PlusPlus, 27 | Xoshiro256StarStar, 28 | }; 29 | 30 | const RAND_BENCH_N: u64 = 1000; 31 | const BYTES_LEN: usize = 1024; 32 | 33 | fn gen_bytes(c: &mut Criterion) { 34 | let mut g = c.benchmark_group("gen_bytes"); 35 | g.throughput(Throughput::Bytes(BYTES_LEN as u64 * RAND_BENCH_N)); 36 | 37 | macro_rules! gen_bytes { 38 | ($fnn:expr, $gen:expr) => { 39 | g.bench_function($fnn, |b| { 40 | let mut rng = $gen; 41 | let mut buf = [0u8; BYTES_LEN]; 42 | b.iter(|| { 43 | for _ in 0..RAND_BENCH_N { 44 | rng.fill_bytes(&mut buf); 45 | black_box(buf); 46 | } 47 | }) 48 | }); 49 | }; 50 | } 51 | 52 | gen_bytes!("xorshift", XorShiftRng::from_os_rng()); 53 | gen_bytes!("xoshiro256starstar", Xoshiro256StarStar::from_os_rng()); 54 | gen_bytes!("xoshiro256plus", Xoshiro256Plus::from_os_rng()); 55 | gen_bytes!("xoshiro256plusplus", Xoshiro256PlusPlus::from_os_rng()); 56 | gen_bytes!("xoshiro128starstar", Xoshiro128StarStar::from_os_rng()); 57 | gen_bytes!("xoshiro128plus", Xoshiro128Plus::from_os_rng()); 58 | gen_bytes!("xoshiro128plusplus", Xoshiro128PlusPlus::from_os_rng()); 59 | gen_bytes!("xoroshiro128starstar", Xoroshiro128StarStar::from_os_rng()); 60 | gen_bytes!("xoroshiro128plus", Xoroshiro128Plus::from_os_rng()); 61 | gen_bytes!("xoroshiro64starstar", Xoroshiro64StarStar::from_os_rng()); 62 | gen_bytes!("xoroshiro64star", Xoroshiro64Star::from_os_rng()); 63 | gen_bytes!("splitmix64", SplitMix64::from_os_rng()); 64 | gen_bytes!("hc128", Hc128Rng::from_os_rng()); 65 | gen_bytes!("isaac", IsaacRng::from_os_rng()); 66 | gen_bytes!("isaac64", Isaac64Rng::from_os_rng()); 67 | } 68 | 69 | // Save a dependency on Rand: 70 | trait Generate { 71 | fn generate(rng: &mut R) -> Self; 72 | } 73 | 74 | impl Generate for u32 { 75 | #[inline] 76 | fn generate(rng: &mut R) -> Self { 77 | rng.next_u32() 78 | } 79 | } 80 | 81 | impl Generate for u64 { 82 | #[inline] 83 | fn generate(rng: &mut R) -> Self { 84 | rng.next_u64() 85 | } 86 | } 87 | 88 | fn gen_uint(c: &mut Criterion) { 89 | macro_rules! gen_uint { 90 | ($g:expr, $fnn:expr, $ty:ty, $gen:expr) => { 91 | $g.bench_function($fnn, |b| { 92 | let mut rng = $gen; 93 | b.iter(|| { 94 | let mut accum: $ty = 0; 95 | for _ in 0..RAND_BENCH_N { 96 | accum = accum.wrapping_add(<$ty as Generate>::generate(&mut rng)); 97 | } 98 | accum 99 | }); 100 | }); 101 | }; 102 | } 103 | 104 | { 105 | let mut g = c.benchmark_group("gen_u32"); 106 | g.throughput(Throughput::Bytes(size_of::() as u64 * RAND_BENCH_N)); 107 | 108 | gen_uint!(g, "xorshift", u32, XorShiftRng::from_os_rng()); 109 | gen_uint!( 110 | g, 111 | "xoshiro256starstar", 112 | u32, 113 | Xoshiro256StarStar::from_os_rng() 114 | ); 115 | gen_uint!(g, "xoshiro256plus", u32, Xoshiro256Plus::from_os_rng()); 116 | gen_uint!( 117 | g, 118 | "xoshiro256plusplus", 119 | u32, 120 | Xoshiro256PlusPlus::from_os_rng() 121 | ); 122 | gen_uint!( 123 | g, 124 | "xoshiro128starstar", 125 | u32, 126 | Xoshiro128StarStar::from_os_rng() 127 | ); 128 | gen_uint!(g, "xoshiro128plus", u32, Xoshiro128Plus::from_os_rng()); 129 | gen_uint!( 130 | g, 131 | "xoshiro128plusplus", 132 | u32, 133 | Xoshiro128PlusPlus::from_os_rng() 134 | ); 135 | gen_uint!( 136 | g, 137 | "xoroshiro128starstar", 138 | u32, 139 | Xoroshiro128StarStar::from_os_rng() 140 | ); 141 | gen_uint!(g, "xoroshiro128plus", u32, Xoroshiro128Plus::from_os_rng()); 142 | gen_uint!( 143 | g, 144 | "xoroshiro64starstar", 145 | u32, 146 | Xoroshiro64StarStar::from_os_rng() 147 | ); 148 | gen_uint!(g, "xoroshiro64star", u32, Xoroshiro64Star::from_os_rng()); 149 | gen_uint!(g, "splitmix64", u32, SplitMix64::from_os_rng()); 150 | gen_uint!(g, "hc128", u32, Hc128Rng::from_os_rng()); 151 | gen_uint!(g, "isaac", u32, IsaacRng::from_os_rng()); 152 | gen_uint!(g, "isaac64", u32, Isaac64Rng::from_os_rng()); 153 | } 154 | 155 | { 156 | let mut g = c.benchmark_group("gen_u64"); 157 | g.throughput(Throughput::Bytes(size_of::() as u64 * RAND_BENCH_N)); 158 | 159 | gen_uint!(g, "xorshift", u64, XorShiftRng::from_os_rng()); 160 | gen_uint!( 161 | g, 162 | "xoshiro256starstar", 163 | u64, 164 | Xoshiro256StarStar::from_os_rng() 165 | ); 166 | gen_uint!(g, "xoshiro256plus", u64, Xoshiro256Plus::from_os_rng()); 167 | gen_uint!( 168 | g, 169 | "xoshiro256plusplus", 170 | u64, 171 | Xoshiro256PlusPlus::from_os_rng() 172 | ); 173 | gen_uint!( 174 | g, 175 | "xoshiro128starstar", 176 | u64, 177 | Xoshiro128StarStar::from_os_rng() 178 | ); 179 | gen_uint!(g, "xoshiro128plus", u64, Xoshiro128Plus::from_os_rng()); 180 | gen_uint!( 181 | g, 182 | "xoshiro128plusplus", 183 | u64, 184 | Xoshiro128PlusPlus::from_os_rng() 185 | ); 186 | gen_uint!( 187 | g, 188 | "xoroshiro128starstar", 189 | u64, 190 | Xoroshiro128StarStar::from_os_rng() 191 | ); 192 | gen_uint!(g, "xoroshiro128plus", u64, Xoroshiro128Plus::from_os_rng()); 193 | gen_uint!( 194 | g, 195 | "xoroshiro64starstar", 196 | u64, 197 | Xoroshiro64StarStar::from_os_rng() 198 | ); 199 | gen_uint!(g, "xoroshiro64star", u64, Xoroshiro64Star::from_os_rng()); 200 | gen_uint!(g, "splitmix64", u64, SplitMix64::from_os_rng()); 201 | gen_uint!(g, "hc128", u64, Hc128Rng::from_os_rng()); 202 | gen_uint!(g, "isaac", u64, IsaacRng::from_os_rng()); 203 | gen_uint!(g, "isaac64", u64, Isaac64Rng::from_os_rng()); 204 | } 205 | } 206 | 207 | fn init(c: &mut Criterion) { 208 | let mut g = c.benchmark_group("init"); 209 | 210 | macro_rules! init_gen { 211 | ($fnn:expr, $gen:ident) => { 212 | g.bench_function($fnn, |b| { 213 | let mut rng = XorShiftRng::from_os_rng(); 214 | b.iter(|| $gen::from_rng(black_box(&mut rng))) 215 | }); 216 | }; 217 | } 218 | 219 | init_gen!("xorshift", XorShiftRng); 220 | init_gen!("xoshiro256starstar", Xoshiro256StarStar); 221 | init_gen!("xoshiro256plus", Xoshiro256Plus); 222 | init_gen!("xoshiro256plusplus", Xoshiro256PlusPlus); 223 | init_gen!("xoshiro128starstar", Xoshiro128StarStar); 224 | init_gen!("xoshiro128plus", Xoshiro128Plus); 225 | init_gen!("xoshiro128plusplus", Xoshiro128PlusPlus); 226 | init_gen!("xoroshiro128starstar", Xoroshiro128StarStar); 227 | init_gen!("xoroshiro128plus", Xoroshiro128Plus); 228 | init_gen!("xoroshiro64starstar", Xoroshiro64StarStar); 229 | init_gen!("xoroshiro64star", Xoroshiro64Star); 230 | init_gen!("splitmix64", SplitMix64); 231 | init_gen!("hc128", Hc128Rng); 232 | init_gen!("isaac", IsaacRng); 233 | init_gen!("isaac64", Isaac64Rng); 234 | } 235 | 236 | criterion_group! { 237 | name = gen_benches; 238 | config = Criterion::default().with_measurement(CyclesPerByte); 239 | targets = 240 | gen_uint, 241 | gen_bytes, 242 | } 243 | 244 | criterion_group! { 245 | name = standard_benches; 246 | config = Criterion::default(); 247 | targets = 248 | init, 249 | } 250 | 251 | criterion_main!(gen_benches, standard_benches); 252 | -------------------------------------------------------------------------------- /rand_hc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.4.0] - 2025-01-27 8 | - Bump the MSRV to 1.63 (#58) 9 | - Update to `rand_core` v0.9.0 (#58) 10 | - Add examples for initializing the RNGs 11 | 12 | ## [0.3.2] - 2023-04-15 13 | - Reduce stack use in `Hc128Core::init` 14 | 15 | ## [0.3.1] - 2021-06-15 16 | - Adjust crate links 17 | 18 | ## [0.3.0] - 2020-12-08 19 | - Bump `rand_core` version to 0.6.0 20 | - Bump MSRV to 1.36 (#1011) 21 | - impl PartialEq+Eq for Hc128Rng and Hc128Core (#979) 22 | - Drop some unsafe code, fixing an unsound internal function (#960) 23 | 24 | ## [0.2.0] - 2019-06-12 25 | - Bump minor crate version since rand_core bump is a breaking change 26 | - Switch to Edition 2018 27 | 28 | ## [0.1.1] - 2019-06-06 - yanked 29 | - Bump `rand_core` version 30 | - Adjust usage of `#[inline]` 31 | 32 | ## [0.1.0] - 2018-10-17 33 | - Pulled out of the Rand crate 34 | -------------------------------------------------------------------------------- /rand_hc/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the Rand project are retained by their contributors. No 2 | copyright assignment is required to contribute to the Rand project. 3 | 4 | For full authorship information, see the version control history. 5 | 6 | Except as otherwise noted (below and/or in individual files), Rand is 7 | licensed under the Apache License, Version 2.0 or 8 | or the MIT license 9 | or , at your option. 10 | 11 | The Rand project includes code from the Rust project 12 | published under these same licenses. 13 | -------------------------------------------------------------------------------- /rand_hc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rand_hc" 3 | version = "0.4.0" 4 | authors = ["The Rand Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | readme = "README.md" 7 | repository = "https://github.com/rust-random/rngs" 8 | documentation = "https://docs.rs/rand_hc" 9 | homepage = "https://rust-random.github.io/book" 10 | description = """ 11 | HC128 random number generator 12 | """ 13 | keywords = ["random", "rng", "hc128"] 14 | categories = ["algorithms", "no-std"] 15 | edition = "2021" 16 | rust-version = "1.63" 17 | 18 | [dependencies] 19 | rand_core = "0.9.0" 20 | -------------------------------------------------------------------------------- /rand_hc/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | https://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /rand_hc/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2018 Developers of the Rand project 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /rand_hc/README.md: -------------------------------------------------------------------------------- 1 | # rand_hc 2 | 3 | [![Test Status](https://github.com/rust-random/rngs/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rngs/actions) 4 | [![Latest version](https://img.shields.io/crates/v/rand_hc.svg)](https://crates.io/crates/rand_hc) 5 | [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) 6 | [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_hc) 7 | [![API](https://docs.rs/rand_hc/badge.svg)](https://docs.rs/rand_hc) 8 | 9 | A cryptographically secure random number generator that uses the HC-128 10 | algorithm. 11 | 12 | HC-128 is a stream cipher designed by Hongjun Wu[^1], that we use as an 13 | RNG. It is selected as one of the "stream ciphers suitable for widespread 14 | adoption" by eSTREAM[^2]. 15 | 16 | Links: 17 | 18 | - [API documentation (master)](https://rust-random.github.io/rand/rand_hc) 19 | - [API documentation (docs.rs)](https://docs.rs/rand_hc) 20 | - [Changelog](https://github.com/rust-random/rngs/blob/master/rand_hc/CHANGELOG.md) 21 | 22 | [rand]: https://crates.io/crates/rand 23 | [^1]: Hongjun Wu (2008). ["The Stream Cipher HC-128"]( 24 | http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf). 25 | *The eSTREAM Finalists*, LNCS 4986, pp. 39–47, Springer-Verlag. 26 | 27 | [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( 28 | http://www.ecrypt.eu.org/stream/) 29 | 30 | 31 | ## Crate Features 32 | 33 | `rand_hc` is `no_std` compatible. It does not require any functionality 34 | outside of the `core` lib, thus there are no features to configure. 35 | 36 | 37 | # License 38 | 39 | `rand_hc` is distributed under the terms of both the MIT license and the 40 | Apache License (Version 2.0). 41 | 42 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and 43 | [COPYRIGHT](COPYRIGHT) for details. 44 | -------------------------------------------------------------------------------- /rand_hc/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! The HC128 random number generator. 10 | //! 11 | //! To initialize a generator, use the [`SeedableRng`][rand_core::SeedableRng] trait. 12 | 13 | #![doc( 14 | html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", 15 | html_favicon_url = "https://www.rust-lang.org/favicon.ico", 16 | html_root_url = "https://rust-random.github.io/rand/" 17 | )] 18 | #![forbid(unsafe_code)] 19 | #![deny(missing_docs)] 20 | #![deny(missing_debug_implementations)] 21 | #![doc(test(attr(allow(unused_variables), deny(warnings))))] 22 | #![no_std] 23 | 24 | mod hc128; 25 | 26 | pub use hc128::{Hc128Core, Hc128Rng}; 27 | -------------------------------------------------------------------------------- /rand_isaac/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.4.0] - 2025-01-27 8 | - Bump the MSRV to 1.63 (#58) 9 | - Update to `rand_core` v0.9.0 (#58) 10 | - Rename feature `serde1` to `serde` (#58) 11 | - Fix compiler and clippy warnings 12 | - Add examples for initializing the RNGs 13 | 14 | ## [0.3.0] - 2020-12-18 15 | - Bump `rand_core` version to 0.6 (#17) 16 | - Derive PartialEq+Eq for IsaacCore, Isaac64Core, and IsaacArray (#6) 17 | 18 | ## [0.2.0] - 2019-06-12 19 | - Bump minor crate version since rand_core bump is a breaking change 20 | - Switch to Edition 2018 21 | 22 | ## [0.1.2] - 2019-06-06 - yanked 23 | - Bump `rand_core` version 24 | - Remove deprecated code 25 | - Adjust usage of `#[inline]` 26 | 27 | ## [0.1.1] - 2018-11-26 28 | - Fix `rand_core` version requirement 29 | - Fix doc links 30 | 31 | ## [0.1.0] - 2018-10-17 32 | - Pulled out of the Rand crate 33 | -------------------------------------------------------------------------------- /rand_isaac/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the Rand project are retained by their contributors. No 2 | copyright assignment is required to contribute to the Rand project. 3 | 4 | For full authorship information, see the version control history. 5 | 6 | Except as otherwise noted (below and/or in individual files), Rand is 7 | licensed under the Apache License, Version 2.0 or 8 | or the MIT license 9 | or , at your option. 10 | 11 | The Rand project includes code from the Rust project 12 | published under these same licenses. 13 | -------------------------------------------------------------------------------- /rand_isaac/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rand_isaac" 3 | version = "0.4.0" # NB: When modifying, also modify html_root_url in lib.rs 4 | authors = ["The Rand Project Developers", "The Rust Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | readme = "README.md" 7 | repository = "https://github.com/rust-random/rngs" 8 | documentation = "https://docs.rs/rand_isaac" 9 | homepage = "https://rust-random.github.io/book" 10 | description = """ 11 | ISAAC random number generator 12 | """ 13 | keywords = ["random", "rng", "isaac"] 14 | categories = ["algorithms", "no-std"] 15 | edition = "2021" 16 | rust-version = "1.63" 17 | 18 | [features] 19 | serde = ["dep:serde", "rand_core/serde"] 20 | 21 | [dependencies] 22 | rand_core = { version = "0.9.0" } 23 | serde = { version = "1.0.104", features = ["derive"], optional = true } 24 | 25 | [dev-dependencies] 26 | # This is for testing serde, unfortunately we can't specify feature-gated dev 27 | # deps yet, see: https://github.com/rust-lang/cargo/issues/1596 28 | bincode = "1.1.4" 29 | -------------------------------------------------------------------------------- /rand_isaac/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | https://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /rand_isaac/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2018 Developers of the Rand project 2 | Copyright (c) 2014 The Rust Project Developers 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /rand_isaac/README.md: -------------------------------------------------------------------------------- 1 | # rand_isaac 2 | 3 | [![Test Status](https://github.com/rust-random/rngs/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rngs/actions) 4 | [![Latest version](https://img.shields.io/crates/v/rand_isaac.svg)](https://crates.io/crates/rand_isaac) 5 | [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) 6 | [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_isaac) 7 | [![API](https://docs.rs/rand_isaac/badge.svg)](https://docs.rs/rand_isaac) 8 | 9 | Implements the ISAAC and ISAAC-64 random number generators. 10 | 11 | ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are 12 | the principal bitwise operations employed. It is the most advanced of a 13 | series of array based random number generator designed by Robert Jenkins 14 | in 1996[^1][^2]. 15 | 16 | ISAAC is notably fast and produces excellent quality random numbers for 17 | non-cryptographic applications. 18 | 19 | Links: 20 | 21 | - [API documentation (master)](https://rust-random.github.io/rand/rand_isaac) 22 | - [API documentation (docs.rs)](https://docs.rs/rand_isaac) 23 | - [Changelog](https://github.com/rust-random/rngs/blob/master/rand_isaac/CHANGELOG.md) 24 | 25 | [rand]: https://crates.io/crates/rand 26 | [^1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number generator*](http://burtleburtle.net/bob/rand/isaacafa.html) 27 | [^2]: Bob Jenkins, [*ISAAC and RC4*](http://burtleburtle.net/bob/rand/isaac.html) 28 | 29 | 30 | ## Crate Features 31 | 32 | `rand_isaac` is `no_std` compatible. It does not require any functionality 33 | outside of the `core` lib, thus there are no features to configure. 34 | 35 | The `serde` feature includes implementations of `Serialize` and `Deserialize` 36 | for the included RNGs. 37 | 38 | 39 | # License 40 | 41 | `rand_isaac` is distributed under the terms of both the MIT license and the 42 | Apache License (Version 2.0). 43 | 44 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and 45 | [COPYRIGHT](COPYRIGHT) for details. 46 | -------------------------------------------------------------------------------- /rand_isaac/src/isaac_array.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // Copyright 2017-2018 The Rust Project Developers. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | //! ISAAC helper functions for 256-element arrays. 11 | 12 | // Terrible workaround because arrays with more than 32 elements do not 13 | // implement `AsRef`, `Default`, `Serialize`, `Deserialize`, or any other 14 | // traits for that matter. 15 | 16 | #[cfg(feature = "serde")] 17 | use serde::{Deserialize, Serialize}; 18 | 19 | const RAND_SIZE_LEN: usize = 8; 20 | const RAND_SIZE: usize = 1 << RAND_SIZE_LEN; 21 | 22 | #[derive(Copy, Clone)] 23 | #[allow(missing_debug_implementations)] 24 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 25 | pub struct IsaacArray { 26 | #[cfg_attr(feature = "serde", serde(with = "isaac_array_serde"))] 27 | #[cfg_attr( 28 | feature = "serde", 29 | serde(bound( 30 | serialize = "T: Serialize", 31 | deserialize = "T: Deserialize<'de> + Copy + Default" 32 | )) 33 | )] 34 | inner: [T; RAND_SIZE], 35 | } 36 | 37 | impl ::core::convert::AsRef<[T]> for IsaacArray { 38 | #[inline(always)] 39 | fn as_ref(&self) -> &[T] { 40 | &self.inner[..] 41 | } 42 | } 43 | 44 | impl ::core::convert::AsMut<[T]> for IsaacArray { 45 | #[inline(always)] 46 | fn as_mut(&mut self) -> &mut [T] { 47 | &mut self.inner[..] 48 | } 49 | } 50 | 51 | impl ::core::ops::Deref for IsaacArray { 52 | type Target = [T; RAND_SIZE]; 53 | #[inline(always)] 54 | fn deref(&self) -> &Self::Target { 55 | &self.inner 56 | } 57 | } 58 | 59 | impl ::core::ops::DerefMut for IsaacArray { 60 | #[inline(always)] 61 | fn deref_mut(&mut self) -> &mut [T; RAND_SIZE] { 62 | &mut self.inner 63 | } 64 | } 65 | 66 | impl ::core::default::Default for IsaacArray 67 | where 68 | T: Copy + Default, 69 | { 70 | fn default() -> IsaacArray { 71 | IsaacArray { 72 | inner: [T::default(); RAND_SIZE], 73 | } 74 | } 75 | } 76 | 77 | // Custom PartialEq implementation as it can't currently be derived from an array of size RAND_SIZE 78 | impl ::core::cmp::PartialEq for IsaacArray 79 | where 80 | T: PartialEq, 81 | { 82 | fn eq(&self, other: &IsaacArray) -> bool { 83 | self.inner[..] == other.inner[..] 84 | } 85 | } 86 | 87 | // Custom Eq implementation as it can't currently be derived from an array of size RAND_SIZE 88 | impl ::core::cmp::Eq for IsaacArray where T: Eq {} 89 | 90 | #[cfg(feature = "serde")] 91 | pub(super) mod isaac_array_serde { 92 | const RAND_SIZE_LEN: usize = 8; 93 | const RAND_SIZE: usize = 1 << RAND_SIZE_LEN; 94 | 95 | use serde::de; 96 | use serde::de::{SeqAccess, Visitor}; 97 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 98 | 99 | use core::fmt; 100 | 101 | pub fn serialize(arr: &[T; RAND_SIZE], ser: S) -> Result 102 | where 103 | T: Serialize, 104 | S: Serializer, 105 | { 106 | use serde::ser::SerializeTuple; 107 | 108 | let mut seq = ser.serialize_tuple(RAND_SIZE)?; 109 | 110 | for e in arr.iter() { 111 | seq.serialize_element(&e)?; 112 | } 113 | 114 | seq.end() 115 | } 116 | 117 | #[inline] 118 | pub fn deserialize<'de, T, D>(de: D) -> Result<[T; RAND_SIZE], D::Error> 119 | where 120 | T: Deserialize<'de> + Default + Copy, 121 | D: Deserializer<'de>, 122 | { 123 | use core::marker::PhantomData; 124 | struct ArrayVisitor { 125 | _pd: PhantomData, 126 | } 127 | impl<'de, T> Visitor<'de> for ArrayVisitor 128 | where 129 | T: Deserialize<'de> + Default + Copy, 130 | { 131 | type Value = [T; RAND_SIZE]; 132 | 133 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 134 | formatter.write_str("Isaac state array") 135 | } 136 | 137 | #[inline] 138 | fn visit_seq(self, mut seq: A) -> Result<[T; RAND_SIZE], A::Error> 139 | where 140 | A: SeqAccess<'de>, 141 | { 142 | let mut out = [Default::default(); RAND_SIZE]; 143 | 144 | for i in 0..RAND_SIZE { 145 | match seq.next_element()? { 146 | Some(val) => out[i] = val, 147 | None => return Err(de::Error::invalid_length(i, &self)), 148 | }; 149 | } 150 | 151 | Ok(out) 152 | } 153 | } 154 | 155 | de.deserialize_tuple(RAND_SIZE, ArrayVisitor { _pd: PhantomData }) 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /rand_isaac/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2023 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! The ISAAC and ISAAC-64 random number generators. 10 | //! 11 | //! To initialize a generator, use the [`SeedableRng`][rand_core::SeedableRng] trait. 12 | 13 | #![doc( 14 | html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", 15 | html_favicon_url = "https://www.rust-lang.org/favicon.ico", 16 | html_root_url = "https://docs.rs/rand_isaac/0.4.0" 17 | )] 18 | #![deny(missing_docs)] 19 | #![deny(missing_debug_implementations)] 20 | #![doc(test(attr(allow(unused_variables), deny(warnings))))] 21 | #![allow( 22 | clippy::too_many_arguments, 23 | clippy::many_single_char_names, 24 | clippy::identity_op 25 | )] 26 | #![cfg_attr(not(all(feature = "serde", test)), no_std)] 27 | 28 | pub mod isaac; 29 | pub mod isaac64; 30 | 31 | mod isaac_array; 32 | 33 | pub use self::isaac::IsaacRng; 34 | pub use self::isaac64::Isaac64Rng; 35 | -------------------------------------------------------------------------------- /rand_jitter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.5.0] - 2025-01-27 8 | - Bump the MSRV to 1.63 (#58) 9 | - Update to `rand_core` v0.9.0 (#58) 10 | 11 | ## [0.4.0] - 2023-12-08 12 | ### Changed 13 | - Update to `rand_core` v0.6 14 | - Bump MSRV to 1.51 15 | - Use return-position impl trait to fix `JitterRng::new` (#16) 16 | 17 | ## [0.3.0] - 2020-09-07 18 | ### Changed 19 | - `JitterRng::new_with_timer` accepts closures (this breaks `JitterRng::new`) 20 | 21 | ## [0.2.1] - 2019-08-16 22 | ### Changed 23 | - `TimerError` changed to `repr(u32)` (#864) 24 | - `TimerError` enum values all increased by `1<<30` to match new `rand_core::Error` range (#864) 25 | 26 | ## [0.2.0] - 2019-06-06 27 | - Bump `rand_core` version 28 | - Support new `Error` type in `rand_core` 0.5 29 | - Remove CryptoRng trait bound (#699, #814) 30 | - Enable doc-testing of README 31 | 32 | ## [0.1.4] - 2019-05-02 33 | - Change error conversion code to partially fix #738 34 | 35 | ## [0.1.3] - 2019-02-05 36 | - Use libc in `no_std` mode to fix #723 37 | 38 | ## [0.1.2] - 2019-01-31 39 | - Fix for older rustc compilers on Windows (#722) 40 | 41 | ## [0.1.1] - 2019-01-29 42 | - Fix for older rustc compilers on Mac OSX / iOS (#720) 43 | - Misc. doc fixes 44 | 45 | ## [0.1.0] - 2019-01-24 46 | Initial release. 47 | -------------------------------------------------------------------------------- /rand_jitter/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the Rand project are retained by their contributors. No 2 | copyright assignment is required to contribute to the Rand project. 3 | 4 | For full authorship information, see the version control history. 5 | 6 | Except as otherwise noted (below and/or in individual files), Rand is 7 | licensed under the Apache License, Version 2.0 or 8 | or the MIT license 9 | or , at your option. 10 | 11 | The Rand project includes code from the Rust project 12 | published under these same licenses. 13 | -------------------------------------------------------------------------------- /rand_jitter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rand_jitter" 3 | version = "0.5.0" 4 | authors = ["The Rand Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | readme = "README.md" 7 | repository = "https://github.com/rust-random/rngs" 8 | documentation = "https://docs.rs/rand_jitter" 9 | description = "Random number generator based on timing jitter" 10 | keywords = ["random", "rng", "os"] 11 | edition = "2021" 12 | rust-version = "1.63" 13 | 14 | [features] 15 | std = ["rand_core/std"] 16 | log = ["dep:log"] 17 | 18 | [dependencies] 19 | rand_core = { version = "0.9.0" } 20 | log = { version = "0.4.4", optional = true } 21 | 22 | [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] 23 | # We don't need the 'use_std' feature and depending on it causes 24 | # issues due to: https://github.com/rust-lang/cargo/issues/1197 25 | libc = { version = "0.2", default-features = false } 26 | 27 | [target.'cfg(target_os = "windows")'.dependencies] 28 | winapi = { version = "0.3", features = ["profileapi"] } 29 | -------------------------------------------------------------------------------- /rand_jitter/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | https://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /rand_jitter/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2018 Developers of the Rand project 2 | Copyright (c) 2014 The Rust Project Developers 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /rand_jitter/README.md: -------------------------------------------------------------------------------- 1 | # rand_jitter 2 | 3 | [![Test Status](https://github.com/rust-random/rngs/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rngs/actions) 4 | [![Latest version](https://img.shields.io/crates/v/rand_jitter.svg)](https://crates.io/crates/rand_jitter) 5 | [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) 6 | [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_jitter) 7 | [![API](https://docs.rs/rand_jitter/badge.svg)](https://docs.rs/rand_jitter) 8 | 9 | Non-physical true random number generator based on timing jitter. 10 | 11 | Note that this RNG is not suited for use cases where cryptographic security is 12 | required (also see [this 13 | discussion](https://github.com/rust-random/rand/issues/699)). 14 | 15 | This crate depends on [rand_core](https://crates.io/crates/rand_core) and is 16 | part of the [Rand project](https://github.com/rust-random/rand). 17 | 18 | This crate aims to support all of Rust's `std` platforms with a system-provided 19 | entropy source. Unlike other Rand crates, this crate does not support `no_std` 20 | (handling this gracefully is a current discussion topic). 21 | 22 | Links: 23 | 24 | - [API documentation (master)](https://rust-random.github.io/rand/rand_jitter) 25 | - [API documentation (docs.rs)](https://docs.rs/rand_jitter) 26 | - [Changelog](https://github.com/rust-random/rngs/blob/master/rand_jitter/CHANGELOG.md) 27 | 28 | ## Features 29 | 30 | This crate has optional `std` support which is *disabled by default*; 31 | this feature is required to provide the `JitterRng::new` function; 32 | without `std` support a timer must be supplied via `JitterRng::new_with_timer`. 33 | 34 | ## Quality testing 35 | 36 | `JitterRng::new()` has built-in, but limited, quality testing, however 37 | before using `JitterRng` on untested hardware, or after changes that could 38 | affect how the code is optimized (such as a new LLVM version), it is 39 | recommended to run the much more stringent 40 | [NIST SP 800-90B Entropy Estimation Suite](https://github.com/usnistgov/SP800-90B_EntropyAssessment). 41 | 42 | Use the following code using `timer_stats` to collect the data: 43 | 44 | ```rust,no_run 45 | use rand_jitter::JitterRng; 46 | 47 | use std::error::Error; 48 | use std::fs::File; 49 | use std::io::Write; 50 | 51 | fn get_nstime() -> u64 { 52 | use std::time::{SystemTime, UNIX_EPOCH}; 53 | 54 | let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); 55 | // The correct way to calculate the current time is 56 | // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64` 57 | // But this is faster, and the difference in terms of entropy is 58 | // negligible (log2(10^9) == 29.9). 59 | dur.as_secs() << 30 | dur.subsec_nanos() as u64 60 | } 61 | 62 | fn main() -> Result<(), Box> { 63 | let mut rng = JitterRng::new_with_timer(get_nstime); 64 | 65 | // 1_000_000 results are required for the 66 | // NIST SP 800-90B Entropy Estimation Suite 67 | const ROUNDS: usize = 1_000_000; 68 | let mut deltas_variable: Vec = Vec::with_capacity(ROUNDS); 69 | let mut deltas_minimal: Vec = Vec::with_capacity(ROUNDS); 70 | 71 | for _ in 0..ROUNDS { 72 | deltas_variable.push(rng.timer_stats(true) as u8); 73 | deltas_minimal.push(rng.timer_stats(false) as u8); 74 | } 75 | 76 | // Write out after the statistics collection loop, to not disturb the 77 | // test results. 78 | File::create("jitter_rng_var.bin")?.write(&deltas_variable)?; 79 | File::create("jitter_rng_min.bin")?.write(&deltas_minimal)?; 80 | Ok(()) 81 | } 82 | ``` 83 | 84 | This will produce two files: `jitter_rng_var.bin` and `jitter_rng_min.bin`. 85 | Run the Entropy Estimation Suite in three configurations, as outlined below. 86 | Every run has two steps. One step to produce an estimation, another to 87 | validate the estimation. 88 | 89 | 1. Estimate the expected amount of entropy that is at least available with 90 | each round of the entropy collector. This number should be greater than 91 | the amount estimated with `64 / test_timer()`. 92 | ```sh 93 | python noniid_main.py -v jitter_rng_var.bin 8 94 | restart.py -v jitter_rng_var.bin 8 95 | ``` 96 | 2. Estimate the expected amount of entropy that is available in the last 4 97 | bits of the timer delta after running noise sources. Note that a value of 98 | `3.70` is the minimum estimated entropy for true randomness. 99 | ```sh 100 | python noniid_main.py -v -u 4 jitter_rng_var.bin 4 101 | restart.py -v -u 4 jitter_rng_var.bin 4 102 | ``` 103 | 3. Estimate the expected amount of entropy that is available to the entropy 104 | collector if both noise sources only run their minimal number of times. 105 | This measures the absolute worst-case, and gives a lower bound for the 106 | available entropy. 107 | ```sh 108 | python noniid_main.py -v -u 4 jitter_rng_min.bin 4 109 | restart.py -v -u 4 jitter_rng_min.bin 4 110 | ``` 111 | 112 | ## License 113 | 114 | `rand_jitter` is distributed under the terms of both the MIT license and the 115 | Apache License (Version 2.0). 116 | 117 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and 118 | [COPYRIGHT](COPYRIGHT) for details. 119 | -------------------------------------------------------------------------------- /rand_jitter/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // Copyright 2013-2015 The Rust Project Developers. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use core::fmt; 11 | 12 | /// Base code for all `JitterRng` errors 13 | const ERROR_BASE: u32 = 0xAE53_0400; 14 | 15 | /// An error that can occur when [`JitterRng::test_timer`] fails. 16 | /// 17 | /// All variants have a value of 0xAE530400 = 2924676096 plus a small 18 | /// increment (1 through 5). 19 | /// 20 | /// [`JitterRng::test_timer`]: crate::JitterRng::test_timer 21 | #[derive(Debug, Clone, PartialEq, Eq)] 22 | #[repr(u32)] 23 | #[allow(clippy::manual_non_exhaustive)] 24 | //^ TODO: Replace with `#[non_exhaustive]` for Rust >= 1.40 25 | pub enum TimerError { 26 | /// No timer available. 27 | NoTimer = ERROR_BASE + 1, 28 | /// Timer too coarse to use as an entropy source. 29 | CoarseTimer = ERROR_BASE + 2, 30 | /// Timer is not monotonically increasing. 31 | NotMonotonic = ERROR_BASE + 3, 32 | /// Variations of deltas of time too small. 33 | TinyVariations = ERROR_BASE + 4, 34 | /// Too many stuck results (indicating no added entropy). 35 | TooManyStuck = ERROR_BASE + 5, 36 | #[doc(hidden)] 37 | __Nonexhaustive, 38 | } 39 | 40 | impl TimerError { 41 | fn description(&self) -> &'static str { 42 | match *self { 43 | TimerError::NoTimer => "no timer available", 44 | TimerError::CoarseTimer => "coarse timer", 45 | TimerError::NotMonotonic => "timer not monotonic", 46 | TimerError::TinyVariations => "time delta variations too small", 47 | TimerError::TooManyStuck => "too many stuck results", 48 | TimerError::__Nonexhaustive => unreachable!(), 49 | } 50 | } 51 | } 52 | 53 | impl fmt::Display for TimerError { 54 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 55 | write!(f, "{}", self.description()) 56 | } 57 | } 58 | 59 | #[cfg(feature = "std")] 60 | impl ::std::error::Error for TimerError { 61 | fn description(&self) -> &str { 62 | self.description() 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /rand_jitter/src/platform.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // Copyright 2013-2015 The Rust Project Developers. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))] 11 | pub fn get_nstime() -> u64 { 12 | use std::time::{SystemTime, UNIX_EPOCH}; 13 | 14 | let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); 15 | // The correct way to calculate the current time is 16 | // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64` 17 | // But this is faster, and the difference in terms of entropy is 18 | // negligible (log2(10^9) == 29.9). 19 | dur.as_secs() << 30 | dur.subsec_nanos() as u64 20 | } 21 | 22 | #[cfg(any(target_os = "macos", target_os = "ios"))] 23 | pub fn get_nstime() -> u64 { 24 | use libc; 25 | 26 | // On Mac OS and iOS std::time::SystemTime only has 1000ns resolution. 27 | // We use `mach_absolute_time` instead. This provides a CPU dependent 28 | // unit, to get real nanoseconds the result should by multiplied by 29 | // numer/denom from `mach_timebase_info`. 30 | // But we are not interested in the exact nanoseconds, just entropy. So 31 | // we use the raw result. 32 | unsafe { libc::mach_absolute_time() } 33 | } 34 | 35 | #[cfg(target_os = "windows")] 36 | pub fn get_nstime() -> u64 { 37 | use winapi; 38 | 39 | unsafe { 40 | let mut t = super::mem::zeroed(); 41 | winapi::um::profileapi::QueryPerformanceCounter(&mut t); 42 | *t.QuadPart() as u64 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /rand_jitter/tests/mod.rs: -------------------------------------------------------------------------------- 1 | use rand_jitter::JitterRng; 2 | 3 | #[cfg(all(feature = "std", not(target_arch = "wasm32")))] 4 | #[test] 5 | fn test_jitter_init() { 6 | use rand_core::RngCore; 7 | 8 | // Because this is a debug build, measurements here are not representative 9 | // of the final release build. 10 | // Don't fail this test if initializing `JitterRng` fails because of a 11 | // bad timer (the timer from the standard library may not have enough 12 | // accuracy on all platforms). 13 | match JitterRng::new() { 14 | Ok(ref mut rng) => { 15 | // false positives are possible, but extremely unlikely 16 | assert!(rng.next_u32() | rng.next_u32() != 0); 17 | } 18 | Err(_) => {} 19 | } 20 | } 21 | 22 | #[test] 23 | fn test_jitter_bad_timer() { 24 | fn bad_timer() -> u64 { 25 | 0 26 | } 27 | let mut rng = JitterRng::new_with_timer(bad_timer); 28 | assert!(rng.test_timer().is_err()); 29 | } 30 | 31 | #[test] 32 | fn test_jitter_closure() { 33 | fn bad_timer() -> u64 { 34 | 0 35 | } 36 | let at_start = bad_timer(); 37 | let _ = JitterRng::new_with_timer(move || bad_timer() - at_start); 38 | } 39 | -------------------------------------------------------------------------------- /rand_xorshift/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.4.0] - 2025-01-27 8 | - Bump the MSRV to 1.63 (#58) 9 | - Update to `rand_core` v0.9.0 (#58) 10 | - Rename feature `serde1` to `serde` (#58) 11 | - Document how zero seeds are handled 12 | - Correctly document MSRV as 1.36 13 | - Speed up `from_seed` implementation for 128-bit seeds 14 | - Add examples for initializing the RNGs 15 | 16 | ## [0.3.0] - 2020-12-18 17 | - Bump `rand_core` version to 0.6 (#17) 18 | - Derive PartialEq+Eq for XorShiftRng (#6) 19 | - Bump serde to 1.0.118 so that `serde1` feature can also be no-std (#12) 20 | 21 | ## [0.2.0] - 2019-06-12 22 | - Bump minor crate version since rand_core bump is a breaking change 23 | - Switch to Edition 2018 24 | 25 | ## [0.1.2] - 2019-06-06 - yanked 26 | - Bump `rand_core` version 27 | - Make XorShiftRng::from_rng portable by enforcing Endianness (#815) 28 | 29 | ## [0.1.1] - 2019-01-04 30 | - Reorganise code and tests; tweak doc 31 | 32 | ## [0.1.0] - 2018-07-16 33 | - Pulled out of the Rand crate 34 | -------------------------------------------------------------------------------- /rand_xorshift/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the Rand project are retained by their contributors. No 2 | copyright assignment is required to contribute to the Rand project. 3 | 4 | For full authorship information, see the version control history. 5 | 6 | Except as otherwise noted (below and/or in individual files), Rand is 7 | licensed under the Apache License, Version 2.0 or 8 | or the MIT license 9 | or , at your option. 10 | 11 | The Rand project includes code from the Rust project 12 | published under these same licenses. 13 | -------------------------------------------------------------------------------- /rand_xorshift/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rand_xorshift" 3 | version = "0.4.0" # NB: When modifying, also modify html_root_url in lib.rs 4 | authors = ["The Rand Project Developers", "The Rust Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | readme = "README.md" 7 | repository = "https://github.com/rust-random/rngs" 8 | documentation = "https://docs.rs/rand_xorshift" 9 | homepage = "https://rust-random.github.io/book" 10 | description = """ 11 | Xorshift random number generator 12 | """ 13 | keywords = ["random", "rng", "xorshift"] 14 | categories = ["algorithms", "no-std"] 15 | edition = "2021" 16 | rust-version = "1.63" 17 | 18 | [features] 19 | serde = ["dep:serde"] 20 | 21 | [dependencies] 22 | rand_core = { version = "0.9.0" } 23 | serde = { version = "1.0.118", default-features = false, features = ["derive"], optional = true } 24 | 25 | [dev-dependencies] 26 | # This is for testing serde, unfortunately we can't specify feature-gated dev 27 | # deps yet, see: https://github.com/rust-lang/cargo/issues/1596 28 | bincode = "1" 29 | -------------------------------------------------------------------------------- /rand_xorshift/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2018 Developers of the Rand project 2 | Copyright (c) 2014 The Rust Project Developers 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /rand_xorshift/README.md: -------------------------------------------------------------------------------- 1 | # rand_xorshift 2 | 3 | [![Test Status](https://github.com/rust-random/rngs/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rngs/actions) 4 | [![Latest version](https://img.shields.io/crates/v/rand_xorshift.svg)](https://crates.io/crates/rand_xorshift) 5 | [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) 6 | [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_xorshift) 7 | [![API](https://docs.rs/rand_xorshift/badge.svg)](https://docs.rs/rand_xorshift) 8 | 9 | Implements the Xorshift random number generator. 10 | 11 | The Xorshift[^1] algorithm is not suitable for cryptographic purposes 12 | but is very fast. If you do not know for sure that it fits your 13 | requirements, use a more secure one such as `StdRng` or `OsRng`. 14 | 15 | [^1]: Marsaglia, George (July 2003). 16 | ["Xorshift RNGs"](https://www.jstatsoft.org/v08/i14/paper). 17 | *Journal of Statistical Software*. Vol. 8 (Issue 14). 18 | 19 | Links: 20 | 21 | - [API documentation (master)](https://rust-random.github.io/rand/rand_xorshift) 22 | - [API documentation (docs.rs)](https://docs.rs/rand_xorshift) 23 | - [Changelog](https://github.com/rust-random/rngs/blob/master/rand_xorshift/CHANGELOG.md) 24 | 25 | [rand]: https://crates.io/crates/rand 26 | 27 | 28 | ## Crate Features 29 | 30 | `rand_xorshift` is `no_std` compatible. It does not require any functionality 31 | outside of the `core` lib, thus there are no features to configure. 32 | 33 | The `serde` feature includes implementations of `Serialize` and `Deserialize` 34 | for the included RNGs. 35 | 36 | 37 | ## License 38 | 39 | `rand_xorshift` is distributed under the terms of both the MIT license and the 40 | Apache License (Version 2.0). 41 | 42 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and 43 | [COPYRIGHT](COPYRIGHT) for details. 44 | -------------------------------------------------------------------------------- /rand_xorshift/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2023 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! The xorshift random number generator. 10 | //! 11 | //! # Example 12 | //! 13 | //! To initialize a generator, use the [`SeedableRng`][rand_core::SeedableRng] trait: 14 | //! 15 | //! ``` 16 | //! use rand_core::{SeedableRng, RngCore}; 17 | //! use rand_xorshift::XorShiftRng; 18 | //! 19 | //! let mut rng = XorShiftRng::seed_from_u64(0); 20 | //! let x = rng.next_u32(); 21 | //! ``` 22 | 23 | #![doc( 24 | html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", 25 | html_favicon_url = "https://www.rust-lang.org/favicon.ico", 26 | html_root_url = "https://docs.rs/rand_xorshift/0.4.0" 27 | )] 28 | #![forbid(unsafe_code)] 29 | #![deny(missing_docs)] 30 | #![deny(missing_debug_implementations)] 31 | #![no_std] 32 | 33 | use core::fmt; 34 | use core::num::Wrapping as w; 35 | use rand_core::{impls, le, RngCore, SeedableRng, TryRngCore}; 36 | #[cfg(feature = "serde")] 37 | use serde::{Deserialize, Serialize}; 38 | 39 | /// An Xorshift random number generator. 40 | /// 41 | /// The Xorshift[^1] algorithm is not suitable for cryptographic purposes 42 | /// but is very fast. If you do not know for sure that it fits your 43 | /// requirements, use a more secure one such as `StdRng` or `OsRng`. 44 | /// 45 | /// When seeded with zero (i.e. `XorShiftRng::from_seed(0)` is called), this implementation 46 | /// actually uses `0xBAD_5EED_0BAD_5EED_0BAD_5EED_0BAD_5EED` for the seed. This arbitrary value is 47 | /// used because the underlying algorithm can't escape from an all-zero state, and the function is 48 | /// infallible so it can't signal this by returning an error. 49 | /// 50 | /// [^1]: Marsaglia, George (July 2003). 51 | /// ["Xorshift RNGs"](https://www.jstatsoft.org/v08/i14/paper). 52 | /// *Journal of Statistical Software*. Vol. 8 (Issue 14). 53 | #[derive(Clone, PartialEq, Eq)] 54 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 55 | pub struct XorShiftRng { 56 | x: w, 57 | y: w, 58 | z: w, 59 | w: w, 60 | } 61 | 62 | // Custom Debug implementation that does not expose the internal state 63 | impl fmt::Debug for XorShiftRng { 64 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 65 | write!(f, "XorShiftRng {{}}") 66 | } 67 | } 68 | 69 | impl RngCore for XorShiftRng { 70 | #[inline] 71 | fn next_u32(&mut self) -> u32 { 72 | // These shifts are taken from the example in the Summary section of 73 | // the paper 'Xorshift RNGs'. (On the bottom of page 5.) 74 | let x = self.x; 75 | let t = x ^ (x << 11); 76 | self.x = self.y; 77 | self.y = self.z; 78 | self.z = self.w; 79 | let w_ = self.w; 80 | self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); 81 | self.w.0 82 | } 83 | 84 | #[inline] 85 | fn next_u64(&mut self) -> u64 { 86 | impls::next_u64_via_u32(self) 87 | } 88 | 89 | #[inline] 90 | fn fill_bytes(&mut self, dest: &mut [u8]) { 91 | impls::fill_bytes_via_next(self, dest) 92 | } 93 | } 94 | 95 | impl SeedableRng for XorShiftRng { 96 | type Seed = [u8; 16]; 97 | 98 | fn from_seed(seed: Self::Seed) -> Self { 99 | let mut seed_u32 = [0u32; 4]; 100 | le::read_u32_into(&seed, &mut seed_u32); 101 | 102 | // Xorshift cannot be seeded with 0 and we cannot return an Error, but 103 | // also do not wish to panic (because a random seed can legitimately be 104 | // 0); our only option is therefore to use a preset value. 105 | if seed_u32 == [0; 4] { 106 | seed_u32 = [0xBAD_5EED, 0xBAD_5EED, 0xBAD_5EED, 0xBAD_5EED]; 107 | } 108 | 109 | XorShiftRng { 110 | x: w(seed_u32[0]), 111 | y: w(seed_u32[1]), 112 | z: w(seed_u32[2]), 113 | w: w(seed_u32[3]), 114 | } 115 | } 116 | 117 | fn from_rng(rng: &mut impl RngCore) -> Self { 118 | let mut b = [0u8; 16]; 119 | loop { 120 | rng.fill_bytes(b.as_mut()); 121 | if b != [0; 16] { 122 | break; 123 | } 124 | } 125 | 126 | XorShiftRng { 127 | x: w(u32::from_le_bytes([b[0], b[1], b[2], b[3]])), 128 | y: w(u32::from_le_bytes([b[4], b[5], b[6], b[7]])), 129 | z: w(u32::from_le_bytes([b[8], b[9], b[10], b[11]])), 130 | w: w(u32::from_le_bytes([b[12], b[13], b[14], b[15]])), 131 | } 132 | } 133 | 134 | fn try_from_rng(rng: &mut R) -> Result { 135 | let mut b = [0u8; 16]; 136 | loop { 137 | rng.try_fill_bytes(b.as_mut())?; 138 | if b != [0; 16] { 139 | break; 140 | } 141 | } 142 | 143 | Ok(XorShiftRng { 144 | x: w(u32::from_le_bytes([b[0], b[1], b[2], b[3]])), 145 | y: w(u32::from_le_bytes([b[4], b[5], b[6], b[7]])), 146 | z: w(u32::from_le_bytes([b[8], b[9], b[10], b[11]])), 147 | w: w(u32::from_le_bytes([b[12], b[13], b[14], b[15]])), 148 | }) 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /rand_xorshift/tests/mod.rs: -------------------------------------------------------------------------------- 1 | use rand_core::{RngCore, SeedableRng}; 2 | use rand_xorshift::XorShiftRng; 3 | 4 | #[test] 5 | fn test_xorshift_construction() { 6 | // Test that various construction techniques produce a working RNG. 7 | let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 8 | let mut rng1 = XorShiftRng::from_seed(seed); 9 | assert_eq!(rng1.next_u64(), 4325440999699518727); 10 | 11 | let mut rng2 = XorShiftRng::from_rng(&mut rng1); 12 | // Yes, this makes rng2 a clone of rng1! 13 | assert_eq!(rng1.next_u64(), 15614385950550801700); 14 | assert_eq!(rng2.next_u64(), 15614385950550801700); 15 | } 16 | 17 | #[test] 18 | fn test_xorshift_true_values() { 19 | let seed = [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; 20 | let mut rng = XorShiftRng::from_seed(seed); 21 | 22 | let mut results = [0u32; 9]; 23 | for i in results.iter_mut() { 24 | *i = rng.next_u32(); 25 | } 26 | let expected: [u32; 9] = [ 27 | 2081028795, 620940381, 269070770, 16943764, 854422573, 29242889, 1550291885, 1227154591, 28 | 271695242, 29 | ]; 30 | assert_eq!(results, expected); 31 | 32 | let mut results = [0u64; 9]; 33 | for i in results.iter_mut() { 34 | *i = rng.next_u64(); 35 | } 36 | let expected: [u64; 9] = [ 37 | 9247529084182843387, 38 | 8321512596129439293, 39 | 14104136531997710878, 40 | 6848554330849612046, 41 | 343577296533772213, 42 | 17828467390962600268, 43 | 9847333257685787782, 44 | 7717352744383350108, 45 | 1133407547287910111, 46 | ]; 47 | assert_eq!(results, expected); 48 | 49 | let mut results = [0u8; 32]; 50 | rng.fill_bytes(&mut results); 51 | let expected = [ 52 | 102, 57, 212, 16, 233, 130, 49, 183, 158, 187, 44, 203, 63, 149, 45, 17, 117, 129, 131, 53 | 160, 70, 121, 158, 155, 224, 209, 192, 53, 10, 62, 57, 72, 54 | ]; 55 | assert_eq!(results, expected); 56 | } 57 | 58 | #[test] 59 | fn test_xorshift_zero_seed() { 60 | // Xorshift does not work with an all zero seed. 61 | // Assert it does not panic. 62 | let seed = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 63 | let mut rng = XorShiftRng::from_seed(seed); 64 | let a = rng.next_u64(); 65 | let b = rng.next_u64(); 66 | assert!(a != 0); 67 | assert!(b != a); 68 | } 69 | 70 | #[test] 71 | fn test_xorshift_clone() { 72 | let seed = [1, 2, 3, 4, 5, 5, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1]; 73 | let mut rng1 = XorShiftRng::from_seed(seed); 74 | let mut rng2 = rng1.clone(); 75 | for _ in 0..16 { 76 | assert_eq!(rng1.next_u64(), rng2.next_u64()); 77 | } 78 | } 79 | 80 | #[cfg(feature = "serde")] 81 | #[test] 82 | fn test_xorshift_serde() { 83 | use bincode; 84 | use std::io::{BufReader, BufWriter}; 85 | 86 | let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 87 | let mut rng = XorShiftRng::from_seed(seed); 88 | 89 | let buf: Vec = Vec::new(); 90 | let mut buf = BufWriter::new(buf); 91 | bincode::serialize_into(&mut buf, &rng).expect("Could not serialize"); 92 | 93 | let buf = buf.into_inner().unwrap(); 94 | let mut read = BufReader::new(&buf[..]); 95 | let mut deserialized: XorShiftRng = 96 | bincode::deserialize_from(&mut read).expect("Could not deserialize"); 97 | 98 | for _ in 0..16 { 99 | assert_eq!(rng.next_u64(), deserialized.next_u64()); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /rand_xoshiro/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.7.0] - 2025-01-27 8 | - Bump the MSRV to 1.63 (#58) 9 | - Update to `rand_core` v0.9.0 (#58) 10 | - Rename feature `serde1` to `serde` (#58) 11 | - Add `Xoshiro128Plus::long_jump` 12 | - Add examples for initializing the RNGs 13 | - Speed up `from_seed` implementation for 128-bit seeds 14 | - Fix a few typos in the docs 15 | 16 | ## [0.6.0] - 2020-12-18 17 | - Bump `rand_core` version to 0.6 (#17) 18 | 19 | ## [0.5.0] - 2020-09-11 20 | - Derive PartialEq+Eq for SplitMix64, Xoroshiro64Star, Xoroshiro64StarStar, 21 | Xoroshiro128Plus, Xoroshiro128PlusPlus, Xoroshiro128StarStar, 22 | Xoshiro128Plus, Xoshiro128PlusPlus, Xoshiro128StarStar, Xoshiro256Plus, 23 | Xoshiro256PlusPlus, Xoshiro256StarStar, Xoshiro512Plus, Xoshiro512PlusPlus, 24 | and Xoshiro512StarStar (#6) 25 | - `next_u32`: Prefer upper bits for `Xoshiro256{PlusPlus,StarStar}` and 26 | `Xoshiro512{Plus,PlusPlus,StarStar}`, breaking value stability 27 | 28 | ## [0.4.0] - 2019-09-03 29 | - Add xoshiro128++, 256++ and 512++ variants 30 | - Add xoroshiro128++ variant 31 | - Add `long_jump` method to RNGs missing it 32 | - Update xoshiro128** to version 1.1, breaking value stability 33 | 34 | ## [0.3.1] - 2019-08-06 35 | - Drop `byteorder`-dependency in favor of `stdlib`-implementation. 36 | 37 | ## [0.3.0] - 2019-06-12 38 | - Bump minor crate version since rand_core bump is a breaking change 39 | - Switch to Edition 2018 40 | 41 | ## [0.2.1] - 2019-06-06 - yanked 42 | - Bump `rand_core` version 43 | - Document crate features in README 44 | 45 | ## [0.2.0] - 2019-05-28 46 | - Fix `seed_from_u64(0)` for `Xoroshiro64StarStar` and `Xoroshiro64Star`. This 47 | breaks value stability for these generators if initialized with `seed_from_u64`. 48 | - Implement Serde support. 49 | 50 | ## [0.1.0] - 2019-01-04 51 | Initial release. 52 | -------------------------------------------------------------------------------- /rand_xoshiro/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the Rand project are retained by their contributors. No 2 | copyright assignment is required to contribute to the Rand project. 3 | 4 | For full authorship information, see the version control history. 5 | 6 | Except as otherwise noted (below and/or in individual files), Rand is 7 | licensed under the Apache License, Version 2.0 or 8 | or the MIT license 9 | or , at your option. 10 | 11 | The Rand project includes code from the Rust project 12 | published under these same licenses. 13 | -------------------------------------------------------------------------------- /rand_xoshiro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rand_xoshiro" 3 | version = "0.7.0" # NB: When modifying, also modify html_root_url in lib.rs 4 | authors = ["The Rand Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | readme = "README.md" 7 | repository = "https://github.com/rust-random/rngs" 8 | documentation = "https://docs.rs/rand_xoshiro" 9 | homepage = "https://rust-random.github.io/book" 10 | description = "Xoshiro, xoroshiro and splitmix64 random number generators" 11 | keywords = ["random", "rng"] 12 | categories = ["algorithms"] 13 | edition = "2021" 14 | rust-version = "1.63" 15 | 16 | [features] 17 | serde = ["dep:serde"] 18 | 19 | [dependencies] 20 | rand_core = { version = "0.9.0" } 21 | serde = { version = "1", features = ["derive"], optional=true } 22 | 23 | [dev-dependencies] 24 | # This is for testing serde, unfortunately we can't specify feature-gated dev 25 | # deps yet, see: https://github.com/rust-lang/cargo/issues/1596 26 | bincode = { version = "1" } 27 | -------------------------------------------------------------------------------- /rand_xoshiro/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /rand_xoshiro/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Developers of the Rand project 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /rand_xoshiro/README.md: -------------------------------------------------------------------------------- 1 | # rand_xoshiro 2 | 3 | [![Test Status](https://github.com/rust-random/rngs/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-random/rngs/actions) 4 | [![Latest version](https://img.shields.io/crates/v/rand_xoshiro.svg)](https://crates.io/crates/rand_xoshiro) 5 | [![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) 6 | [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_xoshiro) 7 | [![API](https://docs.rs/rand_xoshiro/badge.svg)](https://docs.rs/rand_xoshiro) 8 | 9 | Rust implementation of the [xoshiro, xoroshiro and splitmix64](http://xoshiro.di.unimi.it) random number generators. 10 | 11 | This crate depends on [rand_core](https://crates.io/crates/rand_core) and is 12 | part of the [Rand project](https://github.com/rust-random/rand). 13 | 14 | Links: 15 | 16 | - [API documentation (master)](https://rust-random.github.io/rand/rand_xoshiro) 17 | - [API documentation (docs.rs)](https://docs.rs/rand_xoshiro) 18 | - [Changelog](https://github.com/rust-random/rngs/blob/master/rand_xoshiro/CHANGELOG.md) 19 | 20 | ## Crate Features 21 | 22 | `rand_xoshiro` is no_std compatible by default. 23 | 24 | The `serde` feature includes implementations of `Serialize` and `Deserialize` for the included RNGs. 25 | 26 | ## License 27 | 28 | `rand_xoshiro` is distributed under the terms of both the MIT license and the 29 | Apache License (Version 2.0). 30 | 31 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and 32 | [COPYRIGHT](COPYRIGHT) for details. 33 | -------------------------------------------------------------------------------- /rand_xoshiro/src/common.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | /// Initialize a RNG from a `u64` seed using `SplitMix64`. 10 | macro_rules! from_splitmix { 11 | ($seed:expr) => {{ 12 | let mut rng = crate::SplitMix64::seed_from_u64($seed); 13 | Self::from_rng(&mut rng) 14 | }}; 15 | } 16 | 17 | /// Apply the ** scrambler used by some RNGs from the xoshiro family. 18 | macro_rules! starstar_u64 { 19 | ($x:expr) => { 20 | $x.wrapping_mul(5).rotate_left(7).wrapping_mul(9) 21 | }; 22 | } 23 | 24 | /// Apply the ** scrambler used by some RNGs from the xoshiro family. 25 | macro_rules! starstar_u32 { 26 | ($x:expr) => { 27 | $x.wrapping_mul(0x9E3779BB).rotate_left(5).wrapping_mul(5) 28 | }; 29 | } 30 | 31 | /// Apply the ++ scrambler used by some RNGs from the xoshiro family. 32 | macro_rules! plusplus_u64 { 33 | ($x:expr, $y:expr, $rot:expr) => { 34 | $x.wrapping_add($y).rotate_left($rot).wrapping_add($x) 35 | }; 36 | } 37 | 38 | /// Apply the ++ scrambler used by some RNGs from the xoshiro family. 39 | macro_rules! plusplus_u32 { 40 | ($x:expr, $y:expr) => { 41 | $x.wrapping_add($y).rotate_left(7).wrapping_add($x) 42 | }; 43 | } 44 | 45 | /// Implement a jump function for an RNG from the xoshiro family. 46 | macro_rules! impl_jump { 47 | (u32, $self:expr, [$j0:expr, $j1:expr]) => { 48 | const JUMP: [u32; 2] = [$j0, $j1]; 49 | let mut s0 = 0; 50 | let mut s1 = 0; 51 | for j in &JUMP { 52 | for b in 0..32 { 53 | if (j & 1 << b) != 0 { 54 | s0 ^= $self.s0; 55 | s1 ^= $self.s1; 56 | } 57 | $self.next_u32(); 58 | } 59 | } 60 | $self.s0 = s0; 61 | $self.s1 = s1; 62 | }; 63 | (u64, $self:expr, [$j0:expr, $j1:expr]) => { 64 | const JUMP: [u64; 2] = [$j0, $j1]; 65 | let mut s0 = 0; 66 | let mut s1 = 0; 67 | for j in &JUMP { 68 | for b in 0..64 { 69 | if (j & 1 << b) != 0 { 70 | s0 ^= $self.s0; 71 | s1 ^= $self.s1; 72 | } 73 | $self.next_u64(); 74 | } 75 | } 76 | $self.s0 = s0; 77 | $self.s1 = s1; 78 | }; 79 | (u32, $self:expr, [$j0:expr, $j1:expr, $j2:expr, $j3:expr]) => { 80 | const JUMP: [u32; 4] = [$j0, $j1, $j2, $j3]; 81 | let mut s0 = 0; 82 | let mut s1 = 0; 83 | let mut s2 = 0; 84 | let mut s3 = 0; 85 | for j in &JUMP { 86 | for b in 0..32 { 87 | if (j & 1 << b) != 0 { 88 | s0 ^= $self.s[0]; 89 | s1 ^= $self.s[1]; 90 | s2 ^= $self.s[2]; 91 | s3 ^= $self.s[3]; 92 | } 93 | $self.next_u32(); 94 | } 95 | } 96 | $self.s[0] = s0; 97 | $self.s[1] = s1; 98 | $self.s[2] = s2; 99 | $self.s[3] = s3; 100 | }; 101 | (u64, $self:expr, [$j0:expr, $j1:expr, $j2:expr, $j3:expr]) => { 102 | const JUMP: [u64; 4] = [$j0, $j1, $j2, $j3]; 103 | let mut s0 = 0; 104 | let mut s1 = 0; 105 | let mut s2 = 0; 106 | let mut s3 = 0; 107 | for j in &JUMP { 108 | for b in 0..64 { 109 | if (j & 1 << b) != 0 { 110 | s0 ^= $self.s[0]; 111 | s1 ^= $self.s[1]; 112 | s2 ^= $self.s[2]; 113 | s3 ^= $self.s[3]; 114 | } 115 | $self.next_u64(); 116 | } 117 | } 118 | $self.s[0] = s0; 119 | $self.s[1] = s1; 120 | $self.s[2] = s2; 121 | $self.s[3] = s3; 122 | }; 123 | (u64, $self:expr, [$j0:expr, $j1:expr, $j2:expr, $j3:expr, 124 | $j4:expr, $j5:expr, $j6:expr, $j7:expr]) => { 125 | const JUMP: [u64; 8] = [$j0, $j1, $j2, $j3, $j4, $j5, $j6, $j7]; 126 | let mut s = [0; 8]; 127 | for j in &JUMP { 128 | for b in 0..64 { 129 | if (j & 1 << b) != 0 { 130 | s[0] ^= $self.s[0]; 131 | s[1] ^= $self.s[1]; 132 | s[2] ^= $self.s[2]; 133 | s[3] ^= $self.s[3]; 134 | s[4] ^= $self.s[4]; 135 | s[5] ^= $self.s[5]; 136 | s[6] ^= $self.s[6]; 137 | s[7] ^= $self.s[7]; 138 | } 139 | $self.next_u64(); 140 | } 141 | } 142 | $self.s = s; 143 | }; 144 | } 145 | 146 | /// Implement the xoroshiro iteration. 147 | macro_rules! impl_xoroshiro_u32 { 148 | ($self:expr) => { 149 | $self.s1 ^= $self.s0; 150 | $self.s0 = $self.s0.rotate_left(26) ^ $self.s1 ^ ($self.s1 << 9); 151 | $self.s1 = $self.s1.rotate_left(13); 152 | }; 153 | } 154 | 155 | /// Implement the xoroshiro iteration. 156 | macro_rules! impl_xoroshiro_u64 { 157 | ($self:expr) => { 158 | $self.s1 ^= $self.s0; 159 | $self.s0 = $self.s0.rotate_left(24) ^ $self.s1 ^ ($self.s1 << 16); 160 | $self.s1 = $self.s1.rotate_left(37); 161 | }; 162 | } 163 | 164 | /// Implement the xoroshiro iteration for the ++ scrambler. 165 | macro_rules! impl_xoroshiro_u64_plusplus { 166 | ($self:expr) => { 167 | $self.s1 ^= $self.s0; 168 | $self.s0 = $self.s0.rotate_left(49) ^ $self.s1 ^ ($self.s1 << 21); 169 | $self.s1 = $self.s1.rotate_left(28); 170 | }; 171 | } 172 | 173 | /// Implement the xoshiro iteration for `u32` output. 174 | macro_rules! impl_xoshiro_u32 { 175 | ($self:expr) => { 176 | let t = $self.s[1] << 9; 177 | 178 | $self.s[2] ^= $self.s[0]; 179 | $self.s[3] ^= $self.s[1]; 180 | $self.s[1] ^= $self.s[2]; 181 | $self.s[0] ^= $self.s[3]; 182 | 183 | $self.s[2] ^= t; 184 | 185 | $self.s[3] = $self.s[3].rotate_left(11); 186 | }; 187 | } 188 | 189 | /// Implement the xoshiro iteration for `u64` output. 190 | macro_rules! impl_xoshiro_u64 { 191 | ($self:expr) => { 192 | let t = $self.s[1] << 17; 193 | 194 | $self.s[2] ^= $self.s[0]; 195 | $self.s[3] ^= $self.s[1]; 196 | $self.s[1] ^= $self.s[2]; 197 | $self.s[0] ^= $self.s[3]; 198 | 199 | $self.s[2] ^= t; 200 | 201 | $self.s[3] = $self.s[3].rotate_left(45); 202 | }; 203 | } 204 | 205 | /// Implement the large-state xoshiro iteration. 206 | macro_rules! impl_xoshiro_large { 207 | ($self:expr) => { 208 | let t = $self.s[1] << 11; 209 | 210 | $self.s[2] ^= $self.s[0]; 211 | $self.s[5] ^= $self.s[1]; 212 | $self.s[1] ^= $self.s[2]; 213 | $self.s[7] ^= $self.s[3]; 214 | $self.s[3] ^= $self.s[4]; 215 | $self.s[4] ^= $self.s[5]; 216 | $self.s[0] ^= $self.s[6]; 217 | $self.s[6] ^= $self.s[7]; 218 | 219 | $self.s[6] ^= t; 220 | 221 | $self.s[7] = $self.s[7].rotate_left(21); 222 | }; 223 | } 224 | 225 | /// Map an all-zero seed to a different one. 226 | macro_rules! deal_with_zero_seed { 227 | ($seed:expr, $Self:ident, $bytes:expr) => { 228 | if $seed == [0; $bytes] { 229 | return $Self::seed_from_u64(0); 230 | } 231 | }; 232 | 233 | ($seed:expr, $Self:ident) => { 234 | if $seed.iter().all(|&x| x == 0) { 235 | return $Self::seed_from_u64(0); 236 | } 237 | }; 238 | } 239 | 240 | /// 512-bit seed for a generator. 241 | /// 242 | /// This wrapper is necessary, because some traits required for a seed are not 243 | /// implemented on large arrays. 244 | #[derive(Clone)] 245 | pub struct Seed512(pub [u8; 64]); 246 | 247 | impl Seed512 { 248 | /// Return an iterator over the seed. 249 | pub fn iter(&self) -> core::slice::Iter { 250 | self.0.iter() 251 | } 252 | } 253 | 254 | impl core::fmt::Debug for Seed512 { 255 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 256 | self.0[..].fmt(f) 257 | } 258 | } 259 | 260 | impl Default for Seed512 { 261 | fn default() -> Seed512 { 262 | Seed512([0; 64]) 263 | } 264 | } 265 | 266 | impl AsRef<[u8]> for Seed512 { 267 | fn as_ref(&self) -> &[u8] { 268 | &self.0 269 | } 270 | } 271 | 272 | impl AsMut<[u8]> for Seed512 { 273 | fn as_mut(&mut self) -> &mut [u8] { 274 | &mut self.0 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /rand_xoshiro/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2023 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! This crate implements the [xoshiro] family of pseudorandom number generators 10 | //! designed by David Blackman and Sebastiano Vigna. They feature high 11 | //! performance and a small state and supersede the previous xorshift-based 12 | //! generators. However, they are not cryptographically secure and their output 13 | //! can be predicted by observing a few samples. 14 | //! 15 | //! The following generators are implemented: 16 | //! 17 | //! # 64-bit generators 18 | //! - [`Xoshiro256StarStar`]: Recommended for all purposes. Excellent speed and 19 | //! a state space (256 bits) large enough for any parallel application. 20 | //! - [`Xoshiro256PlusPlus`]: Recommended for all purposes. Excellent speed and 21 | //! a state space (256 bits) large enough for any parallel application. 22 | //! - [`Xoshiro256Plus`]: Recommended for generating 64-bit floating-point 23 | //! numbers. About 15% faster than `Xoshiro256StarStar`, but has a [low linear 24 | //! complexity] in the lowest bits (which are discarded when generating 25 | //! floats), making it fail linearity tests. This is unlikely to have any 26 | //! impact in practise. 27 | //! - [`Xoroshiro128StarStar`]: An alternative to `Xoshiro256StarStar`, having 28 | //! the same speed but using half the state. Only suited for low-scale parallel 29 | //! applications. 30 | //! - [`Xoroshiro128PlusPlus`]: An alternative to `Xoshiro256PlusPlus`, having 31 | //! the same speed but using half the state. Only suited for low-scale parallel 32 | //! applications. 33 | //! - [`Xoroshiro128Plus`]: An alternative to `Xoshiro256Plus`, having the same 34 | //! speed but using half the state. Only suited for low-scale parallel 35 | //! applications. Has a [low linear complexity] in the lowest bits (which are 36 | //! discarded when generating floats), making it fail linearity tests. This is 37 | //! unlikely to have any impact in practise. 38 | //! - [`Xoshiro512StarStar`]: An alternative to `Xoshiro256StarStar` with more 39 | //! state and the same speed. 40 | //! - [`Xoshiro512PlusPlus`]: An alternative to `Xoshiro256PlusPlus` with more 41 | //! state and the same speed. 42 | //! - [`Xoshiro512Plus`]: An alternative to `Xoshiro512Plus` with more 43 | //! state and the same speed. Has a [low linear complexity] in the lowest bits 44 | //! (which are discarded when generating floats), making it fail linearity 45 | //! tests. This is unlikely to have any impact in practise. 46 | //! - [`SplitMix64`]: Recommended for initializing generators of the xoshiro 47 | //! family from a 64-bit seed. Used for implementing `seed_from_u64`. 48 | //! 49 | //! # 32-bit generators 50 | //! - [`Xoshiro128StarStar`]: Recommended for all purposes. Excellent speed. 51 | //! - [`Xoshiro128PlusPlus`]: Recommended for all purposes. Excellent speed. 52 | //! - [`Xoshiro128Plus`]: Recommended for generating 32-bit floating-point 53 | //! numbers. Faster than `Xoshiro128StarStar`, but has a [low linear 54 | //! complexity] in the lowest bits (which are discarded when generating 55 | //! floats), making it fail linearity tests. This is unlikely to have any 56 | //! impact in practise. 57 | //! - [`Xoroshiro64StarStar`]: An alternative to `Xoshiro128StarStar`, having 58 | //! the same speed but using half the state. 59 | //! - [`Xoroshiro64Star`]: An alternative to `Xoshiro128Plus`, having the 60 | //! same speed but using half the state. Has a [low linear complexity] in the 61 | //! lowest bits (which are discarded when generating floats), making it fail 62 | //! linearity tests. This is unlikely to have any impact in practise. 63 | //! 64 | //! The `*PlusPlus` generators perform similarly to the `*StarStar` generators. 65 | //! See the [xoshiro paper], where the differences are discussed in detail. 66 | //! 67 | //! # Example 68 | //! 69 | //! To initialize a generator, use the [`SeedableRng`][rand_core::SeedableRng] trait: 70 | //! 71 | //! ``` 72 | //! use rand_core::{SeedableRng, RngCore}; 73 | //! use rand_xoshiro::Xoshiro256PlusPlus; 74 | //! 75 | //! let mut rng = Xoshiro256PlusPlus::seed_from_u64(0); 76 | //! let x = rng.next_u64(); 77 | //! ``` 78 | //! 79 | //! [xoshiro]: http://xoshiro.di.unimi.it/ 80 | //! [xoshiro paper]: http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf 81 | //! [low linear complexity]: http://xoshiro.di.unimi.it/lowcomp.php 82 | 83 | #![doc( 84 | html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", 85 | html_favicon_url = "https://www.rust-lang.org/favicon.ico", 86 | html_root_url = "https://docs.rs/rand_xoshiro/0.7.0" 87 | )] 88 | #![forbid(unsafe_code)] 89 | #![deny(missing_docs)] 90 | #![deny(missing_debug_implementations)] 91 | #![allow(clippy::unreadable_literal)] 92 | #![no_std] 93 | 94 | #[macro_use] 95 | mod common; 96 | mod splitmix64; 97 | mod xoroshiro128plus; 98 | mod xoroshiro128plusplus; 99 | mod xoroshiro128starstar; 100 | mod xoroshiro64star; 101 | mod xoroshiro64starstar; 102 | mod xoshiro128plus; 103 | mod xoshiro128plusplus; 104 | mod xoshiro128starstar; 105 | mod xoshiro256plus; 106 | mod xoshiro256plusplus; 107 | mod xoshiro256starstar; 108 | mod xoshiro512plus; 109 | mod xoshiro512plusplus; 110 | mod xoshiro512starstar; 111 | 112 | pub use common::Seed512; 113 | pub use rand_core; 114 | pub use splitmix64::SplitMix64; 115 | pub use xoroshiro128plus::Xoroshiro128Plus; 116 | pub use xoroshiro128plusplus::Xoroshiro128PlusPlus; 117 | pub use xoroshiro128starstar::Xoroshiro128StarStar; 118 | pub use xoroshiro64star::Xoroshiro64Star; 119 | pub use xoroshiro64starstar::Xoroshiro64StarStar; 120 | pub use xoshiro128plus::Xoshiro128Plus; 121 | pub use xoshiro128plusplus::Xoshiro128PlusPlus; 122 | pub use xoshiro128starstar::Xoshiro128StarStar; 123 | pub use xoshiro256plus::Xoshiro256Plus; 124 | pub use xoshiro256plusplus::Xoshiro256PlusPlus; 125 | pub use xoshiro256starstar::Xoshiro256StarStar; 126 | pub use xoshiro512plus::Xoshiro512Plus; 127 | pub use xoshiro512plusplus::Xoshiro512PlusPlus; 128 | pub use xoshiro512starstar::Xoshiro512StarStar; 129 | -------------------------------------------------------------------------------- /rand_xoshiro/src/splitmix64.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A splitmix64 random number generator. 16 | /// 17 | /// The splitmix algorithm is not suitable for cryptographic purposes, but is 18 | /// very fast and has a 64 bit state. 19 | /// 20 | /// The algorithm used here is translated from [the `splitmix64.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/splitmix64.c) by 22 | /// Sebastiano Vigna. For `next_u32`, a more efficient mixing function taken 23 | /// from [`dsiutils`](http://dsiutils.di.unimi.it/) is used. 24 | #[allow(missing_copy_implementations)] 25 | #[derive(Debug, Clone, PartialEq, Eq)] 26 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 27 | pub struct SplitMix64 { 28 | x: u64, 29 | } 30 | 31 | const PHI: u64 = 0x9e3779b97f4a7c15; 32 | 33 | impl RngCore for SplitMix64 { 34 | #[inline] 35 | fn next_u32(&mut self) -> u32 { 36 | self.x = self.x.wrapping_add(PHI); 37 | let mut z = self.x; 38 | // David Stafford's 39 | // (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html) 40 | // "Mix4" variant of the 64-bit finalizer in Austin Appleby's 41 | // MurmurHash3 algorithm. 42 | z = (z ^ (z >> 33)).wrapping_mul(0x62A9D9ED799705F5); 43 | z = (z ^ (z >> 28)).wrapping_mul(0xCB24D0A5C88C35B3); 44 | (z >> 32) as u32 45 | } 46 | 47 | #[inline] 48 | fn next_u64(&mut self) -> u64 { 49 | self.x = self.x.wrapping_add(PHI); 50 | let mut z = self.x; 51 | z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9); 52 | z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb); 53 | z ^ (z >> 31) 54 | } 55 | 56 | #[inline] 57 | fn fill_bytes(&mut self, dest: &mut [u8]) { 58 | fill_bytes_via_next(self, dest); 59 | } 60 | } 61 | 62 | impl SeedableRng for SplitMix64 { 63 | type Seed = [u8; 8]; 64 | 65 | /// Create a new `SplitMix64`. 66 | fn from_seed(seed: [u8; 8]) -> SplitMix64 { 67 | let mut state = [0; 1]; 68 | read_u64_into(&seed, &mut state); 69 | SplitMix64 { x: state[0] } 70 | } 71 | 72 | /// Seed a `SplitMix64` from a `u64`. 73 | fn seed_from_u64(seed: u64) -> SplitMix64 { 74 | SplitMix64::from_seed(seed.to_le_bytes()) 75 | } 76 | } 77 | 78 | #[cfg(test)] 79 | mod tests { 80 | use super::*; 81 | 82 | #[test] 83 | fn reference() { 84 | let mut rng = SplitMix64::seed_from_u64(1477776061723855037); 85 | // These values were produced with the reference implementation: 86 | // http://xoshiro.di.unimi.it/splitmix64.c 87 | let expected: [u64; 50] = [ 88 | 1985237415132408290, 89 | 2979275885539914483, 90 | 13511426838097143398, 91 | 8488337342461049707, 92 | 15141737807933549159, 93 | 17093170987380407015, 94 | 16389528042912955399, 95 | 13177319091862933652, 96 | 10841969400225389492, 97 | 17094824097954834098, 98 | 3336622647361835228, 99 | 9678412372263018368, 100 | 11111587619974030187, 101 | 7882215801036322410, 102 | 5709234165213761869, 103 | 7799681907651786826, 104 | 4616320717312661886, 105 | 4251077652075509767, 106 | 7836757050122171900, 107 | 5054003328188417616, 108 | 12919285918354108358, 109 | 16477564761813870717, 110 | 5124667218451240549, 111 | 18099554314556827626, 112 | 7603784838804469118, 113 | 6358551455431362471, 114 | 3037176434532249502, 115 | 3217550417701719149, 116 | 9958699920490216947, 117 | 5965803675992506258, 118 | 12000828378049868312, 119 | 12720568162811471118, 120 | 245696019213873792, 121 | 8351371993958923852, 122 | 14378754021282935786, 123 | 5655432093647472106, 124 | 5508031680350692005, 125 | 8515198786865082103, 126 | 6287793597487164412, 127 | 14963046237722101617, 128 | 3630795823534910476, 129 | 8422285279403485710, 130 | 10554287778700714153, 131 | 10871906555720704584, 132 | 8659066966120258468, 133 | 9420238805069527062, 134 | 10338115333623340156, 135 | 13514802760105037173, 136 | 14635952304031724449, 137 | 15419692541594102413, 138 | ]; 139 | for &e in expected.iter() { 140 | assert_eq!(rng.next_u64(), e); 141 | } 142 | } 143 | 144 | #[test] 145 | fn next_u32() { 146 | let mut rng = SplitMix64::seed_from_u64(10); 147 | // These values were produced with the reference implementation: 148 | // http://dsiutils.di.unimi.it/dsiutils-2.5.1-src.tar.gz 149 | let expected: [u32; 100] = [ 150 | 3930361779, 4016923089, 4113052479, 925926767, 1755287528, 802865554, 954171070, 151 | 3724185978, 173676273, 1414488795, 12664133, 1784889697, 1303817078, 261610523, 152 | 941280008, 2571813643, 2954453492, 378291111, 2546873158, 3923319175, 645257028, 153 | 3881821278, 2681538690, 3037029984, 1999958137, 1853970361, 2989951788, 2126166628, 154 | 839962987, 3989679659, 3656977858, 684284364, 1673258011, 170979192, 3037622326, 155 | 1600748179, 1780764218, 1141430714, 4139736875, 3336905707, 2262051600, 3830850262, 156 | 2430765325, 1073032139, 1668888979, 2716938970, 4102420032, 40305196, 386350562, 157 | 2754480591, 622869439, 2129598760, 2306038241, 4218338739, 412298926, 3453855056, 158 | 3061469690, 4284292697, 994843708, 1591016681, 414726151, 1238182607, 18073498, 159 | 1237631493, 351884714, 2347486264, 2488990876, 802846256, 645670443, 957607012, 160 | 3126589776, 1966356370, 3036485766, 868696717, 2808613630, 2070968151, 1025536863, 161 | 1743949425, 466212687, 2994327271, 209776458, 1246125124, 3344380309, 2203947859, 162 | 968313105, 2805485302, 197484837, 3472483632, 3931823935, 3288490351, 4165666529, 163 | 3671080416, 689542830, 1272555356, 1039141475, 3984640460, 4142959054, 2252788890, 164 | 2459379590, 991872507, 165 | ]; 166 | for &e in expected.iter() { 167 | assert_eq!(rng.next_u32(), e); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoroshiro128plus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoroshiro128+ random number generator. 16 | /// 17 | /// The xoroshiro128+ algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has good statistical properties, besides a low linear 19 | /// complexity in the lowest bits. 20 | /// 21 | /// The algorithm used here is translated from [the `xoroshiro128plus.c` 22 | /// reference source code](http://xoshiro.di.unimi.it/xoroshiro128plus.c) by 23 | /// David Blackman and Sebastiano Vigna. 24 | #[allow(missing_copy_implementations)] 25 | #[derive(Debug, Clone, PartialEq, Eq)] 26 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 27 | pub struct Xoroshiro128Plus { 28 | s0: u64, 29 | s1: u64, 30 | } 31 | 32 | impl Xoroshiro128Plus { 33 | /// Jump forward, equivalently to 2^64 calls to `next_u64()`. 34 | /// 35 | /// This can be used to generate 2^64 non-overlapping subsequences for 36 | /// parallel computations. 37 | /// 38 | /// ``` 39 | /// use rand_xoshiro::rand_core::SeedableRng; 40 | /// use rand_xoshiro::Xoroshiro128Plus; 41 | /// 42 | /// let rng1 = Xoroshiro128Plus::seed_from_u64(0); 43 | /// let mut rng2 = rng1.clone(); 44 | /// rng2.jump(); 45 | /// let mut rng3 = rng2.clone(); 46 | /// rng3.jump(); 47 | /// ``` 48 | pub fn jump(&mut self) { 49 | impl_jump!(u64, self, [0xdf900294d8f554a5, 0x170865df4b3201fc]); 50 | } 51 | 52 | /// Jump forward, equivalently to 2^96 calls to `next_u64()`. 53 | /// 54 | /// This can be used to generate 2^32 starting points, from each of which 55 | /// `jump()` will generate 2^32 non-overlapping subsequences for parallel 56 | /// distributed computations. 57 | pub fn long_jump(&mut self) { 58 | impl_jump!(u64, self, [0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1]); 59 | } 60 | } 61 | 62 | impl RngCore for Xoroshiro128Plus { 63 | #[inline] 64 | fn next_u32(&mut self) -> u32 { 65 | // The two lowest bits have some linear dependencies, so we use the 66 | // upper bits instead. 67 | (self.next_u64() >> 32) as u32 68 | } 69 | 70 | #[inline] 71 | fn next_u64(&mut self) -> u64 { 72 | let r = self.s0.wrapping_add(self.s1); 73 | impl_xoroshiro_u64!(self); 74 | r 75 | } 76 | 77 | #[inline] 78 | fn fill_bytes(&mut self, dest: &mut [u8]) { 79 | fill_bytes_via_next(self, dest); 80 | } 81 | } 82 | impl SeedableRng for Xoroshiro128Plus { 83 | type Seed = [u8; 16]; 84 | 85 | /// Create a new `Xoroshiro128Plus`. If `seed` is entirely 0, it will be 86 | /// mapped to a different seed. 87 | fn from_seed(seed: [u8; 16]) -> Xoroshiro128Plus { 88 | deal_with_zero_seed!(seed, Self, 16); 89 | let mut s = [0; 2]; 90 | read_u64_into(&seed, &mut s); 91 | 92 | Xoroshiro128Plus { s0: s[0], s1: s[1] } 93 | } 94 | 95 | /// Seed a `Xoroshiro128Plus` from a `u64` using `SplitMix64`. 96 | fn seed_from_u64(seed: u64) -> Xoroshiro128Plus { 97 | from_splitmix!(seed) 98 | } 99 | } 100 | 101 | #[cfg(test)] 102 | mod tests { 103 | use super::*; 104 | 105 | #[test] 106 | fn reference() { 107 | let mut rng = Xoroshiro128Plus::from_seed([1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]); 108 | // These values were produced with the reference implementation: 109 | // http://xoshiro.di.unimi.it/xoshiro128starstar.c 110 | let expected = [ 111 | 3, 112 | 412333834243, 113 | 2360170716294286339, 114 | 9295852285959843169, 115 | 2797080929874688578, 116 | 6019711933173041966, 117 | 3076529664176959358, 118 | 3521761819100106140, 119 | 7493067640054542992, 120 | 920801338098114767, 121 | ]; 122 | for &e in &expected { 123 | assert_eq!(rng.next_u64(), e); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoroshiro128plusplus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoroshiro128++ random number generator. 16 | /// 17 | /// The xoroshiro128++ algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoroshiro128plusplus.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoroshiro128plusplus.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[allow(missing_copy_implementations)] 24 | #[derive(Debug, Clone, PartialEq, Eq)] 25 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 26 | pub struct Xoroshiro128PlusPlus { 27 | s0: u64, 28 | s1: u64, 29 | } 30 | 31 | impl Xoroshiro128PlusPlus { 32 | /// Jump forward, equivalently to 2^64 calls to `next_u64()`. 33 | /// 34 | /// This can be used to generate 2^64 non-overlapping subsequences for 35 | /// parallel computations. 36 | /// 37 | /// ``` 38 | /// use rand_xoshiro::rand_core::SeedableRng; 39 | /// use rand_xoshiro::Xoroshiro128PlusPlus; 40 | /// 41 | /// let rng1 = Xoroshiro128PlusPlus::seed_from_u64(0); 42 | /// let mut rng2 = rng1.clone(); 43 | /// rng2.jump(); 44 | /// let mut rng3 = rng2.clone(); 45 | /// rng3.jump(); 46 | /// ``` 47 | pub fn jump(&mut self) { 48 | impl_jump!(u64, self, [0x2bd7a6a6e99c2ddc, 0x0992ccaf6a6fca05]); 49 | } 50 | 51 | /// Jump forward, equivalently to 2^96 calls to `next_u64()`. 52 | /// 53 | /// This can be used to generate 2^32 starting points, from each of which 54 | /// `jump()` will generate 2^32 non-overlapping subsequences for parallel 55 | /// distributed computations. 56 | pub fn long_jump(&mut self) { 57 | impl_jump!(u64, self, [0x360fd5f2cf8d5d99, 0x9c6e6877736c46e3]); 58 | } 59 | } 60 | 61 | impl RngCore for Xoroshiro128PlusPlus { 62 | #[inline] 63 | fn next_u32(&mut self) -> u32 { 64 | self.next_u64() as u32 65 | } 66 | 67 | #[inline] 68 | fn next_u64(&mut self) -> u64 { 69 | let r = plusplus_u64!(self.s0, self.s1, 17); 70 | impl_xoroshiro_u64_plusplus!(self); 71 | r 72 | } 73 | 74 | #[inline] 75 | fn fill_bytes(&mut self, dest: &mut [u8]) { 76 | fill_bytes_via_next(self, dest); 77 | } 78 | } 79 | 80 | impl SeedableRng for Xoroshiro128PlusPlus { 81 | type Seed = [u8; 16]; 82 | 83 | /// Create a new `Xoroshiro128PlusPlus`. If `seed` is entirely 0, it will be 84 | /// mapped to a different seed. 85 | fn from_seed(seed: [u8; 16]) -> Xoroshiro128PlusPlus { 86 | deal_with_zero_seed!(seed, Self, 16); 87 | let mut s = [0; 2]; 88 | read_u64_into(&seed, &mut s); 89 | 90 | Xoroshiro128PlusPlus { s0: s[0], s1: s[1] } 91 | } 92 | 93 | /// Seed a `Xoroshiro128PlusPlus` from a `u64` using `SplitMix64`. 94 | fn seed_from_u64(seed: u64) -> Xoroshiro128PlusPlus { 95 | from_splitmix!(seed) 96 | } 97 | } 98 | 99 | #[cfg(test)] 100 | mod tests { 101 | use super::*; 102 | 103 | #[test] 104 | fn reference() { 105 | let mut rng = 106 | Xoroshiro128PlusPlus::from_seed([1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]); 107 | // These values were produced with the reference implementation: 108 | // http://xoshiro.di.unimi.it/xoshiro128plusplus.c 109 | let expected = [ 110 | 393217, 111 | 669327710093319, 112 | 1732421326133921491, 113 | 11394790081659126983, 114 | 9555452776773192676, 115 | 3586421180005889563, 116 | 1691397964866707553, 117 | 10735626796753111697, 118 | 15216282715349408991, 119 | 14247243556711267923, 120 | ]; 121 | for &e in &expected { 122 | assert_eq!(rng.next_u64(), e); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoroshiro128starstar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoroshiro128** random number generator. 16 | /// 17 | /// The xoroshiro128** algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoroshiro128starstar.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoroshiro128starstar.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[allow(missing_copy_implementations)] 24 | #[derive(Debug, Clone, PartialEq, Eq)] 25 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 26 | pub struct Xoroshiro128StarStar { 27 | s0: u64, 28 | s1: u64, 29 | } 30 | 31 | impl Xoroshiro128StarStar { 32 | /// Jump forward, equivalently to 2^64 calls to `next_u64()`. 33 | /// 34 | /// This can be used to generate 2^64 non-overlapping subsequences for 35 | /// parallel computations. 36 | /// 37 | /// ``` 38 | /// use rand_xoshiro::rand_core::SeedableRng; 39 | /// use rand_xoshiro::Xoroshiro128StarStar; 40 | /// 41 | /// let rng1 = Xoroshiro128StarStar::seed_from_u64(0); 42 | /// let mut rng2 = rng1.clone(); 43 | /// rng2.jump(); 44 | /// let mut rng3 = rng2.clone(); 45 | /// rng3.jump(); 46 | /// ``` 47 | pub fn jump(&mut self) { 48 | impl_jump!(u64, self, [0xdf900294d8f554a5, 0x170865df4b3201fc]); 49 | } 50 | 51 | /// Jump forward, equivalently to 2^96 calls to `next_u64()`. 52 | /// 53 | /// This can be used to generate 2^32 starting points, from each of which 54 | /// `jump()` will generate 2^32 non-overlapping subsequences for parallel 55 | /// distributed computations. 56 | pub fn long_jump(&mut self) { 57 | impl_jump!(u64, self, [0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1]); 58 | } 59 | } 60 | 61 | impl RngCore for Xoroshiro128StarStar { 62 | #[inline] 63 | fn next_u32(&mut self) -> u32 { 64 | self.next_u64() as u32 65 | } 66 | 67 | #[inline] 68 | fn next_u64(&mut self) -> u64 { 69 | let r = starstar_u64!(self.s0); 70 | impl_xoroshiro_u64!(self); 71 | r 72 | } 73 | 74 | #[inline] 75 | fn fill_bytes(&mut self, dest: &mut [u8]) { 76 | fill_bytes_via_next(self, dest); 77 | } 78 | } 79 | 80 | impl SeedableRng for Xoroshiro128StarStar { 81 | type Seed = [u8; 16]; 82 | 83 | /// Create a new `Xoroshiro128StarStar`. If `seed` is entirely 0, it will be 84 | /// mapped to a different seed. 85 | fn from_seed(seed: [u8; 16]) -> Xoroshiro128StarStar { 86 | deal_with_zero_seed!(seed, Self, 16); 87 | let mut s = [0; 2]; 88 | read_u64_into(&seed, &mut s); 89 | 90 | Xoroshiro128StarStar { s0: s[0], s1: s[1] } 91 | } 92 | 93 | /// Seed a `Xoroshiro128StarStar` from a `u64` using `SplitMix64`. 94 | fn seed_from_u64(seed: u64) -> Xoroshiro128StarStar { 95 | from_splitmix!(seed) 96 | } 97 | } 98 | 99 | #[cfg(test)] 100 | mod tests { 101 | use super::*; 102 | 103 | #[test] 104 | fn reference() { 105 | let mut rng = 106 | Xoroshiro128StarStar::from_seed([1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]); 107 | // These values were produced with the reference implementation: 108 | // http://xoshiro.di.unimi.it/xoshiro128starstar.c 109 | let expected = [ 110 | 5760, 111 | 97769243520, 112 | 9706862127477703552, 113 | 9223447511460779954, 114 | 8358291023205304566, 115 | 15695619998649302768, 116 | 8517900938696309774, 117 | 16586480348202605369, 118 | 6959129367028440372, 119 | 16822147227405758281, 120 | ]; 121 | for &e in &expected { 122 | assert_eq!(rng.next_u64(), e); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoroshiro64star.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::{fill_bytes_via_next, next_u64_via_u32}; 10 | use rand_core::le::read_u32_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoroshiro64* random number generator. 16 | /// 17 | /// The xoroshiro64* algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has good statistical properties, besides a low linear 19 | /// complexity in the lowest bits. 20 | /// 21 | /// The algorithm used here is translated from [the `xoroshiro64star.c` 22 | /// reference source code](http://xoshiro.di.unimi.it/xoroshiro64star.c) by 23 | /// David Blackman and Sebastiano Vigna. 24 | #[allow(missing_copy_implementations)] 25 | #[derive(Debug, Clone, PartialEq, Eq)] 26 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 27 | pub struct Xoroshiro64Star { 28 | s0: u32, 29 | s1: u32, 30 | } 31 | 32 | impl RngCore for Xoroshiro64Star { 33 | #[inline] 34 | fn next_u32(&mut self) -> u32 { 35 | let r = self.s0.wrapping_mul(0x9E3779BB); 36 | impl_xoroshiro_u32!(self); 37 | r 38 | } 39 | 40 | #[inline] 41 | fn next_u64(&mut self) -> u64 { 42 | next_u64_via_u32(self) 43 | } 44 | 45 | #[inline] 46 | fn fill_bytes(&mut self, dest: &mut [u8]) { 47 | fill_bytes_via_next(self, dest); 48 | } 49 | } 50 | 51 | impl SeedableRng for Xoroshiro64Star { 52 | type Seed = [u8; 8]; 53 | 54 | /// Create a new `Xoroshiro64Star`. If `seed` is entirely 0, it will be 55 | /// mapped to a different seed. 56 | fn from_seed(seed: [u8; 8]) -> Xoroshiro64Star { 57 | deal_with_zero_seed!(seed, Self, 8); 58 | let mut s = [0; 2]; 59 | read_u32_into(&seed, &mut s); 60 | 61 | Xoroshiro64Star { s0: s[0], s1: s[1] } 62 | } 63 | 64 | /// Seed a `Xoroshiro64Star` from a `u64` using `SplitMix64`. 65 | fn seed_from_u64(seed: u64) -> Xoroshiro64Star { 66 | from_splitmix!(seed) 67 | } 68 | } 69 | 70 | #[cfg(test)] 71 | mod tests { 72 | use super::*; 73 | 74 | #[test] 75 | fn reference() { 76 | let mut rng = Xoroshiro64Star::from_seed([1, 0, 0, 0, 2, 0, 0, 0]); 77 | // These values were produced with the reference implementation: 78 | // http://xoshiro.di.unimi.it/xoshiro64star.c 79 | let expected = [ 80 | 2654435771, 327208753, 4063491769, 4259754937, 261922412, 168123673, 552743735, 81 | 1672597395, 1031040050, 2755315674, 82 | ]; 83 | for &e in &expected { 84 | assert_eq!(rng.next_u32(), e); 85 | } 86 | } 87 | 88 | #[test] 89 | fn zero_seed() { 90 | let mut rng = Xoroshiro64Star::seed_from_u64(0); 91 | assert_ne!(rng.next_u64(), 0); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoroshiro64starstar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::{fill_bytes_via_next, next_u64_via_u32}; 10 | use rand_core::le::read_u32_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoroshiro64** random number generator. 16 | /// 17 | /// The xoshiro64** algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoroshiro64starstar.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoroshiro64starstar.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[allow(missing_copy_implementations)] 24 | #[derive(Debug, Clone, PartialEq, Eq)] 25 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 26 | pub struct Xoroshiro64StarStar { 27 | s0: u32, 28 | s1: u32, 29 | } 30 | 31 | impl RngCore for Xoroshiro64StarStar { 32 | #[inline] 33 | fn next_u32(&mut self) -> u32 { 34 | let r = starstar_u32!(self.s0); 35 | impl_xoroshiro_u32!(self); 36 | r 37 | } 38 | 39 | #[inline] 40 | fn next_u64(&mut self) -> u64 { 41 | next_u64_via_u32(self) 42 | } 43 | 44 | #[inline] 45 | fn fill_bytes(&mut self, dest: &mut [u8]) { 46 | fill_bytes_via_next(self, dest); 47 | } 48 | } 49 | 50 | impl SeedableRng for Xoroshiro64StarStar { 51 | type Seed = [u8; 8]; 52 | 53 | /// Create a new `Xoroshiro64StarStar`. If `seed` is entirely 0, it will be 54 | /// mapped to a different seed. 55 | fn from_seed(seed: [u8; 8]) -> Xoroshiro64StarStar { 56 | deal_with_zero_seed!(seed, Self, 8); 57 | let mut s = [0; 2]; 58 | read_u32_into(&seed, &mut s); 59 | 60 | Xoroshiro64StarStar { s0: s[0], s1: s[1] } 61 | } 62 | 63 | /// Seed a `Xoroshiro64StarStar` from a `u64` using `SplitMix64`. 64 | fn seed_from_u64(seed: u64) -> Xoroshiro64StarStar { 65 | from_splitmix!(seed) 66 | } 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use super::*; 72 | 73 | #[test] 74 | fn reference() { 75 | let mut rng = Xoroshiro64StarStar::from_seed([1, 0, 0, 0, 2, 0, 0, 0]); 76 | // These values were produced with the reference implementation: 77 | // http://xoshiro.di.unimi.it/xoshiro64starstar.c 78 | let expected = [ 79 | 3802928447, 813792938, 1618621494, 2955957307, 3252880261, 1129983909, 2539651700, 80 | 1327610908, 1757650787, 2763843748, 81 | ]; 82 | for &e in &expected { 83 | assert_eq!(rng.next_u32(), e); 84 | } 85 | } 86 | 87 | #[test] 88 | fn zero_seed() { 89 | let mut rng = Xoroshiro64StarStar::seed_from_u64(0); 90 | assert_ne!(rng.next_u64(), 0); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro128plus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::{fill_bytes_via_next, next_u64_via_u32}; 10 | use rand_core::le::read_u32_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoshiro128+ random number generator. 16 | /// 17 | /// The xoshiro128+ algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has good statistical properties, besides a low linear 19 | /// complexity in the lowest bits. 20 | /// 21 | /// The algorithm used here is translated from [the `xoshiro128starstar.c` 22 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro128starstar.c) by 23 | /// David Blackman and Sebastiano Vigna. 24 | #[derive(Debug, Clone, PartialEq, Eq)] 25 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 26 | pub struct Xoshiro128Plus { 27 | s: [u32; 4], 28 | } 29 | 30 | impl Xoshiro128Plus { 31 | /// Jump forward, equivalently to 2^64 calls to `next_u32()`. 32 | /// 33 | /// This can be used to generate 2^64 non-overlapping subsequences for 34 | /// parallel computations. 35 | /// 36 | /// ``` 37 | /// use rand_xoshiro::rand_core::SeedableRng; 38 | /// use rand_xoshiro::Xoroshiro128StarStar; 39 | /// 40 | /// let rng1 = Xoroshiro128StarStar::seed_from_u64(0); 41 | /// let mut rng2 = rng1.clone(); 42 | /// rng2.jump(); 43 | /// let mut rng3 = rng2.clone(); 44 | /// rng3.jump(); 45 | /// ``` 46 | pub fn jump(&mut self) { 47 | impl_jump!(u32, self, [0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b]); 48 | } 49 | 50 | /// Jump forward, equivalently to 2^96 calls to `next_u32()`. 51 | /// 52 | /// This can be used to generate 2^32 starting points, from each of which 53 | /// `jump()` will generate 2^32 non-overlapping subsequences for parallel 54 | /// distributed computations. 55 | pub fn long_jump(&mut self) { 56 | impl_jump!(u32, self, [0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662]); 57 | } 58 | } 59 | 60 | impl SeedableRng for Xoshiro128Plus { 61 | type Seed = [u8; 16]; 62 | 63 | /// Create a new `Xoshiro128Plus`. If `seed` is entirely 0, it will be 64 | /// mapped to a different seed. 65 | #[inline] 66 | fn from_seed(seed: [u8; 16]) -> Xoshiro128Plus { 67 | deal_with_zero_seed!(seed, Self, 16); 68 | let mut state = [0; 4]; 69 | read_u32_into(&seed, &mut state); 70 | Xoshiro128Plus { s: state } 71 | } 72 | 73 | /// Seed a `Xoshiro128Plus` from a `u64` using `SplitMix64`. 74 | fn seed_from_u64(seed: u64) -> Xoshiro128Plus { 75 | from_splitmix!(seed) 76 | } 77 | } 78 | 79 | impl RngCore for Xoshiro128Plus { 80 | #[inline] 81 | fn next_u32(&mut self) -> u32 { 82 | let result_plus = self.s[0].wrapping_add(self.s[3]); 83 | impl_xoshiro_u32!(self); 84 | result_plus 85 | } 86 | 87 | #[inline] 88 | fn next_u64(&mut self) -> u64 { 89 | next_u64_via_u32(self) 90 | } 91 | 92 | #[inline] 93 | fn fill_bytes(&mut self, dest: &mut [u8]) { 94 | fill_bytes_via_next(self, dest); 95 | } 96 | } 97 | 98 | #[cfg(test)] 99 | mod tests { 100 | use super::*; 101 | 102 | #[test] 103 | fn reference() { 104 | let mut rng = Xoshiro128Plus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 105 | // These values were produced with the reference implementation: 106 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 107 | let expected = [ 108 | 5, 12295, 25178119, 27286542, 39879690, 1140358681, 3276312097, 4110231701, 399823256, 109 | 2144435200, 110 | ]; 111 | for &e in &expected { 112 | assert_eq!(rng.next_u32(), e); 113 | } 114 | } 115 | 116 | #[test] 117 | fn test_jump() { 118 | let mut rng = Xoshiro128Plus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 119 | rng.jump(); 120 | // These values were produced by instrumenting the reference implementation: 121 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 122 | assert_eq!(rng.s[0], 2843103750); 123 | assert_eq!(rng.s[1], 2038079848); 124 | assert_eq!(rng.s[2], 1533207345); 125 | assert_eq!(rng.s[3], 44816753); 126 | } 127 | 128 | #[test] 129 | fn test_long_jump() { 130 | let mut rng = Xoshiro128Plus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 131 | rng.long_jump(); 132 | // These values were produced by instrumenting the reference implementation: 133 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 134 | assert_eq!(rng.s[0], 1611968294); 135 | assert_eq!(rng.s[1], 2125834322); 136 | assert_eq!(rng.s[2], 966769569); 137 | assert_eq!(rng.s[3], 3193880526); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro128plusplus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::{fill_bytes_via_next, next_u64_via_u32}; 10 | use rand_core::le::read_u32_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoshiro128++ random number generator. 16 | /// 17 | /// The xoshiro128++ algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoshiro128plusplus.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro128plusplus.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[derive(Debug, Clone, PartialEq, Eq)] 24 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 25 | pub struct Xoshiro128PlusPlus { 26 | s: [u32; 4], 27 | } 28 | 29 | impl Xoshiro128PlusPlus { 30 | /// Jump forward, equivalently to 2^64 calls to `next_u32()`. 31 | /// 32 | /// This can be used to generate 2^64 non-overlapping subsequences for 33 | /// parallel computations. 34 | /// 35 | /// ``` 36 | /// use rand_xoshiro::rand_core::SeedableRng; 37 | /// use rand_xoshiro::Xoroshiro128PlusPlus; 38 | /// 39 | /// let rng1 = Xoroshiro128PlusPlus::seed_from_u64(0); 40 | /// let mut rng2 = rng1.clone(); 41 | /// rng2.jump(); 42 | /// let mut rng3 = rng2.clone(); 43 | /// rng3.jump(); 44 | /// ``` 45 | pub fn jump(&mut self) { 46 | impl_jump!(u32, self, [0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b]); 47 | } 48 | 49 | /// Jump forward, equivalently to 2^96 calls to `next_u32()`. 50 | /// 51 | /// This can be used to generate 2^32 starting points, from each of which 52 | /// `jump()` will generate 2^32 non-overlapping subsequences for parallel 53 | /// distributed computations. 54 | pub fn long_jump(&mut self) { 55 | impl_jump!(u32, self, [0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662]); 56 | } 57 | } 58 | 59 | impl SeedableRng for Xoshiro128PlusPlus { 60 | type Seed = [u8; 16]; 61 | 62 | /// Create a new `Xoshiro128PlusPlus`. If `seed` is entirely 0, it will be 63 | /// mapped to a different seed. 64 | #[inline] 65 | fn from_seed(seed: [u8; 16]) -> Xoshiro128PlusPlus { 66 | deal_with_zero_seed!(seed, Self, 16); 67 | let mut state = [0; 4]; 68 | read_u32_into(&seed, &mut state); 69 | Xoshiro128PlusPlus { s: state } 70 | } 71 | 72 | /// Seed a `Xoshiro128PlusPlus` from a `u64` using `SplitMix64`. 73 | fn seed_from_u64(seed: u64) -> Xoshiro128PlusPlus { 74 | from_splitmix!(seed) 75 | } 76 | } 77 | 78 | impl RngCore for Xoshiro128PlusPlus { 79 | #[inline] 80 | fn next_u32(&mut self) -> u32 { 81 | let result_starstar = plusplus_u32!(self.s[0], self.s[3]); 82 | impl_xoshiro_u32!(self); 83 | result_starstar 84 | } 85 | 86 | #[inline] 87 | fn next_u64(&mut self) -> u64 { 88 | next_u64_via_u32(self) 89 | } 90 | 91 | #[inline] 92 | fn fill_bytes(&mut self, dest: &mut [u8]) { 93 | fill_bytes_via_next(self, dest); 94 | } 95 | } 96 | 97 | #[cfg(test)] 98 | mod tests { 99 | use super::*; 100 | 101 | #[test] 102 | fn reference() { 103 | let mut rng = 104 | Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 105 | // These values were produced with the reference implementation: 106 | // http://xoshiro.di.unimi.it/xoshiro128plusplus.c 107 | let expected = [ 108 | 641, 1573767, 3222811527, 3517856514, 836907274, 4247214768, 3867114732, 1355841295, 109 | 495546011, 621204420, 110 | ]; 111 | for &e in &expected { 112 | assert_eq!(rng.next_u32(), e); 113 | } 114 | } 115 | 116 | #[test] 117 | fn test_jump() { 118 | let mut rng = 119 | Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 120 | rng.jump(); 121 | // These values were produced by instrumenting the reference implementation: 122 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 123 | assert_eq!(rng.s[0], 2843103750); 124 | assert_eq!(rng.s[1], 2038079848); 125 | assert_eq!(rng.s[2], 1533207345); 126 | assert_eq!(rng.s[3], 44816753); 127 | } 128 | 129 | #[test] 130 | fn test_long_jump() { 131 | let mut rng = 132 | Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 133 | rng.long_jump(); 134 | // These values were produced by instrumenting the reference implementation: 135 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 136 | assert_eq!(rng.s[0], 1611968294); 137 | assert_eq!(rng.s[1], 2125834322); 138 | assert_eq!(rng.s[2], 966769569); 139 | assert_eq!(rng.s[3], 3193880526); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro128starstar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::{fill_bytes_via_next, next_u64_via_u32}; 10 | use rand_core::le::read_u32_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoshiro128** random number generator. 16 | /// 17 | /// The xoshiro128** algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoshiro128starstar.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro128starstar.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[derive(Debug, Clone, PartialEq, Eq)] 24 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 25 | pub struct Xoshiro128StarStar { 26 | s: [u32; 4], 27 | } 28 | 29 | impl Xoshiro128StarStar { 30 | /// Jump forward, equivalently to 2^64 calls to `next_u32()`. 31 | /// 32 | /// This can be used to generate 2^64 non-overlapping subsequences for 33 | /// parallel computations. 34 | /// 35 | /// ``` 36 | /// use rand_xoshiro::rand_core::SeedableRng; 37 | /// use rand_xoshiro::Xoroshiro128StarStar; 38 | /// 39 | /// let rng1 = Xoroshiro128StarStar::seed_from_u64(0); 40 | /// let mut rng2 = rng1.clone(); 41 | /// rng2.jump(); 42 | /// let mut rng3 = rng2.clone(); 43 | /// rng3.jump(); 44 | /// ``` 45 | pub fn jump(&mut self) { 46 | impl_jump!(u32, self, [0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b]); 47 | } 48 | 49 | /// Jump forward, equivalently to 2^96 calls to `next_u32()`. 50 | /// 51 | /// This can be used to generate 2^32 starting points, from each of which 52 | /// `jump()` will generate 2^32 non-overlapping subsequences for parallel 53 | /// distributed computations. 54 | pub fn long_jump(&mut self) { 55 | impl_jump!(u32, self, [0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662]); 56 | } 57 | } 58 | 59 | impl SeedableRng for Xoshiro128StarStar { 60 | type Seed = [u8; 16]; 61 | 62 | /// Create a new `Xoshiro128StarStar`. If `seed` is entirely 0, it will be 63 | /// mapped to a different seed. 64 | #[inline] 65 | fn from_seed(seed: [u8; 16]) -> Xoshiro128StarStar { 66 | deal_with_zero_seed!(seed, Self, 16); 67 | let mut state = [0; 4]; 68 | read_u32_into(&seed, &mut state); 69 | Xoshiro128StarStar { s: state } 70 | } 71 | 72 | /// Seed a `Xoshiro128StarStar` from a `u64` using `SplitMix64`. 73 | fn seed_from_u64(seed: u64) -> Xoshiro128StarStar { 74 | from_splitmix!(seed) 75 | } 76 | } 77 | 78 | impl RngCore for Xoshiro128StarStar { 79 | #[inline] 80 | fn next_u32(&mut self) -> u32 { 81 | let result_starstar = starstar_u64!(self.s[1]); 82 | impl_xoshiro_u32!(self); 83 | result_starstar 84 | } 85 | 86 | #[inline] 87 | fn next_u64(&mut self) -> u64 { 88 | next_u64_via_u32(self) 89 | } 90 | 91 | #[inline] 92 | fn fill_bytes(&mut self, dest: &mut [u8]) { 93 | fill_bytes_via_next(self, dest); 94 | } 95 | } 96 | 97 | #[cfg(test)] 98 | mod tests { 99 | use super::*; 100 | 101 | #[test] 102 | fn reference() { 103 | let mut rng = 104 | Xoshiro128StarStar::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 105 | // These values were produced with the reference implementation (v1.1): 106 | // http://xoshiro.di.unimi.it/xoshiro128starstar.c 107 | let expected = [ 108 | 11520, 0, 5927040, 70819200, 2031721883, 1637235492, 1287239034, 3734860849, 109 | 3729100597, 4258142804, 110 | ]; 111 | for &e in &expected { 112 | assert_eq!(rng.next_u32(), e); 113 | } 114 | } 115 | 116 | #[test] 117 | fn test_jump() { 118 | let mut rng = 119 | Xoshiro128StarStar::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 120 | rng.jump(); 121 | // These values were produced by instrumenting the reference implementation: 122 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 123 | assert_eq!(rng.s[0], 2843103750); 124 | assert_eq!(rng.s[1], 2038079848); 125 | assert_eq!(rng.s[2], 1533207345); 126 | assert_eq!(rng.s[3], 44816753); 127 | } 128 | 129 | #[test] 130 | fn test_long_jump() { 131 | let mut rng = 132 | Xoshiro128StarStar::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); 133 | rng.long_jump(); 134 | // These values were produced by instrumenting the reference implementation: 135 | // http://xoshiro.di.unimi.it/xoshiro128plus.c 136 | assert_eq!(rng.s[0], 1611968294); 137 | assert_eq!(rng.s[1], 2125834322); 138 | assert_eq!(rng.s[2], 966769569); 139 | assert_eq!(rng.s[3], 3193880526); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro256plus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoshiro256+ random number generator. 16 | /// 17 | /// The xoshiro256+ algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has good statistical properties, besides a low linear 19 | /// complexity in the lowest bits. 20 | /// 21 | /// The algorithm used here is translated from [the `xoshiro256plus.c` 22 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro256plus.c) by 23 | /// David Blackman and Sebastiano Vigna. 24 | #[derive(Debug, Clone, PartialEq, Eq)] 25 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 26 | pub struct Xoshiro256Plus { 27 | s: [u64; 4], 28 | } 29 | 30 | impl Xoshiro256Plus { 31 | /// Jump forward, equivalently to 2^128 calls to `next_u64()`. 32 | /// 33 | /// This can be used to generate 2^128 non-overlapping subsequences for 34 | /// parallel computations. 35 | /// 36 | /// ``` 37 | /// use rand_xoshiro::rand_core::SeedableRng; 38 | /// use rand_xoshiro::Xoshiro256Plus; 39 | /// 40 | /// let rng1 = Xoshiro256Plus::seed_from_u64(0); 41 | /// let mut rng2 = rng1.clone(); 42 | /// rng2.jump(); 43 | /// let mut rng3 = rng2.clone(); 44 | /// rng3.jump(); 45 | /// ``` 46 | pub fn jump(&mut self) { 47 | impl_jump!( 48 | u64, 49 | self, 50 | [ 51 | 0x180ec6d33cfd0aba, 52 | 0xd5a61266f0c9392c, 53 | 0xa9582618e03fc9aa, 54 | 0x39abdc4529b1661c 55 | ] 56 | ); 57 | } 58 | 59 | /// Jump forward, equivalently to 2^192 calls to `next_u64()`. 60 | /// 61 | /// This can be used to generate 2^64 starting points, from each of which 62 | /// `jump()` will generate 2^64 non-overlapping subsequences for parallel 63 | /// distributed computations. 64 | pub fn long_jump(&mut self) { 65 | impl_jump!( 66 | u64, 67 | self, 68 | [ 69 | 0x76e15d3efefdcbbf, 70 | 0xc5004e441c522fb3, 71 | 0x77710069854ee241, 72 | 0x39109bb02acbe635 73 | ] 74 | ); 75 | } 76 | } 77 | 78 | impl SeedableRng for Xoshiro256Plus { 79 | type Seed = [u8; 32]; 80 | 81 | /// Create a new `Xoshiro256Plus`. If `seed` is entirely 0, it will be 82 | /// mapped to a different seed. 83 | #[inline] 84 | fn from_seed(seed: [u8; 32]) -> Xoshiro256Plus { 85 | deal_with_zero_seed!(seed, Self); 86 | let mut state = [0; 4]; 87 | read_u64_into(&seed, &mut state); 88 | Xoshiro256Plus { s: state } 89 | } 90 | 91 | /// Seed a `Xoshiro256Plus` from a `u64` using `SplitMix64`. 92 | fn seed_from_u64(seed: u64) -> Xoshiro256Plus { 93 | from_splitmix!(seed) 94 | } 95 | } 96 | 97 | impl RngCore for Xoshiro256Plus { 98 | #[inline] 99 | fn next_u32(&mut self) -> u32 { 100 | // The lowest bits have some linear dependencies, so we use the 101 | // upper bits instead. 102 | (self.next_u64() >> 32) as u32 103 | } 104 | 105 | #[inline] 106 | fn next_u64(&mut self) -> u64 { 107 | let result_plus = self.s[0].wrapping_add(self.s[3]); 108 | impl_xoshiro_u64!(self); 109 | result_plus 110 | } 111 | 112 | #[inline] 113 | fn fill_bytes(&mut self, dest: &mut [u8]) { 114 | fill_bytes_via_next(self, dest); 115 | } 116 | } 117 | 118 | #[cfg(test)] 119 | mod tests { 120 | use super::*; 121 | 122 | #[test] 123 | fn reference() { 124 | let mut rng = Xoshiro256Plus::from_seed([ 125 | 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 126 | 0, 0, 0, 127 | ]); 128 | // These values were produced with the reference implementation: 129 | // http://xoshiro.di.unimi.it/xoshiro256plus.c 130 | let expected = [ 131 | 5, 132 | 211106232532999, 133 | 211106635186183, 134 | 9223759065350669058, 135 | 9250833439874351877, 136 | 13862484359527728515, 137 | 2346507365006083650, 138 | 1168864526675804870, 139 | 34095955243042024, 140 | 3466914240207415127, 141 | ]; 142 | for &e in &expected { 143 | assert_eq!(rng.next_u64(), e); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro256plusplus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoshiro256++ random number generator. 16 | /// 17 | /// The xoshiro256++ algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoshiro256plusplus.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro256plusplus.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[derive(Debug, Clone, PartialEq, Eq)] 24 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 25 | pub struct Xoshiro256PlusPlus { 26 | s: [u64; 4], 27 | } 28 | 29 | impl Xoshiro256PlusPlus { 30 | /// Jump forward, equivalently to 2^128 calls to `next_u64()`. 31 | /// 32 | /// This can be used to generate 2^128 non-overlapping subsequences for 33 | /// parallel computations. 34 | /// 35 | /// ``` 36 | /// use rand_xoshiro::rand_core::SeedableRng; 37 | /// use rand_xoshiro::Xoshiro256PlusPlus; 38 | /// 39 | /// let rng1 = Xoshiro256PlusPlus::seed_from_u64(0); 40 | /// let mut rng2 = rng1.clone(); 41 | /// rng2.jump(); 42 | /// let mut rng3 = rng2.clone(); 43 | /// rng3.jump(); 44 | /// ``` 45 | pub fn jump(&mut self) { 46 | impl_jump!( 47 | u64, 48 | self, 49 | [ 50 | 0x180ec6d33cfd0aba, 51 | 0xd5a61266f0c9392c, 52 | 0xa9582618e03fc9aa, 53 | 0x39abdc4529b1661c 54 | ] 55 | ); 56 | } 57 | 58 | /// Jump forward, equivalently to 2^192 calls to `next_u64()`. 59 | /// 60 | /// This can be used to generate 2^64 starting points, from each of which 61 | /// `jump()` will generate 2^64 non-overlapping subsequences for parallel 62 | /// distributed computations. 63 | pub fn long_jump(&mut self) { 64 | impl_jump!( 65 | u64, 66 | self, 67 | [ 68 | 0x76e15d3efefdcbbf, 69 | 0xc5004e441c522fb3, 70 | 0x77710069854ee241, 71 | 0x39109bb02acbe635 72 | ] 73 | ); 74 | } 75 | } 76 | 77 | impl SeedableRng for Xoshiro256PlusPlus { 78 | type Seed = [u8; 32]; 79 | 80 | /// Create a new `Xoshiro256PlusPlus`. If `seed` is entirely 0, it will be 81 | /// mapped to a different seed. 82 | #[inline] 83 | fn from_seed(seed: [u8; 32]) -> Xoshiro256PlusPlus { 84 | deal_with_zero_seed!(seed, Self); 85 | let mut state = [0; 4]; 86 | read_u64_into(&seed, &mut state); 87 | Xoshiro256PlusPlus { s: state } 88 | } 89 | 90 | /// Seed a `Xoshiro256PlusPlus` from a `u64` using `SplitMix64`. 91 | fn seed_from_u64(seed: u64) -> Xoshiro256PlusPlus { 92 | from_splitmix!(seed) 93 | } 94 | } 95 | 96 | impl RngCore for Xoshiro256PlusPlus { 97 | #[inline] 98 | fn next_u32(&mut self) -> u32 { 99 | // The lowest bits have some linear dependencies, so we use the 100 | // upper bits instead. 101 | (self.next_u64() >> 32) as u32 102 | } 103 | 104 | #[inline] 105 | fn next_u64(&mut self) -> u64 { 106 | let result_plusplus = plusplus_u64!(self.s[0], self.s[3], 23); 107 | impl_xoshiro_u64!(self); 108 | result_plusplus 109 | } 110 | 111 | #[inline] 112 | fn fill_bytes(&mut self, dest: &mut [u8]) { 113 | fill_bytes_via_next(self, dest); 114 | } 115 | } 116 | 117 | #[cfg(test)] 118 | mod tests { 119 | use super::*; 120 | 121 | #[test] 122 | fn reference() { 123 | let mut rng = Xoshiro256PlusPlus::from_seed([ 124 | 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 125 | 0, 0, 0, 126 | ]); 127 | // These values were produced with the reference implementation: 128 | // http://xoshiro.di.unimi.it/xoshiro256plusplus.c 129 | let expected = [ 130 | 41943041, 131 | 58720359, 132 | 3588806011781223, 133 | 3591011842654386, 134 | 9228616714210784205, 135 | 9973669472204895162, 136 | 14011001112246962877, 137 | 12406186145184390807, 138 | 15849039046786891736, 139 | 10450023813501588000, 140 | ]; 141 | for &e in &expected { 142 | assert_eq!(rng.next_u64(), e); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro256starstar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// A xoshiro256** random number generator. 16 | /// 17 | /// The xoshiro256** algorithm is not suitable for cryptographic purposes, but 18 | /// is very fast and has excellent statistical properties. 19 | /// 20 | /// The algorithm used here is translated from [the `xoshiro256starstar.c` 21 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro256starstar.c) by 22 | /// David Blackman and Sebastiano Vigna. 23 | #[derive(Debug, Clone, PartialEq, Eq)] 24 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 25 | pub struct Xoshiro256StarStar { 26 | s: [u64; 4], 27 | } 28 | 29 | impl Xoshiro256StarStar { 30 | /// Jump forward, equivalently to 2^128 calls to `next_u64()`. 31 | /// 32 | /// This can be used to generate 2^128 non-overlapping subsequences for 33 | /// parallel computations. 34 | /// 35 | /// ``` 36 | /// use rand_xoshiro::rand_core::SeedableRng; 37 | /// use rand_xoshiro::Xoshiro256StarStar; 38 | /// 39 | /// let rng1 = Xoshiro256StarStar::seed_from_u64(0); 40 | /// let mut rng2 = rng1.clone(); 41 | /// rng2.jump(); 42 | /// let mut rng3 = rng2.clone(); 43 | /// rng3.jump(); 44 | /// ``` 45 | pub fn jump(&mut self) { 46 | impl_jump!( 47 | u64, 48 | self, 49 | [ 50 | 0x180ec6d33cfd0aba, 51 | 0xd5a61266f0c9392c, 52 | 0xa9582618e03fc9aa, 53 | 0x39abdc4529b1661c 54 | ] 55 | ); 56 | } 57 | 58 | /// Jump forward, equivalently to 2^192 calls to `next_u64()`. 59 | /// 60 | /// This can be used to generate 2^64 starting points, from each of which 61 | /// `jump()` will generate 2^64 non-overlapping subsequences for parallel 62 | /// distributed computations. 63 | pub fn long_jump(&mut self) { 64 | impl_jump!( 65 | u64, 66 | self, 67 | [ 68 | 0x76e15d3efefdcbbf, 69 | 0xc5004e441c522fb3, 70 | 0x77710069854ee241, 71 | 0x39109bb02acbe635 72 | ] 73 | ); 74 | } 75 | } 76 | 77 | impl SeedableRng for Xoshiro256StarStar { 78 | type Seed = [u8; 32]; 79 | 80 | /// Create a new `Xoshiro256StarStar`. If `seed` is entirely 0, it will be 81 | /// mapped to a different seed. 82 | #[inline] 83 | fn from_seed(seed: [u8; 32]) -> Xoshiro256StarStar { 84 | deal_with_zero_seed!(seed, Self); 85 | let mut state = [0; 4]; 86 | read_u64_into(&seed, &mut state); 87 | Xoshiro256StarStar { s: state } 88 | } 89 | 90 | /// Seed a `Xoshiro256StarStar` from a `u64` using `SplitMix64`. 91 | fn seed_from_u64(seed: u64) -> Xoshiro256StarStar { 92 | from_splitmix!(seed) 93 | } 94 | } 95 | 96 | impl RngCore for Xoshiro256StarStar { 97 | #[inline] 98 | fn next_u32(&mut self) -> u32 { 99 | // The lowest bits have some linear dependencies, so we use the 100 | // upper bits instead. 101 | (self.next_u64() >> 32) as u32 102 | } 103 | 104 | #[inline] 105 | fn next_u64(&mut self) -> u64 { 106 | let result_starstar = starstar_u64!(self.s[1]); 107 | impl_xoshiro_u64!(self); 108 | result_starstar 109 | } 110 | 111 | #[inline] 112 | fn fill_bytes(&mut self, dest: &mut [u8]) { 113 | fill_bytes_via_next(self, dest); 114 | } 115 | } 116 | 117 | #[cfg(test)] 118 | mod tests { 119 | use super::*; 120 | 121 | #[test] 122 | fn reference() { 123 | let mut rng = Xoshiro256StarStar::from_seed([ 124 | 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 125 | 0, 0, 0, 126 | ]); 127 | // These values were produced with the reference implementation: 128 | // http://xoshiro.di.unimi.it/xoshiro128starstar.c 129 | let expected = [ 130 | 11520, 131 | 0, 132 | 1509978240, 133 | 1215971899390074240, 134 | 1216172134540287360, 135 | 607988272756665600, 136 | 16172922978634559625, 137 | 8476171486693032832, 138 | 10595114339597558777, 139 | 2904607092377533576, 140 | ]; 141 | for &e in &expected { 142 | assert_eq!(rng.next_u64(), e); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro512plus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | use crate::Seed512; 16 | 17 | /// A xoshiro512+ random number generator. 18 | /// 19 | /// The xoshiro512+ algorithm is not suitable for cryptographic purposes, but 20 | /// is very fast and has good statistical properties, besides a low linear 21 | /// complexity in the lowest bits. 22 | /// 23 | /// The algorithm used here is translated from [the `xoshiro512plus.c` 24 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro512plus.c) by 25 | /// David Blackman and Sebastiano Vigna. 26 | #[derive(Debug, Clone, PartialEq, Eq)] 27 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 28 | pub struct Xoshiro512Plus { 29 | s: [u64; 8], 30 | } 31 | 32 | impl Xoshiro512Plus { 33 | /// Jump forward, equivalently to 2^256 calls to `next_u64()`. 34 | /// 35 | /// This can be used to generate 2^256 non-overlapping subsequences for 36 | /// parallel computations. 37 | /// 38 | /// ``` 39 | /// use rand_xoshiro::rand_core::SeedableRng; 40 | /// use rand_xoshiro::Xoshiro512Plus; 41 | /// 42 | /// let rng1 = Xoshiro512Plus::seed_from_u64(0); 43 | /// let mut rng2 = rng1.clone(); 44 | /// rng2.jump(); 45 | /// let mut rng3 = rng2.clone(); 46 | /// rng3.jump(); 47 | /// ``` 48 | pub fn jump(&mut self) { 49 | impl_jump!( 50 | u64, 51 | self, 52 | [ 53 | 0x33ed89b6e7a353f9, 54 | 0x760083d7955323be, 55 | 0x2837f2fbb5f22fae, 56 | 0x4b8c5674d309511c, 57 | 0xb11ac47a7ba28c25, 58 | 0xf1be7667092bcc1c, 59 | 0x53851efdb6df0aaf, 60 | 0x1ebbc8b23eaf25db 61 | ] 62 | ); 63 | } 64 | 65 | /// Jump forward, equivalently to 2^384 calls to `next_u64()`. 66 | /// 67 | /// This can be used to generate 2^128 starting points, from each of which 68 | /// `jump()` will generate 2^128 non-overlapping subsequences for parallel 69 | /// distributed computations. 70 | pub fn long_jump(&mut self) { 71 | impl_jump!( 72 | u64, 73 | self, 74 | [ 75 | 0x11467fef8f921d28, 76 | 0xa2a819f2e79c8ea8, 77 | 0xa8299fc284b3959a, 78 | 0xb4d347340ca63ee1, 79 | 0x1cb0940bedbff6ce, 80 | 0xd956c5c4fa1f8e17, 81 | 0x915e38fd4eda93bc, 82 | 0x5b3ccdfa5d7daca5 83 | ] 84 | ); 85 | } 86 | } 87 | 88 | impl SeedableRng for Xoshiro512Plus { 89 | type Seed = Seed512; 90 | 91 | /// Create a new `Xoshiro512Plus`. If `seed` is entirely 0, it will be 92 | /// mapped to a different seed. 93 | #[inline] 94 | fn from_seed(seed: Seed512) -> Xoshiro512Plus { 95 | deal_with_zero_seed!(seed, Self); 96 | let mut state = [0; 8]; 97 | read_u64_into(&seed.0, &mut state); 98 | Xoshiro512Plus { s: state } 99 | } 100 | 101 | /// Seed a `Xoshiro512Plus` from a `u64` using `SplitMix64`. 102 | fn seed_from_u64(seed: u64) -> Xoshiro512Plus { 103 | from_splitmix!(seed) 104 | } 105 | } 106 | 107 | impl RngCore for Xoshiro512Plus { 108 | #[inline] 109 | fn next_u32(&mut self) -> u32 { 110 | // The lowest bits have some linear dependencies, so we use the 111 | // upper bits instead. 112 | (self.next_u64() >> 32) as u32 113 | } 114 | 115 | #[inline] 116 | fn next_u64(&mut self) -> u64 { 117 | let result_plus = self.s[0].wrapping_add(self.s[2]); 118 | impl_xoshiro_large!(self); 119 | result_plus 120 | } 121 | 122 | #[inline] 123 | fn fill_bytes(&mut self, dest: &mut [u8]) { 124 | fill_bytes_via_next(self, dest); 125 | } 126 | } 127 | 128 | #[cfg(test)] 129 | mod tests { 130 | use super::*; 131 | 132 | #[test] 133 | fn reference() { 134 | #[rustfmt::skip] 135 | let mut rng = Xoshiro512Plus::from_seed(Seed512( 136 | [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 137 | 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 138 | 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 139 | 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0])); 140 | // These values were produced with the reference implementation: 141 | // http://xoshiro.di.unimi.it/xoshiro512plus.c 142 | let expected = [ 143 | 4, 144 | 8, 145 | 4113, 146 | 25169936, 147 | 52776585412635, 148 | 57174648719367, 149 | 9223482039571869716, 150 | 9331471677901559830, 151 | 9340533895746033672, 152 | 14078399799840753678, 153 | ]; 154 | for &e in &expected { 155 | assert_eq!(rng.next_u64(), e); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro512plusplus.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | use crate::Seed512; 16 | 17 | /// A xoshiro512++ random number generator. 18 | /// 19 | /// The xoshiro512++ algorithm is not suitable for cryptographic purposes, but 20 | /// is very fast and has excellent statistical properties. 21 | /// 22 | /// The algorithm used here is translated from [the `xoshiro512plusplus.c` 23 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro512plusplus.c) by 24 | /// David Blackman and Sebastiano Vigna. 25 | #[derive(Debug, Clone, PartialEq, Eq)] 26 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 27 | pub struct Xoshiro512PlusPlus { 28 | s: [u64; 8], 29 | } 30 | 31 | impl Xoshiro512PlusPlus { 32 | /// Jump forward, equivalently to 2^256 calls to `next_u64()`. 33 | /// 34 | /// This can be used to generate 2^256 non-overlapping subsequences for 35 | /// parallel computations. 36 | /// 37 | /// ``` 38 | /// use rand_xoshiro::rand_core::SeedableRng; 39 | /// use rand_xoshiro::Xoshiro512PlusPlus; 40 | /// 41 | /// let rng1 = Xoshiro512PlusPlus::seed_from_u64(0); 42 | /// let mut rng2 = rng1.clone(); 43 | /// rng2.jump(); 44 | /// let mut rng3 = rng2.clone(); 45 | /// rng3.jump(); 46 | /// ``` 47 | pub fn jump(&mut self) { 48 | impl_jump!( 49 | u64, 50 | self, 51 | [ 52 | 0x33ed89b6e7a353f9, 53 | 0x760083d7955323be, 54 | 0x2837f2fbb5f22fae, 55 | 0x4b8c5674d309511c, 56 | 0xb11ac47a7ba28c25, 57 | 0xf1be7667092bcc1c, 58 | 0x53851efdb6df0aaf, 59 | 0x1ebbc8b23eaf25db 60 | ] 61 | ); 62 | } 63 | 64 | /// Jump forward, equivalently to 2^384 calls to `next_u64()`. 65 | /// 66 | /// This can be used to generate 2^128 starting points, from each of which 67 | /// `jump()` will generate 2^128 non-overlapping subsequences for parallel 68 | /// distributed computations. 69 | pub fn long_jump(&mut self) { 70 | impl_jump!( 71 | u64, 72 | self, 73 | [ 74 | 0x11467fef8f921d28, 75 | 0xa2a819f2e79c8ea8, 76 | 0xa8299fc284b3959a, 77 | 0xb4d347340ca63ee1, 78 | 0x1cb0940bedbff6ce, 79 | 0xd956c5c4fa1f8e17, 80 | 0x915e38fd4eda93bc, 81 | 0x5b3ccdfa5d7daca5 82 | ] 83 | ); 84 | } 85 | } 86 | 87 | impl SeedableRng for Xoshiro512PlusPlus { 88 | type Seed = Seed512; 89 | 90 | /// Create a new `Xoshiro512PlusPlus`. If `seed` is entirely 0, it will be 91 | /// mapped to a different seed. 92 | #[inline] 93 | fn from_seed(seed: Seed512) -> Xoshiro512PlusPlus { 94 | deal_with_zero_seed!(seed, Self); 95 | let mut state = [0; 8]; 96 | read_u64_into(&seed.0, &mut state); 97 | Xoshiro512PlusPlus { s: state } 98 | } 99 | 100 | /// Seed a `Xoshiro512PlusPlus` from a `u64` using `SplitMix64`. 101 | fn seed_from_u64(seed: u64) -> Xoshiro512PlusPlus { 102 | from_splitmix!(seed) 103 | } 104 | } 105 | 106 | impl RngCore for Xoshiro512PlusPlus { 107 | #[inline] 108 | fn next_u32(&mut self) -> u32 { 109 | // The lowest bits have some linear dependencies, so we use the 110 | // upper bits instead. 111 | (self.next_u64() >> 32) as u32 112 | } 113 | 114 | #[inline] 115 | fn next_u64(&mut self) -> u64 { 116 | let result_plusplus = plusplus_u64!(self.s[2], self.s[0], 17); 117 | impl_xoshiro_large!(self); 118 | result_plusplus 119 | } 120 | 121 | #[inline] 122 | fn fill_bytes(&mut self, dest: &mut [u8]) { 123 | fill_bytes_via_next(self, dest); 124 | } 125 | } 126 | 127 | #[cfg(test)] 128 | mod tests { 129 | use super::*; 130 | 131 | #[test] 132 | fn reference() { 133 | let mut rng = Xoshiro512PlusPlus::from_seed(Seed512([ 134 | 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 135 | 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 136 | 0, 0, 0, 0, 0, 0, 137 | ])); 138 | // These values were produced with the reference implementation: 139 | // http://xoshiro.di.unimi.it/xoshiro512plusplus.c 140 | let expected = [ 141 | 524291, 142 | 1048578, 143 | 539099140, 144 | 3299073855497, 145 | 6917532603230064654, 146 | 7494048333530275843, 147 | 14418333309547923463, 148 | 10960079161595355914, 149 | 18279570946505382726, 150 | 10209173166699159237, 151 | ]; 152 | for &e in &expected { 153 | assert_eq!(rng.next_u64(), e); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /rand_xoshiro/src/xoshiro512starstar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Developers of the Rand project. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use rand_core::impls::fill_bytes_via_next; 10 | use rand_core::le::read_u64_into; 11 | use rand_core::{RngCore, SeedableRng}; 12 | #[cfg(feature = "serde")] 13 | use serde::{Deserialize, Serialize}; 14 | 15 | use crate::Seed512; 16 | 17 | /// A xoshiro512** random number generator. 18 | /// 19 | /// The xoshiro512** algorithm is not suitable for cryptographic purposes, but 20 | /// is very fast and has excellent statistical properties. 21 | /// 22 | /// The algorithm used here is translated from [the `xoshiro512starstar.c` 23 | /// reference source code](http://xoshiro.di.unimi.it/xoshiro512starstar.c) by 24 | /// David Blackman and Sebastiano Vigna. 25 | #[derive(Debug, Clone, PartialEq, Eq)] 26 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 27 | pub struct Xoshiro512StarStar { 28 | s: [u64; 8], 29 | } 30 | 31 | impl Xoshiro512StarStar { 32 | /// Jump forward, equivalently to 2^256 calls to `next_u64()`. 33 | /// 34 | /// This can be used to generate 2^256 non-overlapping subsequences for 35 | /// parallel computations. 36 | /// 37 | /// ``` 38 | /// use rand_xoshiro::rand_core::SeedableRng; 39 | /// use rand_xoshiro::Xoshiro512StarStar; 40 | /// 41 | /// let rng1 = Xoshiro512StarStar::seed_from_u64(0); 42 | /// let mut rng2 = rng1.clone(); 43 | /// rng2.jump(); 44 | /// let mut rng3 = rng2.clone(); 45 | /// rng3.jump(); 46 | /// ``` 47 | pub fn jump(&mut self) { 48 | impl_jump!( 49 | u64, 50 | self, 51 | [ 52 | 0x33ed89b6e7a353f9, 53 | 0x760083d7955323be, 54 | 0x2837f2fbb5f22fae, 55 | 0x4b8c5674d309511c, 56 | 0xb11ac47a7ba28c25, 57 | 0xf1be7667092bcc1c, 58 | 0x53851efdb6df0aaf, 59 | 0x1ebbc8b23eaf25db 60 | ] 61 | ); 62 | } 63 | 64 | /// Jump forward, equivalently to 2^384 calls to `next_u64()`. 65 | /// 66 | /// This can be used to generate 2^128 starting points, from each of which 67 | /// `jump()` will generate 2^128 non-overlapping subsequences for parallel 68 | /// distributed computations. 69 | pub fn long_jump(&mut self) { 70 | impl_jump!( 71 | u64, 72 | self, 73 | [ 74 | 0x11467fef8f921d28, 75 | 0xa2a819f2e79c8ea8, 76 | 0xa8299fc284b3959a, 77 | 0xb4d347340ca63ee1, 78 | 0x1cb0940bedbff6ce, 79 | 0xd956c5c4fa1f8e17, 80 | 0x915e38fd4eda93bc, 81 | 0x5b3ccdfa5d7daca5 82 | ] 83 | ); 84 | } 85 | } 86 | 87 | impl SeedableRng for Xoshiro512StarStar { 88 | type Seed = Seed512; 89 | 90 | /// Create a new `Xoshiro512StarStar`. If `seed` is entirely 0, it will be 91 | /// mapped to a different seed. 92 | #[inline] 93 | fn from_seed(seed: Seed512) -> Xoshiro512StarStar { 94 | deal_with_zero_seed!(seed, Self); 95 | let mut state = [0; 8]; 96 | read_u64_into(&seed.0, &mut state); 97 | Xoshiro512StarStar { s: state } 98 | } 99 | 100 | /// Seed a `Xoshiro512StarStar` from a `u64` using `SplitMix64`. 101 | fn seed_from_u64(seed: u64) -> Xoshiro512StarStar { 102 | from_splitmix!(seed) 103 | } 104 | } 105 | 106 | impl RngCore for Xoshiro512StarStar { 107 | #[inline] 108 | fn next_u32(&mut self) -> u32 { 109 | // The lowest bits have some linear dependencies, so we use the 110 | // upper bits instead. 111 | (self.next_u64() >> 32) as u32 112 | } 113 | 114 | #[inline] 115 | fn next_u64(&mut self) -> u64 { 116 | let result_starstar = starstar_u64!(self.s[1]); 117 | impl_xoshiro_large!(self); 118 | result_starstar 119 | } 120 | 121 | #[inline] 122 | fn fill_bytes(&mut self, dest: &mut [u8]) { 123 | fill_bytes_via_next(self, dest); 124 | } 125 | } 126 | 127 | #[cfg(test)] 128 | mod tests { 129 | use super::*; 130 | 131 | #[test] 132 | #[rustfmt::skip] 133 | fn reference() { 134 | let mut rng = Xoshiro512StarStar::from_seed(Seed512( 135 | [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 136 | 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 137 | 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 138 | 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0])); 139 | // These values were produced with the reference implementation: 140 | // http://xoshiro.di.unimi.it/xoshiro512starstar.c 141 | let expected = [ 142 | 11520, 143 | 0, 144 | 23040, 145 | 23667840, 146 | 144955163520, 147 | 303992986974289920, 148 | 25332796375735680, 149 | 296904390158016, 150 | 13911081092387501979, 151 | 15304787717237593024, 152 | ]; 153 | for &e in &expected { 154 | assert_eq!(rng.next_u64(), e); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /rand_xoshiro/tests/serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde")] 2 | 3 | use rand_core::{RngCore, SeedableRng}; 4 | use rand_xoshiro::{ 5 | SplitMix64, Xoroshiro128Plus, Xoroshiro128StarStar, Xoroshiro64Star, Xoroshiro64StarStar, 6 | Xoshiro128Plus, Xoshiro128StarStar, Xoshiro256Plus, Xoshiro256StarStar, Xoshiro512Plus, 7 | Xoshiro512StarStar, 8 | }; 9 | 10 | macro_rules! serde_rng { 11 | ($rng:ident) => { 12 | use bincode; 13 | use std::io::{BufReader, BufWriter}; 14 | 15 | let mut rng = $rng::seed_from_u64(0); 16 | 17 | let buf: Vec = Vec::new(); 18 | let mut buf = BufWriter::new(buf); 19 | bincode::serialize_into(&mut buf, &rng).expect("Could not serialize"); 20 | 21 | let buf = buf.into_inner().unwrap(); 22 | let mut read = BufReader::new(&buf[..]); 23 | let mut deserialized: $rng = 24 | bincode::deserialize_from(&mut read).expect("Could not deserialize"); 25 | 26 | for _ in 0..16 { 27 | assert_eq!(rng.next_u64(), deserialized.next_u64()); 28 | } 29 | }; 30 | } 31 | 32 | #[test] 33 | fn test_splitmix64() { 34 | serde_rng!(SplitMix64); 35 | } 36 | 37 | #[test] 38 | fn test_xoroshiro64starstar() { 39 | serde_rng!(Xoroshiro64StarStar); 40 | } 41 | 42 | #[test] 43 | fn test_xoroshiro64star() { 44 | serde_rng!(Xoroshiro64Star); 45 | } 46 | 47 | #[test] 48 | fn test_xoroshiro128plus() { 49 | serde_rng!(Xoroshiro128Plus); 50 | } 51 | 52 | #[test] 53 | fn test_xoroshiro128starstar() { 54 | serde_rng!(Xoroshiro128StarStar); 55 | } 56 | 57 | #[test] 58 | fn test_xoshiro128starstar() { 59 | serde_rng!(Xoshiro128StarStar); 60 | } 61 | 62 | #[test] 63 | fn test_xoshiro128plus() { 64 | serde_rng!(Xoshiro128Plus); 65 | } 66 | 67 | #[test] 68 | fn test_xoshiro256starstar() { 69 | serde_rng!(Xoshiro256StarStar); 70 | } 71 | 72 | #[test] 73 | fn test_xoshiro256plus() { 74 | serde_rng!(Xoshiro256Plus); 75 | } 76 | 77 | #[test] 78 | fn test_xoshiro512starstar() { 79 | serde_rng!(Xoshiro512StarStar); 80 | } 81 | 82 | #[test] 83 | fn test_xoshiro512plus() { 84 | serde_rng!(Xoshiro512Plus); 85 | } 86 | --------------------------------------------------------------------------------