Skip to content

Commit

Permalink
Merge pull request #1246 from rust-random/work6
Browse files Browse the repository at this point in the history
Bump MSRV to 1.51.0
  • Loading branch information
TheIronBorn authored Aug 14, 2022
2 parents 2569e9d + fbf06ff commit b736407
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 136 deletions.
14 changes: 4 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
env:
RUSTDOCFLAGS: --cfg doc_cfg
# --all builds all crates, but with default features for other crates (okay in this case)
run: cargo deadlinks --ignore-fragments -- --all --features nightly,serde1,getrandom,small_rng,min_const_gen
run: cargo deadlinks --ignore-fragments -- --all --features nightly,serde1,getrandom,small_rng

test:
runs-on: ${{ matrix.os }}
Expand All @@ -47,7 +47,7 @@ jobs:
# Test both windows-gnu and windows-msvc; use beta rust on one
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
toolchain: 1.36.0 # MSRV
toolchain: 1.51.0 # MSRV
- os: ubuntu-latest
deps: sudo apt-get update ; sudo apt install gcc-multilib
target: i686-unknown-linux-gnu
Expand Down Expand Up @@ -77,21 +77,15 @@ jobs:
cargo test --target ${{ matrix.target }} --all-features
cargo test --target ${{ matrix.target }} --benches --features=nightly
cargo test --target ${{ matrix.target }} --manifest-path rand_distr/Cargo.toml --benches
cargo test --target ${{ matrix.target }} --lib --tests --no-default-features --features min_const_gen
cargo test --target ${{ matrix.target }} --lib --tests --no-default-features
- name: Test rand
run: |
cargo test --target ${{ matrix.target }} --lib --tests --no-default-features
cargo build --target ${{ matrix.target }} --no-default-features --features alloc,getrandom,small_rng
cargo test --target ${{ matrix.target }} --lib --tests --no-default-features --features=alloc,getrandom,small_rng
cargo test --target ${{ matrix.target }} --examples
- name: Test rand (all stable features, non-MSRV)
if: ${{ matrix.toolchain != '1.36.0' }}
run: |
cargo test --target ${{ matrix.target }} --features=serde1,log,small_rng,min_const_gen
- name: Test rand (all stable features, MSRV)
if: ${{ matrix.toolchain == '1.36.0' }}
- name: Test rand (all stable features)
run: |
# const generics are not stable on 1.36.0
cargo test --target ${{ matrix.target }} --features=serde1,log,small_rng
- name: Test rand_core
run: |
Expand Down
6 changes: 1 addition & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ features = ["small_rng", "serde1"]
[features]
# Meta-features:
default = ["std", "std_rng"]
nightly = [] # enables performance optimizations requiring nightly rust
nightly = [] # some additions requiring nightly Rust
serde1 = ["serde", "rand_core/serde1"]

# Option (enabled by default): without "std" rand uses libcore; this option
Expand All @@ -50,10 +50,6 @@ 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",
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,9 @@ Optionally, the following dependencies can be enabled:
Additionally, these features configure Rand:

- `small_rng` enables inclusion of the `SmallRng` PRNG
- `nightly` enables some optimizations requiring nightly Rust
- `nightly` includes some additions 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
Expand Down
4 changes: 1 addition & 3 deletions src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,9 @@ use crate::Rng;
/// compound types where all component types are supported:
///
/// * Tuples (up to 12 elements): each element is generated sequentially.
/// * Arrays (up to 32 elements): each element is generated sequentially;
/// * Arrays: each element is generated sequentially;
/// see also [`Rng::fill`] which supports arbitrary array length for integer
/// 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
Expand Down
27 changes: 0 additions & 27 deletions src/distributions/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::Rng;

#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "min_const_gen")]
use core::mem::{self, MaybeUninit};
#[cfg(feature = "simd_support")]
use core::simd::*;
Expand Down Expand Up @@ -236,8 +235,6 @@ 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>
{
Expand All @@ -253,30 +250,6 @@ where Standard: Distribution<T>
}
}

#[cfg(not(feature = "min_const_gen"))]
macro_rules! array_impl {
// recursive, given at least one type parameter:
{$n:expr, $t:ident, $($ts:ident,)*} => {
array_impl!{($n - 1), $($ts,)*}

impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
#[inline]
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
[_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
}
}
};
// empty case:
{$n:expr,} => {
impl<T> Distribution<[T; $n]> for Standard {
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
}
};
}

#[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
where Standard: Distribution<T>
{
Expand Down
32 changes: 1 addition & 31 deletions src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,9 @@ pub trait Rng: RngCore {
///
/// # Arrays and tuples
///
/// The `rng.gen()` method is able to generate arrays (up to 32 elements)
/// The `rng.gen()` method is able to generate arrays
/// 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`].
Expand Down Expand Up @@ -392,8 +390,6 @@ macro_rules! impl_fill {
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
{
Expand All @@ -402,32 +398,6 @@ where [T]: Fill
}
}

#[cfg(not(feature = "min_const_gen"))]
macro_rules! impl_fill_arrays {
($n:expr,) => {};
($n:expr, $N:ident) => {
impl<T> Fill for [T; $n] where [T]: Fill {
fn try_fill<R: Rng + ?Sized>(&mut self, rng: &mut R) -> Result<(), Error> {
self[..].try_fill(rng)
}
}
};
($n:expr, $N:ident, $($NN:ident,)*) => {
impl_fill_arrays!($n, $N);
impl_fill_arrays!($n - 1, $($NN,)*);
};
(!div $n:expr,) => {};
(!div $n:expr, $N:ident, $($NN:ident,)*) => {
impl_fill_arrays!($n, $N);
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)]
mod test {
use super::*;
Expand Down
80 changes: 23 additions & 57 deletions src/seq/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,7 @@ where R: Rng + ?Sized {
/// sometimes be useful to have the indices themselves so this is provided as
/// an alternative.
///
/// This implementation uses `O(length + amount)` space and `O(length)` time
/// if the "nightly" feature is enabled, or `O(length)` space and
/// `O(length + amount * log length)` time otherwise.
/// This implementation uses `O(length + amount)` space and `O(length)` time.
///
/// Panics if `amount > length`.
#[cfg(feature = "std")]
Expand Down Expand Up @@ -300,9 +298,7 @@ where
///
/// This implementation uses the algorithm described by Efraimidis and Spirakis
/// in this paper: https://doi.org/10.1016/j.ipl.2005.11.003
/// It uses `O(length + amount)` space and `O(length)` time if the
/// "nightly" feature is enabled, or `O(length)` space and `O(length
/// + amount * log length)` time otherwise.
/// It uses `O(length + amount)` space and `O(length)` time.
///
/// Panics if `amount > length`.
#[cfg(feature = "std")]
Expand Down Expand Up @@ -347,63 +343,33 @@ where
}
impl<N> Eq for Element<N> {}

#[cfg(feature = "nightly")]
{
let mut candidates = Vec::with_capacity(length.as_usize());
let mut index = N::zero();
while index < length {
let weight = weight(index.as_usize()).into();
if !(weight >= 0.) {
return Err(WeightedError::InvalidWeight);
}

let key = rng.gen::<f64>().powf(1.0 / weight);
candidates.push(Element { index, key });

index += N::one();
let mut candidates = Vec::with_capacity(length.as_usize());
let mut index = N::zero();
while index < length {
let weight = weight(index.as_usize()).into();
if !(weight >= 0.) {
return Err(WeightedError::InvalidWeight);
}

// Partially sort the array to find the `amount` elements with the greatest
// keys. Do this by using `select_nth_unstable` to put the elements with
// the *smallest* keys at the beginning of the list in `O(n)` time, which
// provides equivalent information about the elements with the *greatest* keys.
let (_, mid, greater)
= candidates.select_nth_unstable(length.as_usize() - amount.as_usize());

let mut result: Vec<N> = Vec::with_capacity(amount.as_usize());
result.push(mid.index);
for element in greater {
result.push(element.index);
}
Ok(IndexVec::from(result))
}

#[cfg(not(feature = "nightly"))]
{
use alloc::collections::BinaryHeap;
let key = rng.gen::<f64>().powf(1.0 / weight);
candidates.push(Element { index, key });

// Partially sort the array such that the `amount` elements with the largest
// keys are first using a binary max heap.
let mut candidates = BinaryHeap::with_capacity(length.as_usize());
let mut index = N::zero();
while index < length {
let weight = weight(index.as_usize()).into();
if !(weight >= 0.) {
return Err(WeightedError::InvalidWeight);
}
index += N::one();
}

let key = rng.gen::<f64>().powf(1.0 / weight);
candidates.push(Element { index, key });
// Partially sort the array to find the `amount` elements with the greatest
// keys. Do this by using `select_nth_unstable` to put the elements with
// the *smallest* keys at the beginning of the list in `O(n)` time, which
// provides equivalent information about the elements with the *greatest* keys.
let (_, mid, greater)
= candidates.select_nth_unstable(length.as_usize() - amount.as_usize());

index += N::one();
}

let mut result: Vec<N> = Vec::with_capacity(amount.as_usize());
while result.len() < amount.as_usize() {
result.push(candidates.pop().unwrap().index);
}
Ok(IndexVec::from(result))
let mut result: Vec<N> = Vec::with_capacity(amount.as_usize());
result.push(mid.index);
for element in greater {
result.push(element.index);
}
Ok(IndexVec::from(result))
}

/// Randomly sample exactly `amount` indices from `0..length`, using Floyd's
Expand Down

0 comments on commit b736407

Please sign in to comment.