Skip to content

Commit

Permalink
No usize except uniform (#1487)
Browse files Browse the repository at this point in the history
- Add UniformUsize
- Support ..end and ..=ub range syntax for unsigned ints
  • Loading branch information
dhardy authored Sep 9, 2024
1 parent 71c53be commit ef052ec
Show file tree
Hide file tree
Showing 13 changed files with 416 additions and 168 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.
- Rename `rand::distributions` to `rand::distr` (#1470)
- The `serde1` feature has been renamed `serde` (#1477)
- Mark `WeightError`, `PoissonError`, `BinomialError` as `#[non_exhaustive]` (#1480).
- Add `UniformUsize` and use to make `Uniform` for `usize` portable (#1487)
- Remove support for generating `isize` and `usize` values with `Standard`, `Uniform` and `Fill` and usage as a `WeightedAliasIndex` weight (#1487)
- Require `Clone` and `AsRef` bound for `SeedableRng::Seed`. (#1491)

## [0.9.0-alpha.1] - 2024-03-18
Expand Down
2 changes: 1 addition & 1 deletion benches/benches/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub fn bench(c: &mut Criterion) {
};
}

do_ty!(i8, i16, i32, i64, i128, isize);
do_ty!(i8, i16, i32, i64, i128);
do_ty!(f32, f64);
do_ty!(char);

Expand Down
1 change: 0 additions & 1 deletion rand_distr/src/weighted_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ impl_weight_for_int!(u64);
impl_weight_for_int!(u32);
impl_weight_for_int!(u16);
impl_weight_for_int!(u8);
impl_weight_for_int!(isize);
impl_weight_for_int!(i128);
impl_weight_for_int!(i64);
impl_weight_for_int!(i32);
Expand Down
36 changes: 3 additions & 33 deletions src/distr/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use core::arch::x86_64::__m512i;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::{__m128i, __m256i};
use core::num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16,
NonZeroU32, NonZeroU64, NonZeroU8,
};
#[cfg(feature = "simd_support")]
use core::simd::*;
Expand Down Expand Up @@ -63,20 +63,6 @@ impl Distribution<u128> for Standard {
}
}

impl Distribution<usize> for Standard {
#[inline]
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
rng.next_u32() as usize
}

#[inline]
#[cfg(target_pointer_width = "64")]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
rng.next_u64() as usize
}
}

macro_rules! impl_int_from_uint {
($ty:ty, $uty:ty) => {
impl Distribution<$ty> for Standard {
Expand All @@ -93,7 +79,6 @@ impl_int_from_uint! { i16, u16 }
impl_int_from_uint! { i32, u32 }
impl_int_from_uint! { i64, u64 }
impl_int_from_uint! { i128, u128 }
impl_int_from_uint! { isize, usize }

macro_rules! impl_nzint {
($ty:ty, $new:path) => {
Expand All @@ -114,14 +99,12 @@ impl_nzint!(NonZeroU16, NonZeroU16::new);
impl_nzint!(NonZeroU32, NonZeroU32::new);
impl_nzint!(NonZeroU64, NonZeroU64::new);
impl_nzint!(NonZeroU128, NonZeroU128::new);
impl_nzint!(NonZeroUsize, NonZeroUsize::new);

impl_nzint!(NonZeroI8, NonZeroI8::new);
impl_nzint!(NonZeroI16, NonZeroI16::new);
impl_nzint!(NonZeroI32, NonZeroI32::new);
impl_nzint!(NonZeroI64, NonZeroI64::new);
impl_nzint!(NonZeroI128, NonZeroI128::new);
impl_nzint!(NonZeroIsize, NonZeroIsize::new);

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
macro_rules! x86_intrinsic_impl {
Expand Down Expand Up @@ -163,7 +146,7 @@ macro_rules! simd_impl {
}

#[cfg(feature = "simd_support")]
simd_impl!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
simd_impl!(u8, i8, u16, i16, u32, i32, u64, i64);

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
x86_intrinsic_impl!(
Expand Down Expand Up @@ -191,14 +174,12 @@ mod tests {
fn test_integers() {
let mut rng = crate::test::rng(806);

rng.sample::<isize, _>(Standard);
rng.sample::<i8, _>(Standard);
rng.sample::<i16, _>(Standard);
rng.sample::<i32, _>(Standard);
rng.sample::<i64, _>(Standard);
rng.sample::<i128, _>(Standard);

rng.sample::<usize, _>(Standard);
rng.sample::<u8, _>(Standard);
rng.sample::<u16, _>(Standard);
rng.sample::<u32, _>(Standard);
Expand Down Expand Up @@ -239,17 +220,6 @@ mod tests {
111087889832015897993126088499035356354,
],
);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
test_samples(0usize, &[2220326409, 2575017975, 2018088303]);
#[cfg(target_pointer_width = "64")]
test_samples(
0usize,
&[
11059617991457472009,
16096616328739788143,
1487364411147516184,
],
);

test_samples(0i8, &[9, -9, 111]);
// Skip further i* types: they are simple reinterpretation of u* samples
Expand Down
35 changes: 3 additions & 32 deletions src/distr/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,11 @@

use core::num::NonZeroUsize;

use crate::distr::{Distribution, Uniform};
use crate::Rng;
use crate::distr::uniform::{UniformSampler, UniformUsize};
use crate::distr::Distribution;
#[cfg(feature = "alloc")]
use alloc::string::String;

#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
compile_error!("unsupported pointer width");

#[derive(Debug, Clone, Copy)]
enum UniformUsize {
U32(Uniform<u32>),
#[cfg(target_pointer_width = "64")]
U64(Uniform<u64>),
}

impl UniformUsize {
pub fn new(ubound: usize) -> Result<Self, super::uniform::Error> {
#[cfg(target_pointer_width = "64")]
if ubound > (u32::MAX as usize) {
return Uniform::new(0, ubound as u64).map(UniformUsize::U64);
}

Uniform::new(0, ubound as u32).map(UniformUsize::U32)
}

pub fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
match self {
UniformUsize::U32(uu) => uu.sample(rng) as usize,
#[cfg(target_pointer_width = "64")]
UniformUsize::U64(uu) => uu.sample(rng) as usize,
}
}
}

/// A distribution to sample items uniformly from a slice.
///
/// [`Slice::new`] constructs a distribution referencing a slice and uniformly
Expand Down Expand Up @@ -110,7 +81,7 @@ impl<'a, T> Slice<'a, T> {

Ok(Self {
slice,
range: UniformUsize::new(num_choices.get()).unwrap(),
range: UniformUsize::new(0, num_choices.get()).unwrap(),
num_choices,
})
}
Expand Down
45 changes: 37 additions & 8 deletions src/distr/uniform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,15 @@ pub use float::UniformFloat;
#[path = "uniform_int.rs"]
mod int;
#[doc(inline)]
pub use int::UniformInt;
pub use int::{UniformInt, UniformUsize};

#[path = "uniform_other.rs"]
mod other;
#[doc(inline)]
pub use other::{UniformChar, UniformDuration};

use core::fmt;
use core::ops::{Range, RangeInclusive};
use core::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive};

use crate::distr::Distribution;
use crate::{Rng, RngCore};
Expand Down Expand Up @@ -439,6 +439,41 @@ impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> {
}
}

macro_rules! impl_sample_range_u {
($t:ty) => {
impl SampleRange<$t> for RangeTo<$t> {
#[inline]
fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
<$t as SampleUniform>::Sampler::sample_single(0, self.end, rng)
}

#[inline]
fn is_empty(&self) -> bool {
0 == self.end
}
}

impl SampleRange<$t> for RangeToInclusive<$t> {
#[inline]
fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
<$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.end, rng)
}

#[inline]
fn is_empty(&self) -> bool {
false
}
}
};
}

impl_sample_range_u!(u8);
impl_sample_range_u!(u16);
impl_sample_range_u!(u32);
impl_sample_range_u!(u64);
impl_sample_range_u!(u128);
impl_sample_range_u!(usize);

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -530,12 +565,6 @@ mod tests {
assert_eq!(&buf, expected_multiple);
}

// We test on a sub-set of types; possibly we should do more.
// TODO: SIMD types

test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]);
test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]);

test_samples(
0f32,
1e-2f32,
Expand Down
Loading

0 comments on commit ef052ec

Please sign in to comment.