``` 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
```
```//! The random module provides methods of randomizing tensors.
//!
//! Here is an example:
//!
//! ```
//! use numeric::Tensor;
//! use numeric::random::RandomState;
//!
//! // Create a random state with seed 1234 (it has to be mutable)
//! let mut rs = RandomState::new(1234);
//!
//! let t = rs.uniform(0.0, 1.0, &[3, 3]);
//! println!("{}", t);
//! //  0.820987  0.93044 0.507159
//! //  0.603939  0.31157 0.383515
//! //  0.702227 0.346673 0.737954
//! // [Tensor<f64> of shape 3x3]
//! ```
use rand::{Rng, SeedableRng, StdRng};
use rand::distributions::range::SampleRange;
use num::traits::Float;
use std::f64;

use tensor::Tensor;
use traits::NumericTrait;
use math;

pub struct RandomState {
rng: StdRng,
}

impl RandomState {
/// Creates a new `RandomState` object with the given seed. The object needs to be captured
/// as mutable in order to draw samples from it (since its internal state changes).
pub fn new(seed: usize) -> RandomState {
let ss: &[_] = &[seed];
RandomState{rng: SeedableRng::from_seed(ss)}
}

/// Generates a tensor by independently drawing samples from a uniform distribution in the
/// range [`low`, `high`). This is appropriate for integer types as well.
pub fn uniform<T>(&mut self, low: T, high: T, shape: &[usize]) -> Tensor<T>
where T: NumericTrait + SampleRange {
let mut t = Tensor::zeros(shape);
{
let n = t.size();
let mut data = t.slice_mut();
for i in 0..n {
data[i] = self.rng.gen_range::<T>(low, high);
}
}
t
}

/// Generates a tensor by independently drawing samples from a standard normal.
pub fn normal<T>(&mut self, shape: &[usize]) -> Tensor<T>
where T: NumericTrait + SampleRange + Float {
let u1 = self.uniform(T::zero(), T::one(), shape);
let u2 = self.uniform(T::zero(), T::one(), shape);

let minustwo = Tensor::fscalar(-2.0);
let twopi = Tensor::fscalar(2.0 * f64::consts::PI);

math::sqrt(math::ln(u1) * &minustwo) * &math::cos(u2 * &twopi)
}
}
```