Skip to content

Commit 4baff9d

Browse files
committed
Optimize u128 Standard distribution
1 parent 18d6fee commit 4baff9d

File tree

3 files changed

+50
-58
lines changed

3 files changed

+50
-58
lines changed

benches/distributions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(test)]
2-
#![cfg_attr(feature = "i128_support", feature(i128_type, i128))]
2+
#![cfg_attr(all(feature="i128_support", feature="nightly"), allow(stable_features))] // stable since 2018-03-27
3+
#![cfg_attr(all(feature="i128_support", feature="nightly"), feature(i128_type, i128))]
34

45
extern crate test;
56
extern crate rand;

benches/generators.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![feature(test)]
2+
#![cfg_attr(all(feature="i128_support", feature="nightly"), allow(stable_features))] // stable since 2018-03-27
3+
#![cfg_attr(all(feature="i128_support", feature="nightly"), feature(i128_type, i128))]
24

35
extern crate test;
46
extern crate rand;
@@ -74,6 +76,10 @@ gen_uint!(gen_u64_std, u64, StdRng::new());
7476
gen_uint!(gen_u64_small, u64, SmallRng::new());
7577
gen_uint!(gen_u64_os, u64, OsRng::new().unwrap());
7678

79+
#[cfg(feature = "i128_support")] gen_uint!(gen_u128_xorshift, u128, XorShiftRng::new());
80+
#[cfg(feature = "i128_support")] gen_uint!(gen_u128_hc128, u128, Hc128Rng::new());
81+
#[cfg(feature = "i128_support")] gen_uint!(gen_u128_os, u128, OsRng::new().unwrap());
82+
7783
// Do not test JitterRng like the others by running it RAND_BENCH_N times per,
7884
// measurement, because it is way too slow. Only run it once.
7985
#[bench]

src/distributions/integer.rs

Lines changed: 42 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,46 +13,52 @@
1313
use {Rng};
1414
use distributions::{Distribution, Standard};
1515

16-
impl Distribution<isize> for Standard {
17-
#[inline]
18-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> isize {
19-
rng.gen::<usize>() as isize
20-
}
21-
}
22-
23-
impl Distribution<i8> for Standard {
16+
impl Distribution<u8> for Standard {
2417
#[inline]
25-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i8 {
26-
rng.next_u32() as i8
18+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
19+
rng.next_u32() as u8
2720
}
2821
}
2922

30-
impl Distribution<i16> for Standard {
23+
impl Distribution<u16> for Standard {
3124
#[inline]
32-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i16 {
33-
rng.next_u32() as i16
25+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
26+
rng.next_u32() as u16
3427
}
3528
}
3629

37-
impl Distribution<i32> for Standard {
30+
impl Distribution<u32> for Standard {
3831
#[inline]
39-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i32 {
40-
rng.next_u32() as i32
32+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
33+
rng.next_u32()
4134
}
4235
}
4336

44-
impl Distribution<i64> for Standard {
37+
impl Distribution<u64> for Standard {
4538
#[inline]
46-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i64 {
47-
rng.next_u64() as i64
39+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
40+
rng.next_u64()
4841
}
4942
}
5043

5144
#[cfg(feature = "i128_support")]
52-
impl Distribution<i128> for Standard {
45+
impl Distribution<u128> for Standard {
5346
#[inline]
54-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i128 {
55-
rng.gen::<u128>() as i128
47+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
48+
if rng.bytes_per_round() < 128 {
49+
// Use LE; we explicitly generate one value before the next.
50+
let x = rng.next_u64() as u128;
51+
let y = rng.next_u64() as u128;
52+
(y << 64) | x
53+
} else {
54+
let mut val = 0u128;
55+
unsafe {
56+
let ptr = &mut val;
57+
let b_ptr = &mut *(ptr as *mut u128 as *mut [u8; 16]);
58+
rng.fill_bytes(b_ptr);
59+
}
60+
val.to_le()
61+
}
5662
}
5763
}
5864

@@ -70,44 +76,23 @@ impl Distribution<usize> for Standard {
7076
}
7177
}
7278

73-
impl Distribution<u8> for Standard {
74-
#[inline]
75-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
76-
rng.next_u32() as u8
79+
macro_rules! impl_int_from_uint {
80+
($ty:ty, $uty:ty) => {
81+
impl Distribution<$ty> for Standard {
82+
#[inline]
83+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
84+
rng.gen::<$uty>() as $ty
85+
}
86+
}
7787
}
7888
}
7989

80-
impl Distribution<u16> for Standard {
81-
#[inline]
82-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
83-
rng.next_u32() as u16
84-
}
85-
}
86-
87-
impl Distribution<u32> for Standard {
88-
#[inline]
89-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
90-
rng.next_u32()
91-
}
92-
}
93-
94-
impl Distribution<u64> for Standard {
95-
#[inline]
96-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
97-
rng.next_u64()
98-
}
99-
}
100-
101-
#[cfg(feature = "i128_support")]
102-
impl Distribution<u128> for Standard {
103-
#[inline]
104-
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
105-
// Use LE; we explicitly generate one value before the next.
106-
let x = rng.next_u64() as u128;
107-
let y = rng.next_u64() as u128;
108-
(y << 64) | x
109-
}
110-
}
90+
impl_int_from_uint! { i8, u8 }
91+
impl_int_from_uint! { i16, u16 }
92+
impl_int_from_uint! { i32, u32 }
93+
impl_int_from_uint! { i64, u64 }
94+
#[cfg(feature = "i128_support")] impl_int_from_uint! { i128, u128 }
95+
impl_int_from_uint! { isize, usize }
11196

11297

11398
#[cfg(test)]

0 commit comments

Comments
 (0)