Skip to content

Commit 08c20bb

Browse files
committedJan 18, 2017
Add missing Debug implementation for librand structs
1 parent c8af93f commit 08c20bb

File tree

9 files changed

+275
-3
lines changed

9 files changed

+275
-3
lines changed
 

‎src/librand/chacha.rs

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
//! The ChaCha random number generator.
1212
13+
use core::fmt;
1314
use {Rand, Rng, SeedableRng};
1415

1516
const KEY_WORDS: usize = 8; // 8 words for the 256-bit key
@@ -32,6 +33,16 @@ pub struct ChaChaRng {
3233
index: usize, // Index into state
3334
}
3435

36+
impl fmt::Debug for ChaChaRng {
37+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38+
f.debug_struct("ChaChaRng")
39+
.field("buffer", &self.buffer.iter())
40+
.field("state", &self.state.iter())
41+
.field("index", &self.index)
42+
.finish()
43+
}
44+
}
45+
3546
static EMPTY: ChaChaRng = ChaChaRng {
3647
buffer: [0; STATE_WORDS],
3748
state: [0; STATE_WORDS],

‎src/librand/distributions/exponential.rs

+19
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
//! The exponential distribution.
1212
13+
use core::fmt;
14+
1315
#[cfg(not(test))] // only necessary for no_std
1416
use FloatMath;
1517

@@ -55,6 +57,14 @@ impl Rand for Exp1 {
5557
}
5658
}
5759

60+
impl fmt::Debug for Exp1 {
61+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62+
f.debug_tuple("Exp1")
63+
.field(&self.0)
64+
.finish()
65+
}
66+
}
67+
5868
/// The exponential distribution `Exp(lambda)`.
5969
///
6070
/// This distribution has density function: `f(x) = lambda *
@@ -79,13 +89,22 @@ impl Sample<f64> for Exp {
7989
self.ind_sample(rng)
8090
}
8191
}
92+
8293
impl IndependentSample<f64> for Exp {
8394
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
8495
let Exp1(n) = rng.gen::<Exp1>();
8596
n * self.lambda_inverse
8697
}
8798
}
8899

100+
impl fmt::Debug for Exp {
101+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102+
f.debug_struct("Exp")
103+
.field("lambda_inverse", &self.lambda_inverse)
104+
.finish()
105+
}
106+
}
107+
89108
#[cfg(test)]
90109
mod tests {
91110
use distributions::{IndependentSample, Sample};

‎src/librand/distributions/gamma.rs

+52
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
//! The Gamma and derived distributions.
1212
13+
use core::fmt;
14+
1315
use self::GammaRepr::*;
1416
use self::ChiSquaredRepr::*;
1517

@@ -44,6 +46,19 @@ pub struct Gamma {
4446
repr: GammaRepr,
4547
}
4648

49+
impl fmt::Debug for Gamma {
50+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51+
f.debug_struct("Gamma")
52+
.field("repr",
53+
&match self.repr {
54+
GammaRepr::Large(_) => "Large",
55+
GammaRepr::One(_) => "Exp",
56+
GammaRepr::Small(_) => "Small"
57+
})
58+
.finish()
59+
}
60+
}
61+
4762
enum GammaRepr {
4863
Large(GammaLargeShape),
4964
One(Exp),
@@ -182,6 +197,18 @@ pub struct ChiSquared {
182197
repr: ChiSquaredRepr,
183198
}
184199

200+
impl fmt::Debug for ChiSquared {
201+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202+
f.debug_struct("ChiSquared")
203+
.field("repr",
204+
&match self.repr {
205+
ChiSquaredRepr::DoFExactlyOne => "DoFExactlyOne",
206+
ChiSquaredRepr::DoFAnythingElse(_) => "DoFAnythingElse",
207+
})
208+
.finish()
209+
}
210+
}
211+
185212
enum ChiSquaredRepr {
186213
// k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
187214
// e.g. when alpha = 1/2 as it would be for this case, so special-
@@ -203,11 +230,13 @@ impl ChiSquared {
203230
ChiSquared { repr: repr }
204231
}
205232
}
233+
206234
impl Sample<f64> for ChiSquared {
207235
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
208236
self.ind_sample(rng)
209237
}
210238
}
239+
211240
impl IndependentSample<f64> for ChiSquared {
212241
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
213242
match self.repr {
@@ -248,17 +277,29 @@ impl FisherF {
248277
}
249278
}
250279
}
280+
251281
impl Sample<f64> for FisherF {
252282
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
253283
self.ind_sample(rng)
254284
}
255285
}
286+
256287
impl IndependentSample<f64> for FisherF {
257288
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
258289
self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
259290
}
260291
}
261292

293+
impl fmt::Debug for FisherF {
294+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
295+
f.debug_struct("FisherF")
296+
.field("numer", &self.numer)
297+
.field("denom", &self.denom)
298+
.field("dof_ratio", &self.dof_ratio)
299+
.finish()
300+
}
301+
}
302+
262303
/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
263304
/// freedom.
264305
pub struct StudentT {
@@ -277,18 +318,29 @@ impl StudentT {
277318
}
278319
}
279320
}
321+
280322
impl Sample<f64> for StudentT {
281323
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
282324
self.ind_sample(rng)
283325
}
284326
}
327+
285328
impl IndependentSample<f64> for StudentT {
286329
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
287330
let StandardNormal(norm) = rng.gen::<StandardNormal>();
288331
norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
289332
}
290333
}
291334

335+
impl fmt::Debug for StudentT {
336+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
337+
f.debug_struct("StudentT")
338+
.field("chi", &self.chi)
339+
.field("dof", &self.dof)
340+
.finish()
341+
}
342+
}
343+
292344
#[cfg(test)]
293345
mod tests {
294346
use distributions::{IndependentSample, Sample};

‎src/librand/distributions/mod.rs

+38
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
//! internally. The `IndependentSample` trait is for generating values
1818
//! that do not need to record state.
1919
20+
use core::fmt;
21+
2022
#[cfg(not(test))] // only necessary for no_std
2123
use core::num::Float;
2224

@@ -78,6 +80,12 @@ impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
7880
}
7981
}
8082

83+
impl<Sup> fmt::Debug for RandSample<Sup> {
84+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85+
f.pad("RandSample { .. }")
86+
}
87+
}
88+
8189
/// A value with a particular weight for use with `WeightedChoice`.
8290
pub struct Weighted<T> {
8391
/// The numerical weight of this item
@@ -86,6 +94,21 @@ pub struct Weighted<T> {
8694
pub item: T,
8795
}
8896

97+
impl<T> fmt::Debug for Weighted<T> {
98+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99+
f.pad("Weighted")
100+
}
101+
}
102+
103+
impl<T: fmt::Debug> fmt::Debug for Weighted<T> {
104+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105+
f.debug_struct("Weighted")
106+
.field("weight", &self.weight)
107+
.field("item", &self.item)
108+
.finish()
109+
}
110+
}
111+
89112
/// A distribution that selects from a finite collection of weighted items.
90113
///
91114
/// Each item has an associated weight that influences how likely it
@@ -189,6 +212,21 @@ impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
189212
}
190213
}
191214

215+
impl<'a, T> fmt::Debug for WeightedChoice<'a, T> {
216+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
217+
f.pad("WeightedChoice")
218+
}
219+
}
220+
221+
impl<'a, T: fmt::Debug> fmt::Debug for WeightedChoice<'a, T> {
222+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
223+
f.debug_struct("WeightedChoice")
224+
.field("items", &self.items)
225+
.field("weight_range", &self.weight_range)
226+
.finish()
227+
}
228+
}
229+
192230
mod ziggurat_tables;
193231

194232
/// Sample a random number using the Ziggurat method (specifically the

‎src/librand/distributions/normal.rs

+31
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
//! The normal and derived distributions.
1212
13+
use core::fmt;
14+
1315
#[cfg(not(test))] // only necessary for no_std
1416
use FloatMath;
1517

@@ -73,6 +75,14 @@ impl Rand for StandardNormal {
7375
}
7476
}
7577

78+
impl fmt::Debug for StandardNormal {
79+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80+
f.debug_tuple("StandardNormal")
81+
.field(&self.0)
82+
.finish()
83+
}
84+
}
85+
7686
/// The normal distribution `N(mean, std_dev**2)`.
7787
///
7888
/// This uses the ZIGNOR variant of the Ziggurat method, see
@@ -98,18 +108,29 @@ impl Normal {
98108
}
99109
}
100110
}
111+
101112
impl Sample<f64> for Normal {
102113
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
103114
self.ind_sample(rng)
104115
}
105116
}
117+
106118
impl IndependentSample<f64> for Normal {
107119
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
108120
let StandardNormal(n) = rng.gen::<StandardNormal>();
109121
self.mean + self.std_dev * n
110122
}
111123
}
112124

125+
impl fmt::Debug for Normal {
126+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127+
f.debug_struct("Normal")
128+
.field("mean", &self.mean)
129+
.field("std_dev", &self.std_dev)
130+
.finish()
131+
}
132+
}
133+
113134

114135
/// The log-normal distribution `ln N(mean, std_dev**2)`.
115136
///
@@ -132,17 +153,27 @@ impl LogNormal {
132153
LogNormal { norm: Normal::new(mean, std_dev) }
133154
}
134155
}
156+
135157
impl Sample<f64> for LogNormal {
136158
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
137159
self.ind_sample(rng)
138160
}
139161
}
162+
140163
impl IndependentSample<f64> for LogNormal {
141164
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
142165
self.norm.ind_sample(rng).exp()
143166
}
144167
}
145168

169+
impl fmt::Debug for LogNormal {
170+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171+
f.debug_struct("LogNormal")
172+
.field("norm", &self.norm)
173+
.finish()
174+
}
175+
}
176+
146177
#[cfg(test)]
147178
mod tests {
148179
use distributions::{IndependentSample, Sample};

‎src/librand/distributions/range.rs

+18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
// this is surprisingly complicated to be both generic & correct
1414

15+
use core::fmt;
1516
use core::marker::Sized;
1617
use Rng;
1718
use distributions::{IndependentSample, Sample};
@@ -50,12 +51,29 @@ impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
5051
self.ind_sample(rng)
5152
}
5253
}
54+
5355
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
5456
fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
5557
SampleRange::sample_range(self, rng)
5658
}
5759
}
5860

61+
impl<X> fmt::Debug for Range<X> {
62+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63+
f.pad("Range { .. }")
64+
}
65+
}
66+
67+
impl<X: fmt::Debug> fmt::Debug for Range<X> {
68+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69+
f.debug_struct("Range")
70+
.field("low", &self.low)
71+
.field("range", &self.range)
72+
.field("accept_zone", &self.accept_zone)
73+
.finish()
74+
}
75+
}
76+
5977
/// The helper trait for types that have a sensible way to sample
6078
/// uniformly between two values. This should not be used directly,
6179
/// and is only to facilitate `Range`.

‎src/librand/isaac.rs

+27
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
#![allow(non_camel_case_types)]
1414

15+
use core::fmt;
1516
use core::slice;
1617
use core::iter::repeat;
1718
use core::num::Wrapping as w;
@@ -44,6 +45,19 @@ pub struct IsaacRng {
4445
c: w32,
4546
}
4647

48+
impl fmt::Debug for IsaacRng {
49+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50+
f.debug_struct("IsaacRng")
51+
.field("cnt", &self.cnt)
52+
.field("rsl", &self.rsl.iter())
53+
.field("mem", &self.mem.iter())
54+
.field("a", &self.a)
55+
.field("b", &self.b)
56+
.field("c", &self.c)
57+
.finish()
58+
}
59+
}
60+
4761
static EMPTY: IsaacRng = IsaacRng {
4862
cnt: 0,
4963
rsl: [w(0); RAND_SIZE_USIZE],
@@ -322,6 +336,19 @@ pub struct Isaac64Rng {
322336
c: w64,
323337
}
324338

339+
impl fmt::Debug for Isaac64Rng {
340+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341+
f.debug_struct("Isaac64Rng")
342+
.field("cnt", &self.cnt)
343+
.field("rsl", &self.rsl.iter())
344+
.field("mem", &self.mem.iter())
345+
.field("a", &self.a)
346+
.field("b", &self.b)
347+
.field("c", &self.c)
348+
.finish()
349+
}
350+
}
351+
325352
static EMPTY_64: Isaac64Rng = Isaac64Rng {
326353
cnt: 0,
327354
rsl: [w(0); RAND_SIZE_64],

‎src/librand/lib.rs

+60-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
html_playground_url = "https://play.rust-lang.org/",
2525
test(attr(deny(warnings))))]
2626
#![deny(warnings)]
27+
#![deny(missing_debug_implementations)]
2728
#![no_std]
2829
#![unstable(feature = "rand",
2930
reason = "use `rand` from crates.io",
@@ -32,6 +33,7 @@
3233
#![feature(staged_api)]
3334
#![feature(step_by)]
3435
#![feature(custom_attribute)]
36+
#![feature(specialization)]
3537
#![allow(unused_attributes)]
3638

3739
#![cfg_attr(not(test), feature(core_float))] // only necessary for no_std
@@ -43,6 +45,7 @@
4345
#[macro_use]
4446
extern crate std;
4547

48+
use core::fmt;
4649
use core::f64;
4750
use core::intrinsics;
4851
use core::marker::PhantomData;
@@ -288,6 +291,20 @@ impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
288291
}
289292
}
290293

294+
impl<'a, T, R> fmt::Debug for Generator<'a, T, R> {
295+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
296+
f.pad("Generator { .. }")
297+
}
298+
}
299+
300+
impl<'a, T, R: fmt::Debug> fmt::Debug for Generator<'a, T, R> {
301+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
302+
f.debug_struct("Generator")
303+
.field("rng", &self.rng)
304+
.finish()
305+
}
306+
}
307+
291308
/// Iterator which will continuously generate random ascii characters.
292309
///
293310
/// This iterator is created via the `gen_ascii_chars` method on `Rng`.
@@ -306,6 +323,20 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {
306323
}
307324
}
308325

326+
impl<'a, R> fmt::Debug for AsciiGenerator<'a, R> {
327+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
328+
f.pad("AsciiGenerator { .. }")
329+
}
330+
}
331+
332+
impl<'a, R: fmt::Debug> fmt::Debug for AsciiGenerator<'a, R> {
333+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334+
f.debug_struct("AsciiGenerator")
335+
.field("rng", &self.rng)
336+
.finish()
337+
}
338+
}
339+
309340
/// A random number generator that can be explicitly seeded to produce
310341
/// the same stream of randomness multiple times.
311342
pub trait SeedableRng<Seed>: Rng {
@@ -326,7 +357,7 @@ pub trait SeedableRng<Seed>: Rng {
326357
/// [1]: Marsaglia, George (July 2003). ["Xorshift
327358
/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
328359
/// Statistical Software*. Vol. 8 (Issue 14).
329-
#[derive(Clone)]
360+
#[derive(Clone, Debug)]
330361
pub struct XorShiftRng {
331362
x: u32,
332363
y: u32,
@@ -415,6 +446,20 @@ impl Rand for XorShiftRng {
415446
/// `[0,1)`.
416447
pub struct Open01<F>(pub F);
417448

449+
impl<F> fmt::Debug for Open01<F> {
450+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
451+
f.pad("Open01 { .. }")
452+
}
453+
}
454+
455+
impl<F: fmt::Debug> fmt::Debug for Open01<F> {
456+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
457+
f.debug_tuple("Open01")
458+
.field(&self.0)
459+
.finish()
460+
}
461+
}
462+
418463
/// A wrapper for generating floating point numbers uniformly in the
419464
/// closed interval `[0,1]` (including both endpoints).
420465
///
@@ -423,6 +468,20 @@ pub struct Open01<F>(pub F);
423468
/// `[0,1)`.
424469
pub struct Closed01<F>(pub F);
425470

471+
impl<F> fmt::Debug for Closed01<F> {
472+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
473+
f.pad("Closed01 { .. }")
474+
}
475+
}
476+
477+
impl<F: fmt::Debug> fmt::Debug for Closed01<F> {
478+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
479+
f.debug_tuple("Closed01")
480+
.field(&self.0)
481+
.finish()
482+
}
483+
}
484+
426485
#[cfg(test)]
427486
mod test {
428487
use std::__rand as rand;

‎src/librand/reseeding.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! A wrapper around another RNG that reseeds it after it
1212
//! generates a certain number of random bytes.
1313
14+
use core::fmt;
1415
use {Rng, SeedableRng};
1516

1617
/// 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> {
5455
}
5556
}
5657

57-
5858
impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
5959
fn next_u32(&mut self) -> u32 {
6060
self.reseed_if_necessary();
@@ -95,6 +95,23 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
9595
}
9696
}
9797

98+
impl<R, Rsdr> fmt::Debug for ReseedingRng<R, Rsdr> {
99+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100+
f.pad("ReseedingRng { .. }")
101+
}
102+
}
103+
104+
impl<R: fmt::Debug, Rsdr: fmt::Debug> fmt::Debug for ReseedingRng<R, Rsdr> {
105+
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106+
f.debug_struct("ReseedingRng")
107+
.field("rng", &self.rng)
108+
.field("generation_threshold", &self.generation_threshold)
109+
.field("bytes_generated", &self.bytes_generated)
110+
.field("reseeder", &self.reseeder)
111+
.finish()
112+
}
113+
}
114+
98115
/// Something that can be used to reseed an RNG via `ReseedingRng`.
99116
pub trait Reseeder<R> {
100117
/// Reseed the given RNG.
@@ -103,7 +120,7 @@ pub trait Reseeder<R> {
103120

104121
/// Reseed an RNG using a `Default` instance. This reseeds by
105122
/// replacing the RNG with the result of a `Default::default` call.
106-
#[derive(Copy, Clone)]
123+
#[derive(Copy, Clone, Debug)]
107124
pub struct ReseedWithDefault;
108125

109126
impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {

0 commit comments

Comments
 (0)
Please sign in to comment.