aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-11 05:07:52 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-11 05:07:52 +0000
commit474a8e9cd65ef42e89b04ec5f15907494dc9b1c5 (patch)
tree369e273affe8fedc061e4b74319fcf9b418aa961
parente488058ff72271a0aeacfa339e81787d6a818005 (diff)
parent76b2d3b02842d754c8f35d32c2e5bef690796a19 (diff)
downloadrand-android13-mainline-scheduling-release.tar.gz
Snap for 8570526 from 76b2d3b02842d754c8f35d32c2e5bef690796a19 to mainline-scheduling-releaseaml_sch_331113000aml_sch_331111000android13-mainline-scheduling-release
Change-Id: I1be94b17aa931f4857d24e386f4d88fe42d4abdf
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp21
-rw-r--r--CHANGELOG.md34
-rw-r--r--Cargo.lock98
-rw-r--r--Cargo.toml33
-rw-r--r--Cargo.toml.orig41
-rw-r--r--LICENSE-APACHE25
-rw-r--r--METADATA8
-rw-r--r--README.md14
-rw-r--r--TEST_MAPPING111
-rw-r--r--cargo2android.json10
-rw-r--r--patches/Android.bp.patch12
-rw-r--r--src/distributions/bernoulli.rs14
-rw-r--r--src/distributions/distribution.rs272
-rw-r--r--src/distributions/float.rs2
-rw-r--r--src/distributions/integer.rs9
-rw-r--r--src/distributions/mod.rs226
-rw-r--r--src/distributions/other.rs76
-rw-r--r--src/distributions/slice.rs117
-rw-r--r--src/distributions/uniform.rs97
-rw-r--r--src/distributions/utils.rs8
-rw-r--r--src/distributions/weighted.rs1
-rw-r--r--src/distributions/weighted_index.rs21
-rw-r--r--src/lib.rs3
-rw-r--r--src/rng.rs47
-rw-r--r--src/rngs/adapter/mod.rs1
-rw-r--r--src/rngs/adapter/read.rs15
-rw-r--r--src/rngs/adapter/reseeding.rs28
-rw-r--r--src/rngs/std.rs6
-rw-r--r--src/rngs/thread.rs9
-rw-r--r--src/rngs/xoshiro256plusplus.rs4
-rw-r--r--src/seq/index.rs14
-rw-r--r--src/seq/mod.rs17
33 files changed, 843 insertions, 558 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index c17e718..681c31d 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "6ecbe2626b2cc6110a25c97b1702b347574febc7"
- }
-}
+ "sha1": "937320cbfeebd4352a23086d9c6e68f067f74644"
+ },
+ "path_in_vcs": ""
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index ec4c075..5f32482 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,8 +1,6 @@
-// This file is generated by cargo2android.py --device --run --dependencies --patch=patches/Android.bp.patch.
+// This file is generated by cargo2android.py --config cargo2android.json.
// Do not modify this file as changes will be overridden on upgrade.
-
-
package {
default_applicable_licenses: ["external_rust_crates_rand_license"],
}
@@ -44,6 +42,8 @@ rust_library {
name: "librand",
host_supported: true,
crate_name: "rand",
+ cargo_env_compat: true,
+ cargo_pkg_version: "0.8.5",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -52,7 +52,7 @@ rust_library {
"getrandom",
"libc",
"rand_chacha",
- "rand_hc",
+ "small_rng",
"std",
"std_rng",
],
@@ -61,13 +61,8 @@ rust_library {
"librand_chacha",
"librand_core",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
-
-// dependent_library ["feature_list"]
-// cfg-if-1.0.0
-// getrandom-0.2.2 "std"
-// libc-0.2.93
-// ppv-lite86-0.2.10 "simd,std"
-// rand_chacha-0.3.0 "std"
-// rand_core-0.6.2 "alloc,getrandom,std"
-// rand_hc-0.3.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 536c510..b0872af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,38 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md).
You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful.
+## [0.8.5] - 2021-08-20
+### Fixes
+- Fix build on non-32/64-bit architectures (#1144)
+- Fix "min_const_gen" feature for `no_std` (#1173)
+- Check `libc::pthread_atfork` return value with panic on error (#1178)
+- More robust reseeding in case `ReseedingRng` is used from a fork handler (#1178)
+- Fix nightly: remove unused `slice_partition_at_index` feature (#1215)
+- Fix nightly + `simd_support`: update `packed_simd` (#1216)
+
+### Rngs
+- `StdRng`: Switch from HC128 to ChaCha12 on emscripten (#1142).
+ We now use ChaCha12 on all platforms.
+
+### Documentation
+- Added docs about rand's use of const generics (#1150)
+- Better random chars example (#1157)
+
+
+## [0.8.4] - 2021-06-15
+### Additions
+- Use const-generics to support arrays of all sizes (#1104)
+- Implement `Clone` and `Copy` for `Alphanumeric` (#1126)
+- Add `Distribution::map` to derive a distribution using a closure (#1129)
+- Add `Slice` distribution (#1107)
+- Add `DistString` trait with impls for `Standard` and `Alphanumeric` (#1133)
+
+### Other
+- Reorder asserts in `Uniform` float distributions for easier debugging of non-finite arguments
+ (#1094, #1108)
+- Add range overflow check in `Uniform` float distributions (#1108)
+- Deprecate `rngs::adapter::ReadRng` (#1130)
+
## [0.8.3] - 2021-01-25
### Fixes
- Fix `no-std` + `alloc` build by gating `choose_multiple_weighted` on `std` (#1088)
@@ -664,4 +696,4 @@ when updating from `rand 0.7.0` without also updating `rand_core`.
## [0.10-pre] - 2014-03-02
### Added
-- Seperate `rand` out of the standard library
+- Separate `rand` out of the standard library
diff --git a/Cargo.lock b/Cargo.lock
index 01304e6..631e46a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,28 +1,17 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "bincode"
-version = "1.3.1"
+version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
- "byteorder",
"serde",
]
[[package]]
-name = "byteorder"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -30,20 +19,20 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
-version = "0.2.82"
+version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]]
name = "libm"
@@ -53,50 +42,50 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
[[package]]
name = "log"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
]
[[package]]
name = "packed_simd_2"
-version = "0.3.4"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
+checksum = "defdcfef86dcc44ad208f71d9ff4ce28df6537a4e0d6b0e8e845cb8ca10059a6"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
"libm",
]
[[package]]
name = "ppv-lite86"
-version = "0.2.10"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
-version = "1.0.24"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
-version = "1.0.8"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
+checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
dependencies = [
"bincode",
"libc",
@@ -104,16 +93,15 @@ dependencies = [
"packed_simd_2",
"rand_chacha",
"rand_core",
- "rand_hc",
"rand_pcg",
"serde",
]
[[package]]
name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
@@ -121,45 +109,37 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.1"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
+ "serde",
]
[[package]]
name = "rand_pcg"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7de198537002b913568a3847e53535ace266f93526caf5c360ec41d72c5787f0"
+checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
dependencies = [
"rand_core",
]
[[package]]
name = "serde"
-version = "1.0.120"
+version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "166b2349061381baf54a58e4b13c89369feb0ef2eaa57198899e2312aac30aab"
+checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.120"
+version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ca2a8cb5805ce9e3b95435e3765b7b553cecc762d938d409434338386cb5775"
+checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
dependencies = [
"proc-macro2",
"quote",
@@ -168,9 +148,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.59"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07cb8b1b4ebf86a89ee88cbd201b022b94138c623644d035185c84d3f41b7e66"
+checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
dependencies = [
"proc-macro2",
"quote",
@@ -179,12 +159,12 @@ dependencies = [
[[package]]
name = "unicode-xid"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "wasi"
-version = "0.10.1+wasi-snapshot-preview1"
+version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
diff --git a/Cargo.toml b/Cargo.toml
index 1086335..3f38081 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
include = ["src/", "LICENSE-*", "README.md", "CHANGELOG.md", "COPYRIGHT"]
autobenches = true
@@ -36,11 +35,16 @@ version = "0.4.4"
optional = true
[dependencies.packed_simd]
-version = "0.3.4"
+version = "0.3.7"
features = ["into_bits"]
optional = true
package = "packed_simd_2"
+[dependencies.rand_chacha]
+version = "0.3.0"
+optional = true
+default-features = false
+
[dependencies.rand_core]
version = "0.6.0"
@@ -51,9 +55,6 @@ optional = true
[dev-dependencies.bincode]
version = "1.2.1"
-[dev-dependencies.rand_hc]
-version = "0.3.0"
-
[dev-dependencies.rand_pcg]
version = "0.3.0"
@@ -61,19 +62,13 @@ version = "0.3.0"
alloc = ["rand_core/alloc"]
default = ["std", "std_rng"]
getrandom = ["rand_core/getrandom"]
+min_const_gen = []
nightly = []
-serde1 = ["serde"]
+serde1 = ["serde", "rand_core/serde1"]
simd_support = ["packed_simd"]
small_rng = []
std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom", "libc"]
-std_rng = ["rand_chacha", "rand_hc"]
-[target."cfg(not(target_os = \"emscripten\"))".dependencies.rand_chacha]
-version = "0.3.0"
-optional = true
-default-features = false
-[target."cfg(target_os = \"emscripten\")".dependencies.rand_hc]
-version = "0.3.0"
-optional = true
+std_rng = ["rand_chacha"]
[target."cfg(unix)".dependencies.libc]
version = "0.2.22"
optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index afd1339..98ba373 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
@@ -16,11 +16,20 @@ autobenches = true
edition = "2018"
include = ["src/", "LICENSE-*", "README.md", "CHANGELOG.md", "COPYRIGHT"]
+[package.metadata.docs.rs]
+# To build locally:
+# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --all-features --no-deps --open
+all-features = true
+rustdoc-args = ["--cfg", "doc_cfg"]
+
+[package.metadata.playground]
+features = ["small_rng", "serde1"]
+
[features]
# Meta-features:
default = ["std", "std_rng"]
nightly = [] # enables performance optimizations requiring nightly rust
-serde1 = ["serde"]
+serde1 = ["serde", "rand_core/serde1"]
# Option (enabled by default): without "std" rand uses libcore; this option
# enables functionality expected to be available on a standard platform.
@@ -36,17 +45,20 @@ getrandom = ["rand_core/getrandom"]
simd_support = ["packed_simd"]
# Option (enabled by default): enable StdRng
-std_rng = ["rand_chacha", "rand_hc"]
+std_rng = ["rand_chacha"]
# Option: enable SmallRng
small_rng = []
+# Option: for rustc ≥ 1.51, enable generating random arrays of any size
+# using min-const-generics
+min_const_gen = []
+
[workspace]
members = [
"rand_core",
"rand_distr",
"rand_chacha",
- "rand_hc",
"rand_pcg",
]
@@ -54,11 +66,12 @@ members = [
rand_core = { path = "rand_core", version = "0.6.0" }
log = { version = "0.4.4", optional = true }
serde = { version = "1.0.103", features = ["derive"], optional = true }
+rand_chacha = { path = "rand_chacha", version = "0.3.0", default-features = false, optional = true }
[dependencies.packed_simd]
# NOTE: so far no version works reliably due to dependence on unstable features
package = "packed_simd_2"
-version = "0.3.4"
+version = "0.3.7"
optional = true
features = ["into_bits"]
@@ -66,25 +79,7 @@ features = ["into_bits"]
# Used for fork protection (reseeding.rs)
libc = { version = "0.2.22", optional = true, default-features = false }
-# Emscripten does not support 128-bit integers, which are used by ChaCha code.
-# We work around this by using a different RNG.
-[target.'cfg(not(target_os = "emscripten"))'.dependencies]
-rand_chacha = { path = "rand_chacha", version = "0.3.0", default-features = false, optional = true }
-[target.'cfg(target_os = "emscripten")'.dependencies]
-rand_hc = { path = "rand_hc", version = "0.3.0", optional = true }
-
[dev-dependencies]
rand_pcg = { path = "rand_pcg", version = "0.3.0" }
-# Only for benches:
-rand_hc = { path = "rand_hc", version = "0.3.0" }
# Only to test serde1
bincode = "1.2.1"
-
-[package.metadata.docs.rs]
-# To build locally:
-# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --all-features --no-deps --open
-all-features = true
-rustdoc-args = ["--cfg", "doc_cfg"]
-
-[package.metadata.playground]
-features = ["small_rng", "serde1"]
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
index 17d7468..494ad3b 100644
--- a/LICENSE-APACHE
+++ b/LICENSE-APACHE
@@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/METADATA b/METADATA
index 7ad83fc..2449ce5 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/rand/rand-0.8.3.crate"
+ value: "https://static.crates.io/crates/rand/rand-0.8.5.crate"
}
- version: "0.8.3"
+ version: "0.8.5"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 4
+ year: 2022
+ month: 3
day: 1
}
}
diff --git a/README.md b/README.md
index aaf6df1..44c2e4d 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-rand = "0.8.0"
+rand = "0.8.4"
```
To get started using Rand, see [The Book](https://rust-random.github.io/book).
@@ -120,7 +120,7 @@ Rand is built with these features enabled by default:
Optionally, the following dependencies can be enabled:
-- `log` enables logging via the `log` crate` crate
+- `log` enables logging via the `log` crate
Additionally, these features configure Rand:
@@ -128,6 +128,8 @@ Additionally, these features configure Rand:
- `nightly` enables some optimizations requiring nightly Rust
- `simd_support` (experimental) enables sampling of SIMD values
(uniformly random SIMD integers and floats), requiring nightly Rust
+- `min_const_gen` enables generating random arrays of
+ any size using min-const-generics, requiring Rust ≥ 1.51.
Note that nightly features are not stable and therefore not all library and
compiler versions will be compatible. This is especially true of Rand's
@@ -139,6 +141,14 @@ unavailable (unless `getrandom` is enabled), large parts of `seq` are
unavailable (unless `alloc` is enabled), and `thread_rng` and `random` are
unavailable.
+### WASM support
+
+The WASM target `wasm32-unknown-unknown` is not *automatically* supported by
+`rand` or `getrandom`. To solve this, either use a different target such as
+`wasm32-wasi` or add a direct dependency on `getrandom` with the `js` feature
+(if the target supports JavaScript). See
+[getrandom#WebAssembly support](https://docs.rs/getrandom/latest/getrandom/#webassembly-support).
+
# License
Rand is distributed under the terms of both the MIT license and the
diff --git a/TEST_MAPPING b/TEST_MAPPING
index c152478..ff12af6 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,134 +1,93 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
- "presubmit": [
- {
- "name": "crossbeam-epoch_device_test_src_lib"
- },
- {
- "name": "crossbeam-epoch_device_test_tests_loom"
- },
- {
- "name": "crossbeam-utils_device_test_src_lib"
- },
- {
- "name": "crossbeam-utils_device_test_tests_atomic_cell"
- },
- {
- "name": "crossbeam-utils_device_test_tests_cache_padded"
- },
- {
- "name": "crossbeam-utils_device_test_tests_parker"
- },
- {
- "name": "crossbeam-utils_device_test_tests_sharded_lock"
- },
+ "imports": [
{
- "name": "crossbeam-utils_device_test_tests_thread"
- },
- {
- "name": "crossbeam-utils_device_test_tests_wait_group"
- },
- {
- "name": "keystore2_test"
+ "path": "external/rust/crates/base64"
},
{
- "name": "tokio_device_test_tests_buffered"
+ "path": "external/rust/crates/cast"
},
{
- "name": "tokio_device_test_tests_io_async_read"
+ "path": "external/rust/crates/crc32fast"
},
{
- "name": "tokio_device_test_tests_io_copy_bidirectional"
+ "path": "external/rust/crates/crossbeam-deque"
},
{
- "name": "tokio_device_test_tests_io_lines"
+ "path": "external/rust/crates/crossbeam-epoch"
},
{
- "name": "tokio_device_test_tests_io_mem_stream"
+ "path": "external/rust/crates/crossbeam-queue"
},
{
- "name": "tokio_device_test_tests_io_read"
+ "path": "external/rust/crates/crossbeam-utils"
},
{
- "name": "tokio_device_test_tests_io_read_buf"
+ "path": "external/rust/crates/mio"
},
{
- "name": "tokio_device_test_tests_io_read_to_end"
+ "path": "external/rust/crates/quickcheck"
},
{
- "name": "tokio_device_test_tests_io_take"
+ "path": "external/rust/crates/regex"
},
{
- "name": "tokio_device_test_tests_io_write"
+ "path": "external/rust/crates/ryu"
},
{
- "name": "tokio_device_test_tests_io_write_all"
- },
- {
- "name": "tokio_device_test_tests_io_write_buf"
- },
- {
- "name": "tokio_device_test_tests_io_write_int"
- },
- {
- "name": "tokio_device_test_tests_macros_join"
- },
- {
- "name": "tokio_device_test_tests_no_rt"
- },
- {
- "name": "tokio_device_test_tests_rt_basic"
- },
- {
- "name": "tokio_device_test_tests_rt_threaded"
- },
+ "path": "external/rust/crates/tokio"
+ }
+ ],
+ "presubmit": [
{
- "name": "tokio_device_test_tests_sync_barrier"
+ "name": "ZipFuseTest"
},
{
- "name": "tokio_device_test_tests_sync_broadcast"
+ "name": "apkdmverity.test"
},
{
- "name": "tokio_device_test_tests_sync_errors"
+ "name": "authfs_device_test_src_lib"
},
{
- "name": "tokio_device_test_tests_sync_mpsc"
+ "name": "keystore2_test"
},
{
- "name": "tokio_device_test_tests_sync_mutex_owned"
+ "name": "keystore2_test_utils_test"
},
{
- "name": "tokio_device_test_tests_sync_rwlock"
+ "name": "legacykeystore_test"
},
{
- "name": "tokio_device_test_tests_sync_watch"
+ "name": "microdroid_manager_test"
},
{
- "name": "tokio_device_test_tests_task_local"
- },
+ "name": "virtualizationservice_device_test"
+ }
+ ],
+ "presubmit-rust": [
{
- "name": "tokio_device_test_tests_task_local_set"
+ "name": "ZipFuseTest"
},
{
- "name": "tokio_device_test_tests_tcp_accept"
+ "name": "apkdmverity.test"
},
{
- "name": "tokio_device_test_tests_tcp_echo"
+ "name": "authfs_device_test_src_lib"
},
{
- "name": "tokio_device_test_tests_tcp_into_std"
+ "name": "keystore2_test"
},
{
- "name": "tokio_device_test_tests_tcp_shutdown"
+ "name": "keystore2_test_utils_test"
},
{
- "name": "tokio_device_test_tests_time_rt"
+ "name": "legacykeystore_test"
},
{
- "name": "tokio_device_test_tests_uds_split"
+ "name": "microdroid_manager_test"
},
{
- "name": "vpnprofilestore_test"
+ "name": "virtualizationservice_device_test"
}
]
}
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..cdb5c0d
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,10 @@
+{
+ "apex-available": [
+ "//apex_available:platform",
+ "com.android.virt"
+ ],
+ "dependencies": true,
+ "device": true,
+ "features": "default,small_rng",
+ "run": true
+} \ No newline at end of file
diff --git a/patches/Android.bp.patch b/patches/Android.bp.patch
deleted file mode 100644
index 59579a5..0000000
--- a/patches/Android.bp.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/Android.bp b/Android.bp
-index 49626bd..5c40f99 100644
---- a/Android.bp
-+++ b/Android.bp
-@@ -23,7 +23,6 @@ rust_library {
- "liblibc",
- "librand_chacha",
- "librand_core",
-- "librand_hc",
- ],
- }
-
diff --git a/src/distributions/bernoulli.rs b/src/distributions/bernoulli.rs
index b968ca0..226db79 100644
--- a/src/distributions/bernoulli.rs
+++ b/src/distributions/bernoulli.rs
@@ -33,7 +33,7 @@ use serde::{Serialize, Deserialize};
/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`),
/// so only probabilities that are multiples of 2<sup>-64</sup> can be
/// represented.
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Bernoulli {
/// Probability of success, relative to the maximal integer.
@@ -49,7 +49,7 @@ pub struct Bernoulli {
// `f64` only has 53 bits of precision, and the next largest value of `p` will
// result in `2^64 - 2048`.
//
-// Also there is a 100% theoretical concern: if someone consistenly wants to
+// Also there is a 100% theoretical concern: if someone consistently wants to
// generate `true` using the Bernoulli distribution (i.e. by using a probability
// of `1.0`), just using `u64::MAX` is not enough. On average it would return
// false once every 2^64 iterations. Some people apparently care about this
@@ -96,7 +96,7 @@ impl Bernoulli {
/// 2<sup>-64</sup> in `[0, 1]` can be represented as a `f64`.)
#[inline]
pub fn new(p: f64) -> Result<Bernoulli, BernoulliError> {
- if !(p >= 0.0 && p < 1.0) {
+ if !(0.0..1.0).contains(&p) {
if p == 1.0 {
return Ok(Bernoulli { p_int: ALWAYS_TRUE });
}
@@ -157,6 +157,9 @@ mod test {
#[test]
fn test_trivial() {
+ // We prefer to be explicit here.
+ #![allow(clippy::bool_assert_comparison)]
+
let mut r = crate::test::rng(1);
let always_false = Bernoulli::new(0.0).unwrap();
let always_true = Bernoulli::new(1.0).unwrap();
@@ -208,4 +211,9 @@ mod test {
true, false, false, true, false, false, true, true, true, true
]);
}
+
+ #[test]
+ fn bernoulli_distributions_can_be_compared() {
+ assert_eq!(Bernoulli::new(1.0), Bernoulli::new(1.0));
+ }
}
diff --git a/src/distributions/distribution.rs b/src/distributions/distribution.rs
new file mode 100644
index 0000000..c5cf6a6
--- /dev/null
+++ b/src/distributions/distribution.rs
@@ -0,0 +1,272 @@
+// Copyright 2018 Developers of the Rand project.
+// Copyright 2013-2017 The Rust Project Developers.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Distribution trait and associates
+
+use crate::Rng;
+use core::iter;
+#[cfg(feature = "alloc")]
+use alloc::string::String;
+
+/// Types (distributions) that can be used to create a random instance of `T`.
+///
+/// It is possible to sample from a distribution through both the
+/// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and
+/// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which
+/// produces an iterator that samples from the distribution.
+///
+/// All implementations are expected to be immutable; this has the significant
+/// advantage of not needing to consider thread safety, and for most
+/// distributions efficient state-less sampling algorithms are available.
+///
+/// Implementations are typically expected to be portable with reproducible
+/// results when used with a PRNG with fixed seed; see the
+/// [portability chapter](https://rust-random.github.io/book/portability.html)
+/// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize`
+/// type requires different sampling on 32-bit and 64-bit machines.
+///
+/// [`sample_iter`]: Distribution::sample_iter
+pub trait Distribution<T> {
+ /// Generate a random value of `T`, using `rng` as the source of randomness.
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;
+
+ /// Create an iterator that generates random values of `T`, using `rng` as
+ /// the source of randomness.
+ ///
+ /// Note that this function takes `self` by value. This works since
+ /// `Distribution<T>` is impl'd for `&D` where `D: Distribution<T>`,
+ /// however borrowing is not automatic hence `distr.sample_iter(...)` may
+ /// need to be replaced with `(&distr).sample_iter(...)` to borrow or
+ /// `(&*distr).sample_iter(...)` to reborrow an existing reference.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use rand::thread_rng;
+ /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard};
+ ///
+ /// let mut rng = thread_rng();
+ ///
+ /// // Vec of 16 x f32:
+ /// let v: Vec<f32> = Standard.sample_iter(&mut rng).take(16).collect();
+ ///
+ /// // String:
+ /// let s: String = Alphanumeric
+ /// .sample_iter(&mut rng)
+ /// .take(7)
+ /// .map(char::from)
+ /// .collect();
+ ///
+ /// // Dice-rolling:
+ /// let die_range = Uniform::new_inclusive(1, 6);
+ /// let mut roll_die = die_range.sample_iter(&mut rng);
+ /// while roll_die.next().unwrap() != 6 {
+ /// println!("Not a 6; rolling again!");
+ /// }
+ /// ```
+ fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
+ where
+ R: Rng,
+ Self: Sized,
+ {
+ DistIter {
+ distr: self,
+ rng,
+ phantom: ::core::marker::PhantomData,
+ }
+ }
+
+ /// Create a distribution of values of 'S' by mapping the output of `Self`
+ /// through the closure `F`
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use rand::thread_rng;
+ /// use rand::distributions::{Distribution, Uniform};
+ ///
+ /// let mut rng = thread_rng();
+ ///
+ /// let die = Uniform::new_inclusive(1, 6);
+ /// let even_number = die.map(|num| num % 2 == 0);
+ /// while !even_number.sample(&mut rng) {
+ /// println!("Still odd; rolling again!");
+ /// }
+ /// ```
+ fn map<F, S>(self, func: F) -> DistMap<Self, F, T, S>
+ where
+ F: Fn(T) -> S,
+ Self: Sized,
+ {
+ DistMap {
+ distr: self,
+ func,
+ phantom: ::core::marker::PhantomData,
+ }
+ }
+}
+
+impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
+ (*self).sample(rng)
+ }
+}
+
+/// An iterator that generates random values of `T` with distribution `D`,
+/// using `R` as the source of randomness.
+///
+/// This `struct` is created by the [`sample_iter`] method on [`Distribution`].
+/// See its documentation for more.
+///
+/// [`sample_iter`]: Distribution::sample_iter
+#[derive(Debug)]
+pub struct DistIter<D, R, T> {
+ distr: D,
+ rng: R,
+ phantom: ::core::marker::PhantomData<T>,
+}
+
+impl<D, R, T> Iterator for DistIter<D, R, T>
+where
+ D: Distribution<T>,
+ R: Rng,
+{
+ type Item = T;
+
+ #[inline(always)]
+ fn next(&mut self) -> Option<T> {
+ // Here, self.rng may be a reference, but we must take &mut anyway.
+ // Even if sample could take an R: Rng by value, we would need to do this
+ // since Rng is not copyable and we cannot enforce that this is "reborrowable".
+ Some(self.distr.sample(&mut self.rng))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (usize::max_value(), None)
+ }
+}
+
+impl<D, R, T> iter::FusedIterator for DistIter<D, R, T>
+where
+ D: Distribution<T>,
+ R: Rng,
+{
+}
+
+#[cfg(features = "nightly")]
+impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
+where
+ D: Distribution<T>,
+ R: Rng,
+{
+}
+
+/// A distribution of values of type `S` derived from the distribution `D`
+/// by mapping its output of type `T` through the closure `F`.
+///
+/// This `struct` is created by the [`Distribution::map`] method.
+/// See its documentation for more.
+#[derive(Debug)]
+pub struct DistMap<D, F, T, S> {
+ distr: D,
+ func: F,
+ phantom: ::core::marker::PhantomData<fn(T) -> S>,
+}
+
+impl<D, F, T, S> Distribution<S> for DistMap<D, F, T, S>
+where
+ D: Distribution<T>,
+ F: Fn(T) -> S,
+{
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> S {
+ (self.func)(self.distr.sample(rng))
+ }
+}
+
+/// `String` sampler
+///
+/// Sampling a `String` of random characters is not quite the same as collecting
+/// a sequence of chars. This trait contains some helpers.
+#[cfg(feature = "alloc")]
+pub trait DistString {
+ /// Append `len` random chars to `string`
+ fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize);
+
+ /// Generate a `String` of `len` random chars
+ #[inline]
+ fn sample_string<R: Rng + ?Sized>(&self, rng: &mut R, len: usize) -> String {
+ let mut s = String::new();
+ self.append_string(rng, &mut s, len);
+ s
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::distributions::{Distribution, Uniform};
+ use crate::Rng;
+
+ #[test]
+ fn test_distributions_iter() {
+ use crate::distributions::Open01;
+ let mut rng = crate::test::rng(210);
+ let distr = Open01;
+ let mut iter = Distribution::<f32>::sample_iter(distr, &mut rng);
+ let mut sum: f32 = 0.;
+ for _ in 0..100 {
+ sum += iter.next().unwrap();
+ }
+ assert!(0. < sum && sum < 100.);
+ }
+
+ #[test]
+ fn test_distributions_map() {
+ let dist = Uniform::new_inclusive(0, 5).map(|val| val + 15);
+
+ let mut rng = crate::test::rng(212);
+ let val = dist.sample(&mut rng);
+ assert!((15..=20).contains(&val));
+ }
+
+ #[test]
+ fn test_make_an_iter() {
+ fn ten_dice_rolls_other_than_five<R: Rng>(
+ rng: &mut R,
+ ) -> impl Iterator<Item = i32> + '_ {
+ Uniform::new_inclusive(1, 6)
+ .sample_iter(rng)
+ .filter(|x| *x != 5)
+ .take(10)
+ }
+
+ let mut rng = crate::test::rng(211);
+ let mut count = 0;
+ for val in ten_dice_rolls_other_than_five(&mut rng) {
+ assert!((1..=6).contains(&val) && val != 5);
+ count += 1;
+ }
+ assert_eq!(count, 10);
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn test_dist_string() {
+ use core::str;
+ use crate::distributions::{Alphanumeric, DistString, Standard};
+ let mut rng = crate::test::rng(213);
+
+ let s1 = Alphanumeric.sample_string(&mut rng, 20);
+ assert_eq!(s1.len(), 20);
+ assert_eq!(str::from_utf8(s1.as_bytes()), Ok(s1.as_str()));
+
+ let s2 = Standard.sample_string(&mut rng, 20);
+ assert_eq!(s2.chars().count(), 20);
+ assert_eq!(str::from_utf8(s2.as_bytes()), Ok(s2.as_str()));
+ }
+}
diff --git a/src/distributions/float.rs b/src/distributions/float.rs
index 733a403..ce5946f 100644
--- a/src/distributions/float.rs
+++ b/src/distributions/float.rs
@@ -78,7 +78,7 @@ pub struct Open01;
pub trait IntoFloat {
type F;
- /// Helper method to combine the fraction and a contant exponent into a
+ /// Helper method to combine the fraction and a constant exponent into a
/// float.
///
/// Only the least significant bits of `self` may be set, 23 for `f32` and
diff --git a/src/distributions/integer.rs b/src/distributions/integer.rs
index 8a2ce4c..19ce715 100644
--- a/src/distributions/integer.rs
+++ b/src/distributions/integer.rs
@@ -14,8 +14,8 @@ use crate::Rng;
use core::arch::x86::{__m128i, __m256i};
#[cfg(all(target_arch = "x86_64", feature = "simd_support"))]
use core::arch::x86_64::{__m128i, __m256i};
-#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128;
-use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
+ NonZeroU128};
#[cfg(feature = "simd_support")] use packed_simd::*;
impl Distribution<u8> for Standard {
@@ -46,7 +46,6 @@ impl Distribution<u64> for Standard {
}
}
-#[cfg(not(target_os = "emscripten"))]
impl Distribution<u128> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
@@ -86,7 +85,6 @@ impl_int_from_uint! { i8, u8 }
impl_int_from_uint! { i16, u16 }
impl_int_from_uint! { i32, u32 }
impl_int_from_uint! { i64, u64 }
-#[cfg(not(target_os = "emscripten"))]
impl_int_from_uint! { i128, u128 }
impl_int_from_uint! { isize, usize }
@@ -108,7 +106,6 @@ impl_nzint!(NonZeroU8, NonZeroU8::new);
impl_nzint!(NonZeroU16, NonZeroU16::new);
impl_nzint!(NonZeroU32, NonZeroU32::new);
impl_nzint!(NonZeroU64, NonZeroU64::new);
-#[cfg(not(target_os = "emscripten"))]
impl_nzint!(NonZeroU128, NonZeroU128::new);
impl_nzint!(NonZeroUsize, NonZeroUsize::new);
@@ -173,7 +170,6 @@ mod tests {
rng.sample::<i16, _>(Standard);
rng.sample::<i32, _>(Standard);
rng.sample::<i64, _>(Standard);
- #[cfg(not(target_os = "emscripten"))]
rng.sample::<i128, _>(Standard);
rng.sample::<usize, _>(Standard);
@@ -181,7 +177,6 @@ mod tests {
rng.sample::<u16, _>(Standard);
rng.sample::<u32, _>(Standard);
rng.sample::<u64, _>(Standard);
- #[cfg(not(target_os = "emscripten"))]
rng.sample::<u128, _>(Standard);
}
diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs
index 652f52a..05ca806 100644
--- a/src/distributions/mod.rs
+++ b/src/distributions/mod.rs
@@ -93,163 +93,43 @@
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs
-use crate::Rng;
-use core::iter;
-
-pub use self::bernoulli::{Bernoulli, BernoulliError};
-pub use self::float::{Open01, OpenClosed01};
-pub use self::other::Alphanumeric;
-#[doc(inline)] pub use self::uniform::Uniform;
-
-#[cfg(feature = "alloc")]
-pub use self::weighted_index::{WeightedError, WeightedIndex};
-
mod bernoulli;
-pub mod uniform;
-
-#[deprecated(since = "0.8.0", note = "use rand::distributions::{WeightedIndex, WeightedError} instead")]
-#[cfg(feature = "alloc")]
-#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
-pub mod weighted;
-#[cfg(feature = "alloc")] mod weighted_index;
-
-#[cfg(feature = "serde1")]
-use serde::{Serialize, Deserialize};
-
+mod distribution;
mod float;
-#[doc(hidden)]
-pub mod hidden_export {
- pub use super::float::IntoFloat; // used by rand_distr
-}
mod integer;
mod other;
+mod slice;
mod utils;
+#[cfg(feature = "alloc")]
+mod weighted_index;
-/// Types (distributions) that can be used to create a random instance of `T`.
-///
-/// It is possible to sample from a distribution through both the
-/// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and
-/// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which
-/// produces an iterator that samples from the distribution.
-///
-/// All implementations are expected to be immutable; this has the significant
-/// advantage of not needing to consider thread safety, and for most
-/// distributions efficient state-less sampling algorithms are available.
-///
-/// Implementations are typically expected to be portable with reproducible
-/// results when used with a PRNG with fixed seed; see the
-/// [portability chapter](https://rust-random.github.io/book/portability.html)
-/// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize`
-/// type requires different sampling on 32-bit and 64-bit machines.
-///
-/// [`sample_iter`]: Distribution::method.sample_iter
-pub trait Distribution<T> {
- /// Generate a random value of `T`, using `rng` as the source of randomness.
- fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;
-
- /// Create an iterator that generates random values of `T`, using `rng` as
- /// the source of randomness.
- ///
- /// Note that this function takes `self` by value. This works since
- /// `Distribution<T>` is impl'd for `&D` where `D: Distribution<T>`,
- /// however borrowing is not automatic hence `distr.sample_iter(...)` may
- /// need to be replaced with `(&distr).sample_iter(...)` to borrow or
- /// `(&*distr).sample_iter(...)` to reborrow an existing reference.
- ///
- /// # Example
- ///
- /// ```
- /// use rand::thread_rng;
- /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard};
- ///
- /// let mut rng = thread_rng();
- ///
- /// // Vec of 16 x f32:
- /// let v: Vec<f32> = Standard.sample_iter(&mut rng).take(16).collect();
- ///
- /// // String:
- /// let s: String = Alphanumeric
- /// .sample_iter(&mut rng)
- /// .take(7)
- /// .map(char::from)
- /// .collect();
- ///
- /// // Dice-rolling:
- /// let die_range = Uniform::new_inclusive(1, 6);
- /// let mut roll_die = die_range.sample_iter(&mut rng);
- /// while roll_die.next().unwrap() != 6 {
- /// println!("Not a 6; rolling again!");
- /// }
- /// ```
- fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
- where
- R: Rng,
- Self: Sized,
- {
- DistIter {
- distr: self,
- rng,
- phantom: ::core::marker::PhantomData,
- }
- }
-}
-
-impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
- fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
- (*self).sample(rng)
- }
-}
-
-
-/// An iterator that generates random values of `T` with distribution `D`,
-/// using `R` as the source of randomness.
-///
-/// This `struct` is created by the [`sample_iter`] method on [`Distribution`].
-/// See its documentation for more.
-///
-/// [`sample_iter`]: Distribution::sample_iter
-#[derive(Debug)]
-pub struct DistIter<D, R, T> {
- distr: D,
- rng: R,
- phantom: ::core::marker::PhantomData<T>,
-}
-
-impl<D, R, T> Iterator for DistIter<D, R, T>
-where
- D: Distribution<T>,
- R: Rng,
-{
- type Item = T;
-
- #[inline(always)]
- fn next(&mut self) -> Option<T> {
- // Here, self.rng may be a reference, but we must take &mut anyway.
- // Even if sample could take an R: Rng by value, we would need to do this
- // since Rng is not copyable and we cannot enforce that this is "reborrowable".
- Some(self.distr.sample(&mut self.rng))
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (usize::max_value(), None)
- }
-}
-
-impl<D, R, T> iter::FusedIterator for DistIter<D, R, T>
-where
- D: Distribution<T>,
- R: Rng,
-{
+#[doc(hidden)]
+pub mod hidden_export {
+ pub use super::float::IntoFloat; // used by rand_distr
}
+pub mod uniform;
+#[deprecated(
+ since = "0.8.0",
+ note = "use rand::distributions::{WeightedIndex, WeightedError} instead"
+)]
+#[cfg(feature = "alloc")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
+pub mod weighted;
-#[cfg(features = "nightly")]
-impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
-where
- D: Distribution<T>,
- R: Rng,
-{
-}
+pub use self::bernoulli::{Bernoulli, BernoulliError};
+pub use self::distribution::{Distribution, DistIter, DistMap};
+#[cfg(feature = "alloc")]
+pub use self::distribution::DistString;
+pub use self::float::{Open01, OpenClosed01};
+pub use self::other::Alphanumeric;
+pub use self::slice::Slice;
+#[doc(inline)]
+pub use self::uniform::Uniform;
+#[cfg(feature = "alloc")]
+pub use self::weighted_index::{WeightedError, WeightedIndex};
+#[allow(unused)]
+use crate::Rng;
/// A generic random value distribution, implemented for many primitive types.
/// Usually generates values with a numerically uniform distribution, and with a
@@ -278,7 +158,13 @@ where
/// * Tuples (up to 12 elements): each element is generated sequentially.
/// * Arrays (up to 32 elements): each element is generated sequentially;
/// see also [`Rng::fill`] which supports arbitrary array length for integer
-/// types and tends to be faster for `u32` and smaller types.
+/// and float types and tends to be faster for `u32` and smaller types.
+/// When using `rustc` ≥ 1.51, enable the `min_const_gen` feature to support
+/// arrays larger than 32 elements.
+/// Note that [`Rng::fill`] and `Standard`'s array support are *not* equivalent:
+/// the former is optimised for integer types (using fewer RNG calls for
+/// element types smaller than the RNG word size), while the latter supports
+/// any element type supported by `Standard`.
/// * `Option<T>` first generates a `bool`, and if true generates and returns
/// `Some(value)` where `value: T`, otherwise returning `None`.
///
@@ -328,45 +214,5 @@ where
///
/// [`Uniform`]: uniform::Uniform
#[derive(Clone, Copy, Debug)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Standard;
-
-
-#[cfg(test)]
-mod tests {
- use super::{Distribution, Uniform};
- use crate::Rng;
-
- #[test]
- fn test_distributions_iter() {
- use crate::distributions::Open01;
- let mut rng = crate::test::rng(210);
- let distr = Open01;
- let mut iter = Distribution::<f32>::sample_iter(distr, &mut rng);
- let mut sum: f32 = 0.;
- for _ in 0..100 {
- sum += iter.next().unwrap();
- }
- assert!(0. < sum && sum < 100.);
- }
-
- #[test]
- fn test_make_an_iter() {
- fn ten_dice_rolls_other_than_five<'a, R: Rng>(
- rng: &'a mut R,
- ) -> impl Iterator<Item = i32> + 'a {
- Uniform::new_inclusive(1, 6)
- .sample_iter(rng)
- .filter(|x| *x != 5)
- .take(10)
- }
-
- let mut rng = crate::test::rng(211);
- let mut count = 0;
- for val in ten_dice_rolls_other_than_five(&mut rng) {
- assert!(val >= 1 && val <= 6 && val != 5);
- count += 1;
- }
- assert_eq!(count, 10);
- }
-}
diff --git a/src/distributions/other.rs b/src/distributions/other.rs
index f62fe59..03802a7 100644
--- a/src/distributions/other.rs
+++ b/src/distributions/other.rs
@@ -10,12 +10,19 @@
use core::char;
use core::num::Wrapping;
+#[cfg(feature = "alloc")]
+use alloc::string::String;
use crate::distributions::{Distribution, Standard, Uniform};
+#[cfg(feature = "alloc")]
+use crate::distributions::DistString;
use crate::Rng;
#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};
+#[cfg(feature = "min_const_gen")]
+use core::mem::{self, MaybeUninit};
+
// ----- Sampling distributions -----
@@ -25,19 +32,22 @@ use serde::{Serialize, Deserialize};
/// # Example
///
/// ```
-/// use std::iter;
/// use rand::{Rng, thread_rng};
/// use rand::distributions::Alphanumeric;
///
/// let mut rng = thread_rng();
-/// let chars: String = iter::repeat(())
-/// .map(|()| rng.sample(Alphanumeric))
-/// .map(char::from)
-/// .take(7)
-/// .collect();
+/// let chars: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
/// println!("Random chars: {}", chars);
/// ```
///
+/// The [`DistString`] trait provides an easier method of generating
+/// a random `String`, and offers more efficient allocation:
+/// ```
+/// use rand::distributions::{Alphanumeric, DistString};
+/// let string = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
+/// println!("Random string: {}", string);
+/// ```
+///
/// # Passwords
///
/// Users sometimes ask whether it is safe to use a string of random characters
@@ -54,7 +64,7 @@ use serde::{Serialize, Deserialize};
///
/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength)
/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware)
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Alphanumeric;
@@ -82,6 +92,19 @@ impl Distribution<char> for Standard {
}
}
+/// Note: the `String` is potentially left with excess capacity; optionally the
+/// user may call `string.shrink_to_fit()` afterwards.
+#[cfg(feature = "alloc")]
+impl DistString for Standard {
+ fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, s: &mut String, len: usize) {
+ // A char is encoded with at most four bytes, thus this reservation is
+ // guaranteed to be sufficient. We do not shrink_to_fit afterwards so
+ // that repeated usage on the same `String` buffer does not reallocate.
+ s.reserve(4 * len);
+ s.extend(Distribution::<char>::sample_iter(self, rng).take(len));
+ }
+}
+
impl Distribution<u8> for Alphanumeric {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
const RANGE: u32 = 26 + 26 + 10;
@@ -101,6 +124,16 @@ impl Distribution<u8> for Alphanumeric {
}
}
+#[cfg(feature = "alloc")]
+impl DistString for Alphanumeric {
+ fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize) {
+ unsafe {
+ let v = string.as_mut_vec();
+ v.extend(self.sample_iter(rng).take(len));
+ }
+ }
+}
+
impl Distribution<bool> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
@@ -156,6 +189,24 @@ tuple_impl! {A, B, C, D, E, F, G, H, I, J}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L}
+#[cfg(feature = "min_const_gen")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "min_const_gen")))]
+impl<T, const N: usize> Distribution<[T; N]> for Standard
+where Standard: Distribution<T>
+{
+ #[inline]
+ fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; N] {
+ let mut buff: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
+
+ for elem in &mut buff {
+ *elem = MaybeUninit::new(_rng.gen());
+ }
+
+ unsafe { mem::transmute_copy::<_, _>(&buff) }
+ }
+}
+
+#[cfg(not(feature = "min_const_gen"))]
macro_rules! array_impl {
// recursive, given at least one type parameter:
{$n:expr, $t:ident, $($ts:ident,)*} => {
@@ -176,6 +227,7 @@ macro_rules! array_impl {
};
}
+#[cfg(not(feature = "min_const_gen"))]
array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
impl<T> Distribution<Option<T>> for Standard
@@ -228,7 +280,7 @@ mod tests {
.map(|()| rng.gen::<char>())
.take(1000)
.collect();
- assert!(word.len() != 0);
+ assert!(!word.is_empty());
}
#[test]
@@ -240,11 +292,11 @@ mod tests {
let mut incorrect = false;
for _ in 0..100 {
let c: char = rng.sample(Alphanumeric).into();
- incorrect |= !((c >= '0' && c <= '9') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') );
+ incorrect |= !(('0'..='9').contains(&c) ||
+ ('A'..='Z').contains(&c) ||
+ ('a'..='z').contains(&c) );
}
- assert!(incorrect == false);
+ assert!(!incorrect);
}
#[test]
diff --git a/src/distributions/slice.rs b/src/distributions/slice.rs
new file mode 100644
index 0000000..3302deb
--- /dev/null
+++ b/src/distributions/slice.rs
@@ -0,0 +1,117 @@
+// Copyright 2021 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::distributions::{Distribution, Uniform};
+
+/// A distribution to sample items uniformly from a slice.
+///
+/// [`Slice::new`] constructs a distribution referencing a slice and uniformly
+/// samples references from the items in the slice. It may do extra work up
+/// front to make sampling of multiple values faster; if only one sample from
+/// the slice is required, [`SliceRandom::choose`] can be more efficient.
+///
+/// Steps are taken to avoid bias which might be present in naive
+/// implementations; for example `slice[rng.gen() % slice.len()]` samples from
+/// the slice, but may be more likely to select numbers in the low range than
+/// other values.
+///
+/// This distribution samples with replacement; each sample is independent.
+/// Sampling without replacement requires state to be retained, and therefore
+/// cannot be handled by a distribution; you should instead consider methods
+/// on [`SliceRandom`], such as [`SliceRandom::choose_multiple`].
+///
+/// # Example
+///
+/// ```
+/// use rand::Rng;
+/// use rand::distributions::Slice;
+///
+/// let vowels = ['a', 'e', 'i', 'o', 'u'];
+/// let vowels_dist = Slice::new(&vowels).unwrap();
+/// let rng = rand::thread_rng();
+///
+/// // build a string of 10 vowels
+/// let vowel_string: String = rng
+/// .sample_iter(&vowels_dist)
+/// .take(10)
+/// .collect();
+///
+/// println!("{}", vowel_string);
+/// assert_eq!(vowel_string.len(), 10);
+/// assert!(vowel_string.chars().all(|c| vowels.contains(&c)));
+/// ```
+///
+/// For a single sample, [`SliceRandom::choose`][crate::seq::SliceRandom::choose]
+/// may be preferred:
+///
+/// ```
+/// use rand::seq::SliceRandom;
+///
+/// let vowels = ['a', 'e', 'i', 'o', 'u'];
+/// let mut rng = rand::thread_rng();
+///
+/// println!("{}", vowels.choose(&mut rng).unwrap())
+/// ```
+///
+/// [`SliceRandom`]: crate::seq::SliceRandom
+/// [`SliceRandom::choose`]: crate::seq::SliceRandom::choose
+/// [`SliceRandom::choose_multiple`]: crate::seq::SliceRandom::choose_multiple
+#[derive(Debug, Clone, Copy)]
+pub struct Slice<'a, T> {
+ slice: &'a [T],
+ range: Uniform<usize>,
+}
+
+impl<'a, T> Slice<'a, T> {
+ /// Create a new `Slice` instance which samples uniformly from the slice.
+ /// Returns `Err` if the slice is empty.
+ pub fn new(slice: &'a [T]) -> Result<Self, EmptySlice> {
+ match slice.len() {
+ 0 => Err(EmptySlice),
+ len => Ok(Self {
+ slice,
+ range: Uniform::new(0, len),
+ }),
+ }
+ }
+}
+
+impl<'a, T> Distribution<&'a T> for Slice<'a, T> {
+ fn sample<R: crate::Rng + ?Sized>(&self, rng: &mut R) -> &'a T {
+ let idx = self.range.sample(rng);
+
+ debug_assert!(
+ idx < self.slice.len(),
+ "Uniform::new(0, {}) somehow returned {}",
+ self.slice.len(),
+ idx
+ );
+
+ // Safety: at construction time, it was ensured that the slice was
+ // non-empty, and that the `Uniform` range produces values in range
+ // for the slice
+ unsafe { self.slice.get_unchecked(idx) }
+ }
+}
+
+/// Error type indicating that a [`Slice`] distribution was improperly
+/// constructed with an empty slice.
+#[derive(Debug, Clone, Copy)]
+pub struct EmptySlice;
+
+impl core::fmt::Display for EmptySlice {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ write!(
+ f,
+ "Tried to create a `distributions::Slice` with an empty slice"
+ )
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for EmptySlice {}
diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs
index e4a6407..261357b 100644
--- a/src/distributions/uniform.rs
+++ b/src/distributions/uniform.rs
@@ -80,7 +80,10 @@
//! where B1: SampleBorrow<Self::X> + Sized,
//! B2: SampleBorrow<Self::X> + Sized
//! {
-//! UniformSampler::new(low, high)
+//! UniformMyF32(UniformFloat::<f32>::new_inclusive(
+//! low.borrow().0,
+//! high.borrow().0,
+//! ))
//! }
//! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
//! MyF32(self.0.sample(rng))
@@ -103,8 +106,7 @@
//! [`UniformDuration`]: crate::distributions::uniform::UniformDuration
//! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow
-#[cfg(not(feature = "std"))] use core::time::Duration;
-#[cfg(feature = "std")] use std::time::Duration;
+use core::time::Duration;
use core::ops::{Range, RangeInclusive};
use crate::distributions::float::IntoFloat;
@@ -158,7 +160,7 @@ use serde::{Serialize, Deserialize};
/// println!("{}", sum);
/// ```
///
-/// For a single sample, [`Rng::gen_range`] may be prefered:
+/// For a single sample, [`Rng::gen_range`] may be preferred:
///
/// ```
/// use rand::Rng;
@@ -170,8 +172,10 @@ use serde::{Serialize, Deserialize};
/// [`new`]: Uniform::new
/// [`new_inclusive`]: Uniform::new_inclusive
/// [`Rng::gen_range`]: Rng::gen_range
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", serde(bound(serialize = "X::Sampler: Serialize")))]
+#[cfg_attr(feature = "serde1", serde(bound(deserialize = "X::Sampler: Deserialize<'de>")))]
pub struct Uniform<X: SampleUniform>(X::Sampler);
impl<X: SampleUniform> Uniform<X> {
@@ -414,7 +418,7 @@ impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> {
/// An alternative to using a modulus is widening multiply: After a widening
/// multiply by `range`, the result is in the high word. Then comparing the low
/// word against `zone` makes sure our distribution is uniform.
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct UniformInt<X> {
low: X,
@@ -556,7 +560,6 @@ uniform_int_impl! { i8, u8, u32 }
uniform_int_impl! { i16, u16, u32 }
uniform_int_impl! { i32, u32, u32 }
uniform_int_impl! { i64, u64, u64 }
-#[cfg(not(target_os = "emscripten"))]
uniform_int_impl! { i128, u128, u128 }
uniform_int_impl! { isize, usize, usize }
uniform_int_impl! { u8, u8, u32 }
@@ -564,7 +567,6 @@ uniform_int_impl! { u16, u16, u32 }
uniform_int_impl! { u32, u32, u32 }
uniform_int_impl! { u64, u64, u64 }
uniform_int_impl! { usize, usize, usize }
-#[cfg(not(target_os = "emscripten"))]
uniform_int_impl! { u128, u128, u128 }
#[cfg(feature = "simd_support")]
@@ -804,7 +806,7 @@ impl UniformSampler for UniformChar {
/// [`new`]: UniformSampler::new
/// [`new_inclusive`]: UniformSampler::new_inclusive
/// [`Standard`]: crate::distributions::Standard
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct UniformFloat<X> {
low: X,
@@ -827,16 +829,21 @@ macro_rules! uniform_float_impl {
{
let low = *low_b.borrow();
let high = *high_b.borrow();
- assert!(low.all_lt(high), "Uniform::new called with `low >= high`");
- assert!(
- low.all_finite() && high.all_finite(),
- "Uniform::new called with non-finite boundaries"
+ debug_assert!(
+ low.all_finite(),
+ "Uniform::new called with `low` non-finite."
+ );
+ debug_assert!(
+ high.all_finite(),
+ "Uniform::new called with `high` non-finite."
);
+ assert!(low.all_lt(high), "Uniform::new called with `low >= high`");
let max_rand = <$ty>::splat(
(::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0,
);
let mut scale = high - low;
+ assert!(scale.all_finite(), "Uniform::new: range overflow");
loop {
let mask = (scale * max_rand + low).ge_mask(high);
@@ -858,19 +865,24 @@ macro_rules! uniform_float_impl {
{
let low = *low_b.borrow();
let high = *high_b.borrow();
+ debug_assert!(
+ low.all_finite(),
+ "Uniform::new_inclusive called with `low` non-finite."
+ );
+ debug_assert!(
+ high.all_finite(),
+ "Uniform::new_inclusive called with `high` non-finite."
+ );
assert!(
low.all_le(high),
"Uniform::new_inclusive called with `low > high`"
);
- assert!(
- low.all_finite() && high.all_finite(),
- "Uniform::new_inclusive called with non-finite boundaries"
- );
let max_rand = <$ty>::splat(
(::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0,
);
let mut scale = (high - low) / max_rand;
+ assert!(scale.all_finite(), "Uniform::new_inclusive: range overflow");
loop {
let mask = (scale * max_rand + low).gt_mask(high);
@@ -909,11 +921,20 @@ macro_rules! uniform_float_impl {
{
let low = *low_b.borrow();
let high = *high_b.borrow();
+ debug_assert!(
+ low.all_finite(),
+ "UniformSampler::sample_single called with `low` non-finite."
+ );
+ debug_assert!(
+ high.all_finite(),
+ "UniformSampler::sample_single called with `high` non-finite."
+ );
assert!(
low.all_lt(high),
"UniformSampler::sample_single: low >= high"
);
let mut scale = high - low;
+ assert!(scale.all_finite(), "UniformSampler::sample_single: range overflow");
loop {
// Generate a value in the range [1, 2)
@@ -1134,7 +1155,7 @@ mod tests {
#[test]
#[cfg(feature = "serde1")]
fn test_serialization_uniform_duration() {
- let distr = UniformDuration::new(std::time::Duration::from_secs(10), std::time::Duration::from_secs(60));
+ let distr = UniformDuration::new(Duration::from_secs(10), Duration::from_secs(60));
let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap();
assert_eq!(
distr.offset, de_distr.offset
@@ -1205,7 +1226,7 @@ mod tests {
#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_integers() {
- #[cfg(not(target_os = "emscripten"))] use core::{i128, u128};
+ use core::{i128, u128};
use core::{i16, i32, i64, i8, isize};
use core::{u16, u32, u64, u8, usize};
@@ -1273,9 +1294,7 @@ mod tests {
);)*
}};
}
- t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
- #[cfg(not(target_os = "emscripten"))]
- t!(i128, u128);
+ t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, i128, u128);
#[cfg(feature = "simd_support")]
{
@@ -1297,7 +1316,7 @@ mod tests {
let mut max = core::char::from_u32(0).unwrap();
for _ in 0..100 {
let c = rng.gen_range('A'..='Z');
- assert!('A' <= c && c <= 'Z');
+ assert!(('A'..='Z').contains(&c));
max = max.max(c);
}
assert_eq!(max, 'Z');
@@ -1328,12 +1347,8 @@ mod tests {
(-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)),
(-<$f_scalar>::from_bits(5), 0.0),
(-<$f_scalar>::from_bits(7), -0.0),
- (10.0, ::core::$f_scalar::MAX),
- (-100.0, ::core::$f_scalar::MAX),
- (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX),
- (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0),
- (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7),
- (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX),
+ (0.1 * ::core::$f_scalar::MAX, ::core::$f_scalar::MAX),
+ (-::core::$f_scalar::MAX * 0.2, ::core::$f_scalar::MAX * 0.7),
];
for &(low_scalar, high_scalar) in v.iter() {
for lane in 0..<$ty>::lanes() {
@@ -1413,6 +1428,19 @@ mod tests {
}
#[test]
+ #[should_panic]
+ fn test_float_overflow() {
+ let _ = Uniform::from(::core::f64::MIN..::core::f64::MAX);
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_float_overflow_single() {
+ let mut rng = crate::test::rng(252);
+ rng.gen_range(::core::f64::MIN..::core::f64::MAX);
+ }
+
+ #[test]
#[cfg(all(
feature = "std",
not(target_arch = "wasm32"),
@@ -1477,9 +1505,6 @@ mod tests {
#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_durations() {
- #[cfg(not(feature = "std"))] use core::time::Duration;
- #[cfg(feature = "std")] use std::time::Duration;
-
let mut rng = crate::test::rng(253);
let v = &[
@@ -1622,4 +1647,12 @@ mod tests {
],
);
}
+
+ #[test]
+ fn uniform_distributions_can_be_compared() {
+ assert_eq!(Uniform::new(1.0, 2.0), Uniform::new(1.0, 2.0));
+
+ // To cover UniformInt
+ assert_eq!(Uniform::new(1 as u32, 2 as u32), Uniform::new(1 as u32, 2 as u32));
+ }
}
diff --git a/src/distributions/utils.rs b/src/distributions/utils.rs
index e3bceb8..89da5fd 100644
--- a/src/distributions/utils.rs
+++ b/src/distributions/utils.rs
@@ -56,7 +56,6 @@ macro_rules! wmul_impl {
wmul_impl! { u8, u16, 8 }
wmul_impl! { u16, u32, 16 }
wmul_impl! { u32, u64, 32 }
-#[cfg(not(target_os = "emscripten"))]
wmul_impl! { u64, u128, 64 }
// This code is a translation of the __mulddi3 function in LLVM's
@@ -120,9 +119,6 @@ macro_rules! wmul_impl_large {
)+
};
}
-#[cfg(target_os = "emscripten")]
-wmul_impl_large! { u64, 32 }
-#[cfg(not(target_os = "emscripten"))]
wmul_impl_large! { u128, 64 }
macro_rules! wmul_impl_usize {
@@ -138,6 +134,8 @@ macro_rules! wmul_impl_usize {
}
};
}
+#[cfg(target_pointer_width = "16")]
+wmul_impl_usize! { u16 }
#[cfg(target_pointer_width = "32")]
wmul_impl_usize! { u32 }
#[cfg(target_pointer_width = "64")]
@@ -235,6 +233,8 @@ pub(crate) trait FloatSIMDUtils {
/// Implement functions available in std builds but missing from core primitives
#[cfg(not(std))]
+// False positive: We are following `std` here.
+#[allow(clippy::wrong_self_convention)]
pub(crate) trait Float: Sized {
fn is_nan(self) -> bool;
fn is_infinite(self) -> bool;
diff --git a/src/distributions/weighted.rs b/src/distributions/weighted.rs
index 6dd9273..846b9df 100644
--- a/src/distributions/weighted.rs
+++ b/src/distributions/weighted.rs
@@ -43,6 +43,5 @@ pub mod alias_method {
impl_weight!(f64, f32,);
impl_weight!(u8, u16, u32, u64, usize,);
impl_weight!(i8, i16, i32, i64, isize,);
- #[cfg(not(target_os = "emscripten"))]
impl_weight!(u128, i128,);
}
diff --git a/src/distributions/weighted_index.rs b/src/distributions/weighted_index.rs
index 07ba53e..8252b17 100644
--- a/src/distributions/weighted_index.rs
+++ b/src/distributions/weighted_index.rs
@@ -75,7 +75,7 @@ use serde::{Serialize, Deserialize};
///
/// [`Uniform<X>`]: crate::distributions::Uniform
/// [`RngCore`]: crate::RngCore
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub struct WeightedIndex<X: SampleUniform + PartialOrd> {
@@ -418,6 +418,11 @@ mod test {
2, 2, 1, 3, 2, 1, 3, 3, 2, 1,
]);
}
+
+ #[test]
+ fn weighted_index_distributions_can_be_compared() {
+ assert_eq!(WeightedIndex::new(&[1, 2]), WeightedIndex::new(&[1, 2]));
+ }
}
/// Error type returned from `WeightedIndex::new`.
@@ -439,15 +444,15 @@ pub enum WeightedError {
}
#[cfg(feature = "std")]
-impl ::std::error::Error for WeightedError {}
+impl std::error::Error for WeightedError {}
impl fmt::Display for WeightedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- WeightedError::NoItem => write!(f, "No weights provided."),
- WeightedError::InvalidWeight => write!(f, "A weight is invalid."),
- WeightedError::AllWeightsZero => write!(f, "All weights are zero."),
- WeightedError::TooMany => write!(f, "Too many weights (hit u32::MAX)"),
- }
+ f.write_str(match *self {
+ WeightedError::NoItem => "No weights provided in distribution",
+ WeightedError::InvalidWeight => "A weight is invalid in distribution",
+ WeightedError::AllWeightsZero => "All weights are zero in distribution",
+ WeightedError::TooMany => "Too many weights (hit u32::MAX) in distribution",
+ })
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 8bf7a9d..6d84718 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -50,7 +50,6 @@
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
#![no_std]
#![cfg_attr(feature = "simd_support", feature(stdsimd))]
-#![cfg_attr(feature = "nightly", feature(slice_partition_at_index))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(
clippy::float_cmp,
@@ -201,10 +200,10 @@ mod test {
#[test]
#[cfg(all(feature = "std", feature = "std_rng"))]
fn test_random() {
- // not sure how to test this aside from just getting some values
let _n: usize = random();
let _f: f32 = random();
let _o: Option<Option<i8>> = random();
+ #[allow(clippy::type_complexity)]
let _many: (
(),
(usize, isize, Option<(u32, (bool,))>),
diff --git a/src/rng.rs b/src/rng.rs
index bb977a5..79a9fbf 100644
--- a/src/rng.rs
+++ b/src/rng.rs
@@ -28,7 +28,7 @@ use core::{mem, slice};
/// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no
/// difference whether we use `R: Rng` or `R: RngCore`.
/// - The `+ ?Sized` un-bounding allows functions to be called directly on
-/// type-erased references; i.e. `foo(r)` where `r: &mut RngCore`. Without
+/// type-erased references; i.e. `foo(r)` where `r: &mut dyn RngCore`. Without
/// this it would be necessary to write `foo(&mut r)`.
///
/// An alternative pattern is possible: `fn foo<R: Rng>(rng: R)`. This has some
@@ -71,6 +71,8 @@ pub trait Rng: RngCore {
/// The `rng.gen()` method is able to generate arrays (up to 32 elements)
/// and tuples (up to 12 elements), so long as all element types can be
/// generated.
+ /// When using `rustc` ≥ 1.51, enable the `min_const_gen` feature to support
+ /// arrays larger than 32 elements.
///
/// For arrays of integers, especially for those with small element types
/// (< 64 bit), it will likely be faster to instead use [`Rng::fill`].
@@ -387,13 +389,20 @@ macro_rules! impl_fill {
}
}
-impl_fill!(u16, u32, u64, usize,);
-#[cfg(not(target_os = "emscripten"))]
-impl_fill!(u128);
-impl_fill!(i8, i16, i32, i64, isize,);
-#[cfg(not(target_os = "emscripten"))]
-impl_fill!(i128);
+impl_fill!(u16, u32, u64, usize, u128,);
+impl_fill!(i8, i16, i32, i64, isize, i128,);
+#[cfg_attr(doc_cfg, doc(cfg(feature = "min_const_gen")))]
+#[cfg(feature = "min_const_gen")]
+impl<T, const N: usize> Fill for [T; N]
+where [T]: Fill
+{
+ fn try_fill<R: Rng + ?Sized>(&mut self, rng: &mut R) -> Result<(), Error> {
+ self[..].try_fill(rng)
+ }
+}
+
+#[cfg(not(feature = "min_const_gen"))]
macro_rules! impl_fill_arrays {
($n:expr,) => {};
($n:expr, $N:ident) => {
@@ -413,8 +422,10 @@ macro_rules! impl_fill_arrays {
impl_fill_arrays!(!div $n / 2, $($NN,)*);
};
}
+#[cfg(not(feature = "min_const_gen"))]
#[rustfmt::skip]
impl_fill_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,);
+#[cfg(not(feature = "min_const_gen"))]
impl_fill_arrays!(!div 4096, N,N,N,N,N,N,N,);
#[cfg(test)]
@@ -487,15 +498,15 @@ mod test {
let mut r = rng(101);
for _ in 0..1000 {
let a = r.gen_range(-4711..17);
- assert!(a >= -4711 && a < 17);
- let a = r.gen_range(-3i8..42);
- assert!(a >= -3i8 && a < 42i8);
+ assert!((-4711..17).contains(&a));
+ let a: i8 = r.gen_range(-3..42);
+ assert!((-3..42).contains(&a));
let a: u16 = r.gen_range(10..99);
- assert!(a >= 10u16 && a < 99u16);
- let a = r.gen_range(-100i32..2000);
- assert!(a >= -100i32 && a < 2000i32);
+ assert!((10..99).contains(&a));
+ let a: i32 = r.gen_range(-100..2000);
+ assert!((-100..2000).contains(&a));
let a: u32 = r.gen_range(12..=24);
- assert!(a >= 12u32 && a <= 24u32);
+ assert!((12..=24).contains(&a));
assert_eq!(r.gen_range(0u32..1), 0u32);
assert_eq!(r.gen_range(-12i64..-11), -12i64);
@@ -508,9 +519,9 @@ mod test {
let mut r = rng(101);
for _ in 0..1000 {
let a = r.gen_range(-4.5..1.7);
- assert!(a >= -4.5 && a < 1.7);
+ assert!((-4.5..1.7).contains(&a));
let a = r.gen_range(-1.1..=-0.3);
- assert!(a >= -1.1 && a <= -0.3);
+ assert!((-1.1..=-0.3).contains(&a));
assert_eq!(r.gen_range(0.0f32..=0.0), 0.);
assert_eq!(r.gen_range(-11.0..=-11.0), -11.);
@@ -521,6 +532,7 @@ mod test {
#[test]
#[should_panic]
fn test_gen_range_panic_int() {
+ #![allow(clippy::reversed_empty_ranges)]
let mut r = rng(102);
r.gen_range(5..-2);
}
@@ -528,12 +540,15 @@ mod test {
#[test]
#[should_panic]
fn test_gen_range_panic_usize() {
+ #![allow(clippy::reversed_empty_ranges)]
let mut r = rng(103);
r.gen_range(5..2);
}
#[test]
fn test_gen_bool() {
+ #![allow(clippy::bool_assert_comparison)]
+
let mut r = rng(105);
for _ in 0..5 {
assert_eq!(r.gen_bool(0.0), false);
diff --git a/src/rngs/adapter/mod.rs b/src/rngs/adapter/mod.rs
index 22b7158..bd1d294 100644
--- a/src/rngs/adapter/mod.rs
+++ b/src/rngs/adapter/mod.rs
@@ -11,5 +11,6 @@
mod read;
mod reseeding;
+#[allow(deprecated)]
pub use self::read::{ReadError, ReadRng};
pub use self::reseeding::ReseedingRng;
diff --git a/src/rngs/adapter/read.rs b/src/rngs/adapter/read.rs
index 63b0dd0..25a9ca7 100644
--- a/src/rngs/adapter/read.rs
+++ b/src/rngs/adapter/read.rs
@@ -9,6 +9,8 @@
//! A wrapper around any Read to treat it as an RNG.
+#![allow(deprecated)]
+
use std::fmt;
use std::io::Read;
@@ -30,20 +32,10 @@ use rand_core::{impls, Error, RngCore};
/// have enough data, will only be reported through [`try_fill_bytes`].
/// The other [`RngCore`] methods will panic in case of an error.
///
-/// # Example
-///
-/// ```
-/// use rand::Rng;
-/// use rand::rngs::adapter::ReadRng;
-///
-/// let data = vec![1, 2, 3, 4, 5, 6, 7, 8];
-/// let mut rng = ReadRng::new(&data[..]);
-/// println!("{:x}", rng.gen::<u32>());
-/// ```
-///
/// [`OsRng`]: crate::rngs::OsRng
/// [`try_fill_bytes`]: RngCore::try_fill_bytes
#[derive(Debug)]
+#[deprecated(since="0.8.4", note="removal due to lack of usage")]
pub struct ReadRng<R> {
reader: R,
}
@@ -86,6 +78,7 @@ impl<R: Read> RngCore for ReadRng<R> {
/// `ReadRng` error type
#[derive(Debug)]
+#[deprecated(since="0.8.4")]
pub struct ReadError(std::io::Error);
impl fmt::Display for ReadError {
diff --git a/src/rngs/adapter/reseeding.rs b/src/rngs/adapter/reseeding.rs
index 1977cb3..ae3fcbb 100644
--- a/src/rngs/adapter/reseeding.rs
+++ b/src/rngs/adapter/reseeding.rs
@@ -22,10 +22,10 @@ use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
///
/// - On a manual call to [`reseed()`].
/// - After `clone()`, the clone will be reseeded on first use.
-/// - After a process is forked, the RNG in the child process is reseeded within
-/// the next few generated values, depending on the block size of the
-/// underlying PRNG. For ChaCha and Hc128 this is a maximum of
-/// 15 `u32` values before reseeding.
+/// - When a process is forked on UNIX, the RNGs in both the parent and child
+/// processes will be reseeded just before the next call to
+/// [`BlockRngCore::generate`], i.e. "soon". For ChaCha and Hc128 this is a
+/// maximum of fifteen `u32` values before reseeding.
/// - After the PRNG has generated a configurable number of random bytes.
///
/// # When should reseeding after a fixed number of generated bytes be used?
@@ -43,6 +43,12 @@ use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
/// Use [`ReseedingRng::new`] with a `threshold` of `0` to disable reseeding
/// after a fixed number of generated bytes.
///
+/// # Limitations
+///
+/// It is recommended that a `ReseedingRng` (including `ThreadRng`) not be used
+/// from a fork handler.
+/// Use `OsRng` or `getrandom`, or defer your use of the RNG until later.
+///
/// # Error handling
///
/// Although unlikely, reseeding the wrapped PRNG can fail. `ReseedingRng` will
@@ -310,8 +316,16 @@ mod fork {
pub fn register_fork_handler() {
static REGISTER: Once = Once::new();
- REGISTER.call_once(|| unsafe {
- libc::pthread_atfork(None, None, Some(fork_handler));
+ REGISTER.call_once(|| {
+ // Bump the counter before and after forking (see #1169):
+ let ret = unsafe { libc::pthread_atfork(
+ Some(fork_handler),
+ Some(fork_handler),
+ Some(fork_handler),
+ ) };
+ if ret != 0 {
+ panic!("libc::pthread_atfork failed with code {}", ret);
+ }
});
}
}
@@ -355,6 +369,8 @@ mod test {
#[test]
fn test_clone_reseeding() {
+ #![allow(clippy::redundant_clone)]
+
let mut zero = StepRng::new(0, 0);
let rng = Core::from_rng(&mut zero).unwrap();
let mut rng1 = ReseedingRng::new(rng, 32 * 4, zero);
diff --git a/src/rngs/std.rs b/src/rngs/std.rs
index 80f8433..cdae8fa 100644
--- a/src/rngs/std.rs
+++ b/src/rngs/std.rs
@@ -10,13 +10,9 @@
use crate::{CryptoRng, Error, RngCore, SeedableRng};
-#[cfg(all(any(test, feature = "std"), not(target_os = "emscripten")))]
pub(crate) use rand_chacha::ChaCha12Core as Core;
-#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))]
-pub(crate) use rand_hc::Hc128Core as Core;
-#[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha12Rng as Rng;
-#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng;
+use rand_chacha::ChaCha12Rng as Rng;
/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient
/// on the current platform, to be statistically strong and unpredictable
diff --git a/src/rngs/thread.rs b/src/rngs/thread.rs
index 552851f..baebb1d 100644
--- a/src/rngs/thread.rs
+++ b/src/rngs/thread.rs
@@ -33,15 +33,16 @@ use crate::{CryptoRng, Error, RngCore, SeedableRng};
// Number of generated bytes after which to reseed `ThreadRng`.
-// According to benchmarks, reseeding has a noticable impact with thresholds
+// According to benchmarks, reseeding has a noticeable impact with thresholds
// of 32 kB and less. We choose 64 kB to avoid significant overhead.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;
/// A reference to the thread-local generator
///
/// An instance can be obtained via [`thread_rng`] or via `ThreadRng::default()`.
-/// This handle is safe to use everywhere (including thread-local destructors)
-/// but cannot be passed between threads (is not `Send` or `Sync`).
+/// This handle is safe to use everywhere (including thread-local destructors),
+/// though it is recommended not to use inside a fork handler.
+/// The handle cannot be passed between threads (is not `Send` or `Sync`).
///
/// `ThreadRng` uses the same PRNG as [`StdRng`] for security and performance
/// and is automatically seeded from [`OsRng`].
@@ -59,7 +60,7 @@ const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
#[derive(Clone, Debug)]
pub struct ThreadRng {
- // Rc is explictly !Send and !Sync
+ // Rc is explicitly !Send and !Sync
rng: Rc<UnsafeCell<ReseedingRng<Core, OsRng>>>,
}
diff --git a/src/rngs/xoshiro256plusplus.rs b/src/rngs/xoshiro256plusplus.rs
index cd373c3..8ffb18b 100644
--- a/src/rngs/xoshiro256plusplus.rs
+++ b/src/rngs/xoshiro256plusplus.rs
@@ -11,9 +11,9 @@ use rand_core::impls::fill_bytes_via_next;
use rand_core::le::read_u64_into;
use rand_core::{SeedableRng, RngCore, Error};
-/// A xoshiro256** random number generator.
+/// A xoshiro256++ random number generator.
///
-/// The xoshiro256** algorithm is not suitable for cryptographic purposes, but
+/// The xoshiro256++ algorithm is not suitable for cryptographic purposes, but
/// is very fast and has excellent statistical properties.
///
/// The algorithm used here is translated from [the `xoshiro256plusplus.c`
diff --git a/src/seq/index.rs b/src/seq/index.rs
index 8b155e1..b38e464 100644
--- a/src/seq/index.rs
+++ b/src/seq/index.rs
@@ -16,11 +16,11 @@
use alloc::collections::BTreeSet;
#[cfg(feature = "std")] use std::collections::HashSet;
-#[cfg(feature = "alloc")]
-use crate::distributions::{uniform::SampleUniform, Distribution, Uniform};
#[cfg(feature = "std")]
use crate::distributions::WeightedError;
-use crate::Rng;
+
+#[cfg(feature = "alloc")]
+use crate::{Rng, distributions::{uniform::SampleUniform, Distribution, Uniform}};
#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};
@@ -380,7 +380,7 @@ where
#[cfg(not(feature = "nightly"))]
{
- use std::collections::BinaryHeap;
+ use alloc::collections::BinaryHeap;
// Partially sort the array such that the `amount` elements with the largest
// keys are first using a binary max heap.
@@ -630,7 +630,7 @@ mod test {
match v {
IndexVec::U32(mut indices) => {
assert_eq!(indices.len(), amount);
- indices.sort();
+ indices.sort_unstable();
indices.dedup();
assert_eq!(indices.len(), amount);
for &i in &indices {
@@ -668,10 +668,10 @@ mod test {
do_test(300, 80, &[31, 289, 248, 154, 5, 78, 19, 286]); // inplace
do_test(300, 180, &[31, 289, 248, 154, 5, 78, 19, 286]); // inplace
- do_test(1000_000, 8, &[
+ do_test(1_000_000, 8, &[
103717, 963485, 826422, 509101, 736394, 807035, 5327, 632573,
]); // floyd
- do_test(1000_000, 180, &[
+ do_test(1_000_000, 180, &[
103718, 963490, 826426, 509103, 736396, 807036, 5327, 632573,
]); // rejection
}
diff --git a/src/seq/mod.rs b/src/seq/mod.rs
index 4375fa1..069e9e6 100644
--- a/src/seq/mod.rs
+++ b/src/seq/mod.rs
@@ -991,8 +991,8 @@ mod test {
move_last(&mut arr, pos);
assert_eq!(arr[3], i);
}
- for i in 0..4 {
- assert_eq!(arr[i], i);
+ for (i, &a) in arr.iter().enumerate() {
+ assert_eq!(a, i);
}
counts[permutation] += 1;
}
@@ -1252,11 +1252,10 @@ mod test {
// Case 2: All of the weights are 0
let choices = [('a', 0), ('b', 0), ('c', 0)];
- let result = choices
+
+ assert_eq!(choices
.choose_multiple_weighted(&mut rng, 2, |item| item.1)
- .unwrap()
- .collect::<Vec<_>>();
- assert_eq!(result.len(), 2);
+ .unwrap().count(), 2);
// Case 3: Negative weights
let choices = [('a', -1), ('b', 1), ('c', 1)];
@@ -1269,11 +1268,9 @@ mod test {
// Case 4: Empty list
let choices = [];
- let result = choices
+ assert_eq!(choices
.choose_multiple_weighted(&mut rng, 0, |_: &()| 0)
- .unwrap()
- .collect::<Vec<_>>();
- assert_eq!(result.len(), 0);
+ .unwrap().count(), 0);
// Case 5: NaN weights
let choices = [('a', core::f64::NAN), ('b', 1.0), ('c', 1.0)];