Skip to content

Commit ef052ec

Browse files
authored
No usize except uniform (#1487)
- Add UniformUsize - Support ..end and ..=ub range syntax for unsigned ints
1 parent 71c53be commit ef052ec

File tree

13 files changed

+416
-168
lines changed

13 files changed

+416
-168
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.
2121
- Rename `rand::distributions` to `rand::distr` (#1470)
2222
- The `serde1` feature has been renamed `serde` (#1477)
2323
- Mark `WeightError`, `PoissonError`, `BinomialError` as `#[non_exhaustive]` (#1480).
24+
- Add `UniformUsize` and use to make `Uniform` for `usize` portable (#1487)
25+
- Remove support for generating `isize` and `usize` values with `Standard`, `Uniform` and `Fill` and usage as a `WeightedAliasIndex` weight (#1487)
2426
- Require `Clone` and `AsRef` bound for `SeedableRng::Seed`. (#1491)
2527

2628
## [0.9.0-alpha.1] - 2024-03-18

benches/benches/standard.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn bench(c: &mut Criterion) {
4949
};
5050
}
5151

52-
do_ty!(i8, i16, i32, i64, i128, isize);
52+
do_ty!(i8, i16, i32, i64, i128);
5353
do_ty!(f32, f64);
5454
do_ty!(char);
5555

rand_distr/src/weighted_alias.rs

-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,6 @@ impl_weight_for_int!(u64);
365365
impl_weight_for_int!(u32);
366366
impl_weight_for_int!(u16);
367367
impl_weight_for_int!(u8);
368-
impl_weight_for_int!(isize);
369368
impl_weight_for_int!(i128);
370369
impl_weight_for_int!(i64);
371370
impl_weight_for_int!(i32);

src/distr/integer.rs

+3-33
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use core::arch::x86_64::__m512i;
1919
#[cfg(target_arch = "x86_64")]
2020
use core::arch::x86_64::{__m128i, __m256i};
2121
use core::num::{
22-
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
23-
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
22+
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16,
23+
NonZeroU32, NonZeroU64, NonZeroU8,
2424
};
2525
#[cfg(feature = "simd_support")]
2626
use core::simd::*;
@@ -63,20 +63,6 @@ impl Distribution<u128> for Standard {
6363
}
6464
}
6565

66-
impl Distribution<usize> for Standard {
67-
#[inline]
68-
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
69-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
70-
rng.next_u32() as usize
71-
}
72-
73-
#[inline]
74-
#[cfg(target_pointer_width = "64")]
75-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
76-
rng.next_u64() as usize
77-
}
78-
}
79-
8066
macro_rules! impl_int_from_uint {
8167
($ty:ty, $uty:ty) => {
8268
impl Distribution<$ty> for Standard {
@@ -93,7 +79,6 @@ impl_int_from_uint! { i16, u16 }
9379
impl_int_from_uint! { i32, u32 }
9480
impl_int_from_uint! { i64, u64 }
9581
impl_int_from_uint! { i128, u128 }
96-
impl_int_from_uint! { isize, usize }
9782

9883
macro_rules! impl_nzint {
9984
($ty:ty, $new:path) => {
@@ -114,14 +99,12 @@ impl_nzint!(NonZeroU16, NonZeroU16::new);
11499
impl_nzint!(NonZeroU32, NonZeroU32::new);
115100
impl_nzint!(NonZeroU64, NonZeroU64::new);
116101
impl_nzint!(NonZeroU128, NonZeroU128::new);
117-
impl_nzint!(NonZeroUsize, NonZeroUsize::new);
118102

119103
impl_nzint!(NonZeroI8, NonZeroI8::new);
120104
impl_nzint!(NonZeroI16, NonZeroI16::new);
121105
impl_nzint!(NonZeroI32, NonZeroI32::new);
122106
impl_nzint!(NonZeroI64, NonZeroI64::new);
123107
impl_nzint!(NonZeroI128, NonZeroI128::new);
124-
impl_nzint!(NonZeroIsize, NonZeroIsize::new);
125108

126109
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
127110
macro_rules! x86_intrinsic_impl {
@@ -163,7 +146,7 @@ macro_rules! simd_impl {
163146
}
164147

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

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

194-
rng.sample::<isize, _>(Standard);
195177
rng.sample::<i8, _>(Standard);
196178
rng.sample::<i16, _>(Standard);
197179
rng.sample::<i32, _>(Standard);
198180
rng.sample::<i64, _>(Standard);
199181
rng.sample::<i128, _>(Standard);
200182

201-
rng.sample::<usize, _>(Standard);
202183
rng.sample::<u8, _>(Standard);
203184
rng.sample::<u16, _>(Standard);
204185
rng.sample::<u32, _>(Standard);
@@ -239,17 +220,6 @@ mod tests {
239220
111087889832015897993126088499035356354,
240221
],
241222
);
242-
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
243-
test_samples(0usize, &[2220326409, 2575017975, 2018088303]);
244-
#[cfg(target_pointer_width = "64")]
245-
test_samples(
246-
0usize,
247-
&[
248-
11059617991457472009,
249-
16096616328739788143,
250-
1487364411147516184,
251-
],
252-
);
253223

254224
test_samples(0i8, &[9, -9, 111]);
255225
// Skip further i* types: they are simple reinterpretation of u* samples

src/distr/slice.rs

+3-32
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,11 @@
88

99
use core::num::NonZeroUsize;
1010

11-
use crate::distr::{Distribution, Uniform};
12-
use crate::Rng;
11+
use crate::distr::uniform::{UniformSampler, UniformUsize};
12+
use crate::distr::Distribution;
1313
#[cfg(feature = "alloc")]
1414
use alloc::string::String;
1515

16-
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
17-
compile_error!("unsupported pointer width");
18-
19-
#[derive(Debug, Clone, Copy)]
20-
enum UniformUsize {
21-
U32(Uniform<u32>),
22-
#[cfg(target_pointer_width = "64")]
23-
U64(Uniform<u64>),
24-
}
25-
26-
impl UniformUsize {
27-
pub fn new(ubound: usize) -> Result<Self, super::uniform::Error> {
28-
#[cfg(target_pointer_width = "64")]
29-
if ubound > (u32::MAX as usize) {
30-
return Uniform::new(0, ubound as u64).map(UniformUsize::U64);
31-
}
32-
33-
Uniform::new(0, ubound as u32).map(UniformUsize::U32)
34-
}
35-
36-
pub fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
37-
match self {
38-
UniformUsize::U32(uu) => uu.sample(rng) as usize,
39-
#[cfg(target_pointer_width = "64")]
40-
UniformUsize::U64(uu) => uu.sample(rng) as usize,
41-
}
42-
}
43-
}
44-
4516
/// A distribution to sample items uniformly from a slice.
4617
///
4718
/// [`Slice::new`] constructs a distribution referencing a slice and uniformly
@@ -110,7 +81,7 @@ impl<'a, T> Slice<'a, T> {
11081

11182
Ok(Self {
11283
slice,
113-
range: UniformUsize::new(num_choices.get()).unwrap(),
84+
range: UniformUsize::new(0, num_choices.get()).unwrap(),
11485
num_choices,
11586
})
11687
}

src/distr/uniform.rs

+37-8
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,15 @@ pub use float::UniformFloat;
112112
#[path = "uniform_int.rs"]
113113
mod int;
114114
#[doc(inline)]
115-
pub use int::UniformInt;
115+
pub use int::{UniformInt, UniformUsize};
116116

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

122122
use core::fmt;
123-
use core::ops::{Range, RangeInclusive};
123+
use core::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive};
124124

125125
use crate::distr::Distribution;
126126
use crate::{Rng, RngCore};
@@ -439,6 +439,41 @@ impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> {
439439
}
440440
}
441441

442+
macro_rules! impl_sample_range_u {
443+
($t:ty) => {
444+
impl SampleRange<$t> for RangeTo<$t> {
445+
#[inline]
446+
fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
447+
<$t as SampleUniform>::Sampler::sample_single(0, self.end, rng)
448+
}
449+
450+
#[inline]
451+
fn is_empty(&self) -> bool {
452+
0 == self.end
453+
}
454+
}
455+
456+
impl SampleRange<$t> for RangeToInclusive<$t> {
457+
#[inline]
458+
fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
459+
<$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.end, rng)
460+
}
461+
462+
#[inline]
463+
fn is_empty(&self) -> bool {
464+
false
465+
}
466+
}
467+
};
468+
}
469+
470+
impl_sample_range_u!(u8);
471+
impl_sample_range_u!(u16);
472+
impl_sample_range_u!(u32);
473+
impl_sample_range_u!(u64);
474+
impl_sample_range_u!(u128);
475+
impl_sample_range_u!(usize);
476+
442477
#[cfg(test)]
443478
mod tests {
444479
use super::*;
@@ -530,12 +565,6 @@ mod tests {
530565
assert_eq!(&buf, expected_multiple);
531566
}
532567

533-
// We test on a sub-set of types; possibly we should do more.
534-
// TODO: SIMD types
535-
536-
test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]);
537-
test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]);
538-
539568
test_samples(
540569
0f32,
541570
1e-2f32,

0 commit comments

Comments
 (0)