Auto merge of #39156 - GuillaumeGomez:debug_librand, r=alexcrichton

Add missing Debug implementation for librand structs

Part of #31869.
This commit is contained in:
bors 2017-01-21 05:44:21 +00:00
commit b4cb1878f0
9 changed files with 227 additions and 3 deletions

View File

@ -10,6 +10,7 @@
//! The ChaCha random number generator.
use core::fmt;
use {Rand, Rng, SeedableRng};
const KEY_WORDS: usize = 8; // 8 words for the 256-bit key
@ -32,6 +33,16 @@ pub struct ChaChaRng {
index: usize, // Index into state
}
impl fmt::Debug for ChaChaRng {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ChaChaRng")
.field("buffer", &self.buffer.iter())
.field("state", &self.state.iter())
.field("index", &self.index)
.finish()
}
}
static EMPTY: ChaChaRng = ChaChaRng {
buffer: [0; STATE_WORDS],
state: [0; STATE_WORDS],

View File

@ -10,6 +10,8 @@
//! The exponential distribution.
use core::fmt;
#[cfg(not(test))] // only necessary for no_std
use FloatMath;
@ -55,6 +57,14 @@ impl Rand for Exp1 {
}
}
impl fmt::Debug for Exp1 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Exp1")
.field(&self.0)
.finish()
}
}
/// The exponential distribution `Exp(lambda)`.
///
/// This distribution has density function: `f(x) = lambda *
@ -79,6 +89,7 @@ impl Sample<f64> for Exp {
self.ind_sample(rng)
}
}
impl IndependentSample<f64> for Exp {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
let Exp1(n) = rng.gen::<Exp1>();
@ -86,6 +97,14 @@ impl IndependentSample<f64> for Exp {
}
}
impl fmt::Debug for Exp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Exp")
.field("lambda_inverse", &self.lambda_inverse)
.finish()
}
}
#[cfg(test)]
mod tests {
use distributions::{IndependentSample, Sample};

View File

@ -10,6 +10,8 @@
//! The Gamma and derived distributions.
use core::fmt;
use self::GammaRepr::*;
use self::ChiSquaredRepr::*;
@ -44,6 +46,19 @@ pub struct Gamma {
repr: GammaRepr,
}
impl fmt::Debug for Gamma {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Gamma")
.field("repr",
&match self.repr {
GammaRepr::Large(_) => "Large",
GammaRepr::One(_) => "Exp",
GammaRepr::Small(_) => "Small"
})
.finish()
}
}
enum GammaRepr {
Large(GammaLargeShape),
One(Exp),
@ -182,6 +197,18 @@ pub struct ChiSquared {
repr: ChiSquaredRepr,
}
impl fmt::Debug for ChiSquared {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ChiSquared")
.field("repr",
&match self.repr {
ChiSquaredRepr::DoFExactlyOne => "DoFExactlyOne",
ChiSquaredRepr::DoFAnythingElse(_) => "DoFAnythingElse",
})
.finish()
}
}
enum ChiSquaredRepr {
// k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
// e.g. when alpha = 1/2 as it would be for this case, so special-
@ -203,11 +230,13 @@ impl ChiSquared {
ChiSquared { repr: repr }
}
}
impl Sample<f64> for ChiSquared {
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
self.ind_sample(rng)
}
}
impl IndependentSample<f64> for ChiSquared {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
match self.repr {
@ -248,17 +277,29 @@ impl FisherF {
}
}
}
impl Sample<f64> for FisherF {
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
self.ind_sample(rng)
}
}
impl IndependentSample<f64> for FisherF {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
}
}
impl fmt::Debug for FisherF {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("FisherF")
.field("numer", &self.numer)
.field("denom", &self.denom)
.field("dof_ratio", &self.dof_ratio)
.finish()
}
}
/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
pub struct StudentT {
@ -277,11 +318,13 @@ impl StudentT {
}
}
}
impl Sample<f64> for StudentT {
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
self.ind_sample(rng)
}
}
impl IndependentSample<f64> for StudentT {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
let StandardNormal(norm) = rng.gen::<StandardNormal>();
@ -289,6 +332,15 @@ impl IndependentSample<f64> for StudentT {
}
}
impl fmt::Debug for StudentT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("StudentT")
.field("chi", &self.chi)
.field("dof", &self.dof)
.finish()
}
}
#[cfg(test)]
mod tests {
use distributions::{IndependentSample, Sample};

View File

@ -17,6 +17,8 @@
//! internally. The `IndependentSample` trait is for generating values
//! that do not need to record state.
use core::fmt;
#[cfg(not(test))] // only necessary for no_std
use core::num::Float;
@ -78,6 +80,12 @@ impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
}
}
impl<Sup> fmt::Debug for RandSample<Sup> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("RandSample { .. }")
}
}
/// A value with a particular weight for use with `WeightedChoice`.
pub struct Weighted<T> {
/// The numerical weight of this item
@ -86,6 +94,15 @@ pub struct Weighted<T> {
pub item: T,
}
impl<T: fmt::Debug> fmt::Debug for Weighted<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Weighted")
.field("weight", &self.weight)
.field("item", &self.item)
.finish()
}
}
/// A distribution that selects from a finite collection of weighted items.
///
/// Each item has an associated weight that influences how likely it
@ -189,6 +206,15 @@ impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
}
}
impl<'a, T: fmt::Debug> fmt::Debug for WeightedChoice<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("WeightedChoice")
.field("items", &self.items)
.field("weight_range", &self.weight_range)
.finish()
}
}
mod ziggurat_tables;
/// Sample a random number using the Ziggurat method (specifically the

View File

@ -10,6 +10,8 @@
//! The normal and derived distributions.
use core::fmt;
#[cfg(not(test))] // only necessary for no_std
use FloatMath;
@ -73,6 +75,14 @@ impl Rand for StandardNormal {
}
}
impl fmt::Debug for StandardNormal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("StandardNormal")
.field(&self.0)
.finish()
}
}
/// The normal distribution `N(mean, std_dev**2)`.
///
/// This uses the ZIGNOR variant of the Ziggurat method, see
@ -98,11 +108,13 @@ impl Normal {
}
}
}
impl Sample<f64> for Normal {
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
self.ind_sample(rng)
}
}
impl IndependentSample<f64> for Normal {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
let StandardNormal(n) = rng.gen::<StandardNormal>();
@ -110,6 +122,15 @@ impl IndependentSample<f64> for Normal {
}
}
impl fmt::Debug for Normal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Normal")
.field("mean", &self.mean)
.field("std_dev", &self.std_dev)
.finish()
}
}
/// The log-normal distribution `ln N(mean, std_dev**2)`.
///
@ -132,17 +153,27 @@ impl LogNormal {
LogNormal { norm: Normal::new(mean, std_dev) }
}
}
impl Sample<f64> for LogNormal {
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
self.ind_sample(rng)
}
}
impl IndependentSample<f64> for LogNormal {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
self.norm.ind_sample(rng).exp()
}
}
impl fmt::Debug for LogNormal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("LogNormal")
.field("norm", &self.norm)
.finish()
}
}
#[cfg(test)]
mod tests {
use distributions::{IndependentSample, Sample};

View File

@ -12,6 +12,7 @@
// this is surprisingly complicated to be both generic & correct
use core::fmt;
use core::marker::Sized;
use Rng;
use distributions::{IndependentSample, Sample};
@ -50,12 +51,23 @@ impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
self.ind_sample(rng)
}
}
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
SampleRange::sample_range(self, rng)
}
}
impl<X: fmt::Debug> fmt::Debug for Range<X> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Range")
.field("low", &self.low)
.field("range", &self.range)
.field("accept_zone", &self.accept_zone)
.finish()
}
}
/// The helper trait for types that have a sensible way to sample
/// uniformly between two values. This should not be used directly,
/// and is only to facilitate `Range`.

View File

@ -12,6 +12,7 @@
#![allow(non_camel_case_types)]
use core::fmt;
use core::slice;
use core::iter::repeat;
use core::num::Wrapping as w;
@ -44,6 +45,19 @@ pub struct IsaacRng {
c: w32,
}
impl fmt::Debug for IsaacRng {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("IsaacRng")
.field("cnt", &self.cnt)
.field("rsl", &self.rsl.iter())
.field("mem", &self.mem.iter())
.field("a", &self.a)
.field("b", &self.b)
.field("c", &self.c)
.finish()
}
}
static EMPTY: IsaacRng = IsaacRng {
cnt: 0,
rsl: [w(0); RAND_SIZE_USIZE],
@ -322,6 +336,19 @@ pub struct Isaac64Rng {
c: w64,
}
impl fmt::Debug for Isaac64Rng {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Isaac64Rng")
.field("cnt", &self.cnt)
.field("rsl", &self.rsl.iter())
.field("mem", &self.mem.iter())
.field("a", &self.a)
.field("b", &self.b)
.field("c", &self.c)
.finish()
}
}
static EMPTY_64: Isaac64Rng = Isaac64Rng {
cnt: 0,
rsl: [w(0); RAND_SIZE_64],

View File

@ -24,6 +24,7 @@
html_playground_url = "https://play.rust-lang.org/",
test(attr(deny(warnings))))]
#![deny(warnings)]
#![deny(missing_debug_implementations)]
#![no_std]
#![unstable(feature = "rand",
reason = "use `rand` from crates.io",
@ -32,6 +33,7 @@
#![feature(staged_api)]
#![feature(step_by)]
#![feature(custom_attribute)]
#![feature(specialization)]
#![allow(unused_attributes)]
#![cfg_attr(not(test), feature(core_float))] // only necessary for no_std
@ -43,6 +45,7 @@
#[macro_use]
extern crate std;
use core::fmt;
use core::f64;
use core::intrinsics;
use core::marker::PhantomData;
@ -288,6 +291,14 @@ impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
}
}
impl<'a, T, R: fmt::Debug> fmt::Debug for Generator<'a, T, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Generator")
.field("rng", &self.rng)
.finish()
}
}
/// Iterator which will continuously generate random ascii characters.
///
/// This iterator is created via the `gen_ascii_chars` method on `Rng`.
@ -306,6 +317,14 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {
}
}
impl<'a, R: fmt::Debug> fmt::Debug for AsciiGenerator<'a, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("AsciiGenerator")
.field("rng", &self.rng)
.finish()
}
}
/// A random number generator that can be explicitly seeded to produce
/// the same stream of randomness multiple times.
pub trait SeedableRng<Seed>: Rng {
@ -326,7 +345,7 @@ pub trait SeedableRng<Seed>: Rng {
/// [1]: Marsaglia, George (July 2003). ["Xorshift
/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
/// Statistical Software*. Vol. 8 (Issue 14).
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct XorShiftRng {
x: u32,
y: u32,
@ -415,6 +434,14 @@ impl Rand for XorShiftRng {
/// `[0,1)`.
pub struct Open01<F>(pub F);
impl<F: fmt::Debug> fmt::Debug for Open01<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Open01")
.field(&self.0)
.finish()
}
}
/// A wrapper for generating floating point numbers uniformly in the
/// closed interval `[0,1]` (including both endpoints).
///
@ -423,6 +450,14 @@ pub struct Open01<F>(pub F);
/// `[0,1)`.
pub struct Closed01<F>(pub F);
impl<F: fmt::Debug> fmt::Debug for Closed01<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Closed01")
.field(&self.0)
.finish()
}
}
#[cfg(test)]
mod test {
use std::__rand as rand;

View File

@ -11,6 +11,7 @@
//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.
use core::fmt;
use {Rng, SeedableRng};
/// How many bytes of entropy the underling RNG is allowed to generate
@ -54,7 +55,6 @@ impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
}
}
impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
fn next_u32(&mut self) -> u32 {
self.reseed_if_necessary();
@ -95,6 +95,17 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
}
}
impl<R: fmt::Debug, Rsdr: fmt::Debug> fmt::Debug for ReseedingRng<R, Rsdr> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ReseedingRng")
.field("rng", &self.rng)
.field("generation_threshold", &self.generation_threshold)
.field("bytes_generated", &self.bytes_generated)
.field("reseeder", &self.reseeder)
.finish()
}
}
/// Something that can be used to reseed an RNG via `ReseedingRng`.
pub trait Reseeder<R> {
/// Reseed the given RNG.
@ -103,7 +114,7 @@ pub trait Reseeder<R> {
/// Reseed an RNG using a `Default` instance. This reseeds by
/// replacing the RNG with the result of a `Default::default` call.
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub struct ReseedWithDefault;
impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {