xiangyun/rand/
mod.rs

1pub mod base;
2mod flag;
3
4use self::base::{BaseRand, RAND_MAX};
5use self::flag::Flag;
6use std::f64::consts::PI;
7
8pub enum Style {
9    Normal,
10    Pythagoras,
11    Gauss(u32),
12    BMgauss(f64, f64, bool),
13    Marsaglia(f64, f64, f64, bool),
14}
15
16pub enum JumpStyle {
17    Static,
18    Next,
19    Jump,
20    DoubleJump,
21}
22
23/// Solver is random number solver  
24/// Please do not assume that the fields are any type  
25pub struct Solver {
26    base: Vec<BaseRand>,
27    handle: Flag,
28    style: Style,
29    jump: JumpStyle,
30}
31
32impl Solver {
33    /// A lazy way to get a random solver
34    pub fn new() -> Self {
35        Solver {
36            base: vec![BaseRand::new()],
37            handle: Flag::On(0),
38            style: Style::Normal,
39            jump: JumpStyle::Static,
40        }
41    }
42
43    /// Insert a new base
44    pub fn new_multibase(mul: usize) -> Self {
45        let mut _base = Solver::new();
46        let mut _seed: Vec<usize> = Vec::new();
47        for _ in 0..mul {
48            _seed.push(_base.base());
49        }
50        for _ in 1..mul {
51            _base.new_base();
52        }
53        _base.multisrand(_seed);
54        _base.jump_style(JumpStyle::DoubleJump);
55        _base
56    }
57
58    /// Set random solver style
59    pub fn set_style(&mut self, style: Style) {
60        self.style = style;
61    }
62
63    /// Get handle base
64    pub fn get_base(&self, handle: usize) -> Option<BaseRand> {
65        if handle<self.base.len() {
66            Some(self.base[handle])
67        } else {
68            None
69        }   
70    }
71
72    pub fn set_base(&mut self, handle: usize, base: BaseRand) -> bool {
73        if handle<self.base.len() {
74            self.base[handle] = base;
75            return true;
76        }
77        false
78    }
79
80    /// Set the random seed
81    pub fn multisrand(&mut self, seed: Vec<usize>) {
82        for (i, item) in seed.iter().enumerate() {
83            let mut _base = BaseRand::new();
84            _base.srand(*item);
85            self.set_base(i, _base);
86        }
87    }
88
89    /// Lazy way to set the random seed
90    pub fn lazy_srand(&mut self) {
91        for i in 0..self.base.len() {
92            self.base[i].lazy_srand();
93        }
94    }
95
96    /// Get a random number
97    pub fn rand(&mut self) -> f64 {
98        match self.style {
99            Style::Normal => self.base() as f64,
100            Style::Pythagoras => pythagoras(self),
101            Style::Gauss(nsum) => gauss(self, nsum),
102            Style::BMgauss(u, v, phase) => {
103                let mut _u = u;
104                let mut _v = v;
105                let mut _phase = phase;
106                let _return = bmgauss(self,
107                                      &mut _u,
108                                      &mut _v,
109                                      &mut _phase);
110                self.style = Style::BMgauss(_u, _v, _phase);
111                _return
112            }
113            Style::Marsaglia(v1, v2, s, phase) => {
114                let mut _v1 = v1;
115                let mut _v2 = v2;
116                let mut _s = s;
117                let mut _phase = phase;
118                let _return = marsaglia(self,
119                                        &mut _v1,
120                                        &mut _v2,
121                                        &mut _s,
122                                        &mut _phase);
123                self.style = Style::Marsaglia(_v1,
124                                              _v2,
125                                              _s,
126                                              _phase);
127                _return
128            }
129        }
130    }
131
132    /// Get a random number for multibase
133    pub fn multirand(&mut self) -> f64 {
134        let _return = self.rand();
135        self.jump();
136        _return
137    }
138
139    pub fn base(&mut self) -> usize {
140        match self.handle {
141            Flag::On(e) => self.base[e].rand(),
142            _ => {
143                let mut _base = 0;
144                for i in 0..self.base.len() {
145                    _base += self.base[i].rand() / self.base.len();
146                }
147                _base
148            }
149        }
150    }
151
152    pub fn new_base(&mut self) {
153        self.base.push(BaseRand::new());
154    }
155
156    pub fn del_base(&mut self) -> Option<BaseRand> {
157        self.base.pop()
158    }
159
160    pub fn add_base(&mut self, base: BaseRand) {
161        self.base.push(base);
162    }
163
164    pub fn jump_style(&mut self, style: JumpStyle) {
165        self.jump = style;
166    }
167
168    pub fn jump(&mut self) {
169        if let Flag::On(e) = self.handle {           
170            match self.jump {
171                JumpStyle::Next => self.handle = Flag::On((e + 1) % self.base.len()),
172                JumpStyle::Jump => {
173                    let _jump = self.base();
174                    self.handle = Flag::On(_jump % self.base.len());
175                }
176                JumpStyle::DoubleJump => {
177                    let mut _gap = Flag::new();
178                    _gap.on(Some(self.base()));
179                    while _gap.is_on() {
180                        let _jump = self.base();
181                        self.handle = Flag::On(_jump % self.base.len());
182                        _gap.down();
183                    }
184                }
185                _ => {}
186            }
187        }
188    }
189}
190
191impl Default for Solver {
192    fn default() -> Self {
193        Self::new()
194    }
195}
196
197fn base64(base: &mut Solver,
198          base_offset: usize,
199          max_offset: usize) -> f64 {
200    (base.base() + base_offset) as f64 / (RAND_MAX + base_offset + max_offset) as f64
201}
202
203fn gauss(base: &mut Solver, nsum: u32) -> f64 {
204    let mut x = 0.0;
205    for _ in 0..nsum {
206        x += base64(base, 0, 0);
207    }
208    x -= nsum as f64 / 2.0;
209    x /= (nsum as f64 / 12.0).sqrt();
210    x
211}
212
213fn bmgauss(base: &mut Solver, u: &mut f64, v: &mut f64, phase: &mut bool) -> f64 {
214    if *phase {
215        *phase = false;
216        *u = base64(base, 1, 1);
217        *v = base64(base, 0, 1);
218        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).sin()
219    } else {
220        *phase = true;
221        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).cos()
222    }
223}
224
225fn marsaglia(base: &mut Solver,
226             v1: &mut f64,
227             v2: &mut f64,
228             s: &mut f64,
229             phase: &mut bool) -> f64 {
230    if *phase {
231        *phase = false;
232        let u1 = base64(base, 0, 0);
233        let u2 = base64(base, 0, 0);
234        *v1 = 2.0 * u1 - 1.0;
235        *v2 = 2.0 * u2 - 1.0;
236        *v1 * (-2.0 * (*s).log10() / (*s)).sqrt()
237    } else {
238        *phase = true;
239        *v2 * (-2.0 * (*s).log10() / (*s)).sqrt()
240    }
241}
242
243fn pythagoras(base: &mut Solver) -> f64 {
244    let a = base64(base, 0, 1);
245    let b = base64(base, 0, 1);
246    let c_sqr = a * a + b * b;
247    c_sqr.sqrt()
248}