-
Notifications
You must be signed in to change notification settings - Fork 432
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
Optimise Rng::gen
on arrays?
#269
Comments
Perhaps |
That is how they work right now 😄. This issue asks the question if we can/should optimise the |
Actually The point is that you can write let mut x = [0u32; 32];
rng.fill(&mut x); |
Well, the current
... for I found a way to make // Specialized implementation:
impl<T> Distribution<T> for Standard where T: AsByteSliceMut+Default {
#[inline]
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> T {
let mut result: T = Default::default();
_rng.fill(&mut result);
result
}
} The problems are (1) that it conflicts with other implementations (even using If we can sort out the specialisation (when Rust supports it on stable, or alternatively negative trait bounds), and we restrict to small types ( // within array_impl macro:
// Specialized implementation:
impl<u8> Distribution<[u8; $n]> for Standard where [u8; $n]: AsByteSliceMut+Default {
#[inline]
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [u8; $n] {
let mut result: [u8; $n] = Default::default();
_rng.fill(&mut result);
result
}
} For now, I believe the best option is to do nothing (we can actually implement this instead of the generic |
I propose we close this with documentation only (provided in #812) since although using specialisation as above might be possible in the future, value-stability is important and this specialisation would yield different values for many types (with actual behaviour depending on the RNG). It appears that specialization will not be available in the near future: tracking issue. Would we want to make a value-breaking change when it becomes available? Also, any such implementation would have to make a fixed choice about which types to use the |
This might be a better option: diff --git a/src/distributions/other.rs b/src/distributions/other.rs
index 2295f79..883b332 100644
--- a/src/distributions/other.rs
+++ b/src/distributions/other.rs
@@ -137,10 +137,13 @@ macro_rules! array_impl {
{$n:expr, $t:ident, $($ts:ident,)*} => {
array_impl!{($n - 1), $($ts,)*}
- impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
+ impl<T> Distribution<[T; $n]> for Standard
+ where Standard: Distribution<T>, [T]: crate::AsByteSliceMut, T: Default {
#[inline]
- fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
- [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [T; $n] {
+ let mut a = Default::default();
+ rng.fill(&mut a);
+ a
}
}
}; The Of course, this is still a regression for types that don't implement |
This doesn't work for many types, e.g. |
Fair enough. However, it would be nice if |
Perhaps we got the design of pub trait Fill {
fn try_fill<R: Rng + ?Sized>(&mut self, rng: &mut R) -> Result<(), Error>;
} With that, we could implement support for float slices; also we could support Possibly this was not done because |
I agree that I would not worry too much about |
|
I noticed that
Rng::gen
andRng::fill
don't do the same thing on arrays and have different results when the element size is small:rng.gen()
essentially does[rng.gen(), rng.gen(), ..., rng.gen()]
rng.fill(&mut buf)
castsbuf
to&mut [u8]
then usesRngCore::fill_bytes
— more efficient, and only implemented for integer arrays/slicesWe likely want to keep the current behaviour for
rng.gen()
when the element type isf32
/f64
/complex types, but for integer types can we optimise to usefill_bytes
?The text was updated successfully, but these errors were encountered: