Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump MSRV to 1.51.0 #1246

Merged
merged 3 commits into from
Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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