peroxide/macros/
r_macro.rs

1//! R like macros
2//!
3//! # List
4//!
5//! * `c`
6//! * `seq`
7//! * `matrix`
8//! * `cbind`
9//! * `rbind`
10//! * `runif`
11//! * `rnorm`
12//! * `dnorm`
13//! * `pnorm`
14//! * `rt`
15//! * `dt`
16//! * `pt`
17//! * `lm`
18
19/// R like concatenate (Type: Vec\<f64\>)
20///
21/// # Examples
22/// ```
23/// #[macro_use]
24/// extern crate peroxide;
25/// use peroxide::fuga::*;
26///
27/// fn main() {
28///     let a = c!(1,2,3,4);
29///     let b = c![5,6,7,8];
30///     let c = c![a; b];
31///     println!("{:?}", a); // [1,2,3,4]
32///     println!("{:?}", b); // [5,6,7,8]
33///     println!("{:?}", c); // [1,2,3,4,5,6,7,8]
34/// }
35/// ```
36#[macro_export]
37macro_rules! c {
38    ( $( $x:expr ),* ) => {
39        {
40            let mut v: Vec<f64> = Vec::new();
41            let mut l: usize = 0;
42            $(
43                v.push($x as f64);
44                l += 1;
45            )*
46            v
47        }
48    };
49    ( $( $x:expr );* ) => {
50        {
51            let mut v: Vec<f64> = Vec::new();
52            $(
53                v.extend(&$x);
54            )*
55            v
56        }
57    }
58}
59
60/// R like seq macro
61///
62/// # Examples
63/// ```
64/// #[macro_use]
65/// extern crate peroxide;
66/// use peroxide::fuga::*;
67///
68/// fn main() {
69///     assert_eq!(seq!(1,10,1), c!(1,2,3,4,5,6,7,8,9,10));
70///     assert_eq!(seq!(1,10,1), seq!(1;10;1));
71/// }
72/// ```
73#[macro_export]
74macro_rules! seq {
75    ( $start:expr, $end:expr, $step:expr ) => {{
76        let s = $start as f64;
77        let e = $end as f64;
78        let step = $step as f64;
79
80        assert!(e > s);
81
82        let factor: f64 = (e - s) / step;
83        let l: usize = factor as usize + 1;
84        let mut v: Vec<f64> = Vec::new();
85
86        for i in 0..l {
87            v.push(s + step * (i as f64));
88        }
89        v
90    }};
91    ( $start:expr; $end:expr; $step:expr ) => {
92        seq!($start, $end, $step)
93    };
94}
95
96/// More R like Matrix constructor (Macro)
97///
98/// # Examples
99/// ```
100/// #[macro_use]
101/// extern crate peroxide;
102/// use peroxide::fuga::*;
103///
104/// fn main() {
105///     let a = matrix!(1;4;1, 2, 2, Row); // start;end;step
106///     let b = matrix(c!(1,2,3,4), 2, 2, Row);
107///     let c = matrix(vec![1,2,3,4], 2, 2, Row); // Normal function
108///     assert!(a == b && b == c);
109///
110///     let m = matrix!(0, 2, 2, Row);
111///     assert_eq!(m, zeros!(2, 2));
112/// }
113/// ```
114#[macro_export]
115macro_rules! matrix {
116    ( $start:expr;$end:expr;$step:expr, $row:expr, $col:expr, $shape:expr ) => {{
117        matrix(seq!($start, $end, $step), $row, $col, $shape)
118    }};
119
120    ( $value:expr, $row:expr, $col:expr, $shape:expr ) => {{
121        matrix(vec![$value as f64; $row * $col], $row, $col, $shape)
122    }};
123}
124
125/// R like cbind
126///
127/// # Examples
128/// ```
129/// #[macro_use]
130/// extern crate peroxide;
131/// use peroxide::fuga::*;
132///
133/// fn main() {
134///     let a = matrix!(1;4;1, 2, 2, Col);
135///     let b = matrix(c!(5,6),2, 1, Col);
136///     let c = matrix(c!(7,8),2,1,Col);
137///     assert_eq!(cbind!(a.clone(),b.clone()), matrix!(1;6;1,2,3,Col));
138///     assert_eq!(cbind!(a,b,c), matrix!(1;8;1, 2, 4, Col));
139/// }
140/// ```
141#[macro_export]
142macro_rules! cbind {
143    // Two
144    ( $x:expr, $y:expr ) => {
145        {
146            let mut temp = $x;
147            if temp.shape != Col {
148                temp = temp.change_shape();
149            }
150
151            let mut v: Vec<f64> = temp.data;
152            let mut c: usize = temp.col;
153            let r: usize = temp.row;
154
155            assert_eq!(r, $y.row);
156            v.extend(&$y.data.clone());
157            c += &$y.col;
158            matrix(v, r, c, Col)
159        }
160    };
161
162    // Multi
163    ( $x0:expr, $( $x: expr ),* ) => {
164        {
165            let mut temp0 = $x0;
166            if temp0.shape != Col {
167                temp0 = temp0.change_shape();
168            }
169            let mut v: Vec<f64> = temp0.data;
170            let mut c: usize = temp0.col;
171            let r: usize = temp0.row;
172            $(
173                let mut temp = $x;
174                if temp.shape != Col {
175                    temp = temp.change_shape();
176                }
177                // Must equal row
178                assert_eq!(r, temp.row);
179                // Add column
180                c += temp.col;
181                v.extend(&temp.data.clone());
182            )*
183            matrix(v, r, c, Col)
184        }
185    };
186}
187
188/// R like rbind
189///
190/// # Examples
191/// ```
192/// #[macro_use]
193/// extern crate peroxide;
194/// use peroxide::fuga::*;
195///
196/// fn main() {
197///     let a = matrix!(1;4;1, 2, 2, Row);
198///     let b = matrix(c!(5,6),1, 2, Row);
199///     let c = matrix(c!(7,8),1, 2, Row);
200///     assert_eq!(rbind!(a.clone(),b.clone()), matrix!(1;6;1, 3, 2, Row));
201///     assert_eq!(rbind!(a,b,c), matrix!(1;8;1, 4, 2, Row));
202/// }
203/// ```
204#[macro_export]
205macro_rules! rbind {
206    // Two
207    ( $x:expr, $y:expr ) => {
208        {
209            let mut temp = $x;
210            if temp.shape != Row {
211                temp = temp.change_shape();
212            }
213
214            let mut temp2 = $y;
215            if temp2.shape != Row {
216                temp2 = temp2.change_shape();
217            }
218
219            let mut v: Vec<f64> = temp.data;
220            let c: usize = temp.col;
221            let mut r: usize = temp.row;
222
223            assert_eq!(c, temp2.col);
224            v.extend(&temp2.data.clone());
225            r += temp2.row;
226            matrix(v, r, c, Row)
227        }
228    };
229
230    // Multi
231    ( $x0:expr, $( $x: expr ),* ) => {
232        {
233            let mut temp0 = $x0;
234            if temp0.shape != Row {
235                temp0 = temp0.change_shape();
236            }
237            let mut v: Vec<f64> = temp0.data;
238            let c: usize = temp0.col;
239            let mut r: usize = temp0.row;
240            $(
241                let mut temp = $x;
242                if temp.shape != Row {
243                    temp = temp.change_shape();
244                }
245                // Must equal row
246                assert_eq!(c, temp.col);
247                // Add column
248                r += temp.row;
249                v.extend(&temp.data.clone());
250            )*
251            matrix(v, r, c, Row)
252        }
253    };
254}
255
256/// R like random uniform
257///
258/// # Examples
259/// ```
260/// #[macro_use]
261/// extern crate peroxide;
262/// use peroxide::fuga::*;
263///
264/// fn main() {
265///     let a = runif!(5, -1, 1);
266///     println!("{:?}", a);
267///
268///     let b = runif!(5); // same as runif!(5,0,1)
269///     println!("{:?}", b);
270/// }
271/// ```
272#[macro_export]
273macro_rules! runif {
274    ( $x0:expr, $start:expr, $end:expr ) => {{
275        let n: usize = $x0;
276        let mut v = vec![0f64; n];
277
278        let mut rng = rand::rng();
279
280        for i in 0..n {
281            v[i] = rng.random_range($start as f64..=$end as f64);
282        }
283        v
284    }};
285
286    ( $x0:expr ) => {{
287        runif!($x0, 0, 1)
288    }};
289}
290
291/// R like random normal
292///
293/// # Examples
294/// ```
295/// #[macro_use]
296/// extern crate peroxide;
297/// use peroxide::fuga::*;
298///
299/// fn main() {
300///     let a = rnorm!(5, 2, 1);
301///     println!("{:?}", a);
302///
303///     let b = rnorm!(5); // same as rnorm!(5,0,1)
304///     println!("{:?}", b);
305/// }
306/// ```
307#[macro_export]
308macro_rules! rnorm {
309    ( $n:expr, $mean:expr, $sd:expr ) => {{
310        let n: usize = $n;
311        let normal = Normal($mean as f64, $sd as f64);
312        normal.sample(n)
313    }};
314
315    ( $n:expr ) => {{
316        rnorm!($n, 0, 1)
317    }};
318}
319
320/// R like `dnorm`
321///
322/// # Examples
323/// ```
324/// #[macro_use]
325/// extern crate peroxide;
326/// use peroxide::fuga::*;
327///
328/// fn main() {
329///     let a = dnorm!(2, 2, 1);
330///     println!("{:?}", a); // 0.3989422804014327
331///
332///     let b = dnorm!(0); // same as dnorm!(0,0,1)
333///     println!("{:?}", b);
334/// }
335/// ```
336#[macro_export]
337macro_rules! dnorm {
338    ( $x:expr, $mean: expr, $sd:expr ) => {{
339        let x = $x as f64;
340        let mean = $mean as f64;
341        let sd = $sd as f64;
342        let normal = Normal(mean, sd);
343        normal.pdf(x)
344    }};
345
346    ( $x:expr ) => {{
347        dnorm!($x, 0, 1)
348    }};
349}
350
351/// R like `pnorm`
352///
353/// # Examples
354/// ```
355/// #[macro_use]
356/// extern crate peroxide;
357/// use peroxide::fuga::*;
358///
359/// fn main() {
360///     let a = pnorm!(2, 2, 1);
361///     println!("{:?}", a); // 0.5
362///
363///     let b = pnorm!(0); // same as pnorm!(0,0,1)
364///     println!("{:?}", b);
365/// }
366/// ```
367#[macro_export]
368macro_rules! pnorm {
369    ( $x:expr, $mean:expr, $sd:expr ) => {{
370        let x = $x as f64;
371        let mean = $mean as f64;
372        let sd = $sd as f64;
373        let normal = Normal(mean, sd);
374        normal.cdf(x)
375    }};
376
377    ( $x:expr ) => {
378        pnorm!($x, 0, 1)
379    };
380}
381
382/// R like random Student's t
383///
384/// # Examples
385/// ```
386/// #[macro_use]
387/// extern crate peroxide;
388/// use peroxide::fuga::*;
389///
390/// fn main() {
391///     let a = rt!(5, 1);
392///     println!("{:?}", a);
393/// }
394/// ```
395#[macro_export]
396macro_rules! rt {
397    ( $n:expr, $df:expr ) => {{
398        let n: usize = $n;
399        let t = StudentT($df as f64);
400        t.sample(n)
401    }};
402}
403
404/// R like `dt`
405///
406/// # Examples
407/// ```
408/// #[macro_use]
409/// extern crate peroxide;
410/// use peroxide::fuga::*;
411///
412/// fn main() {
413///     let a = dt!(1, 1);
414///     println!("{:?}", a);
415/// }
416/// ```
417#[macro_export]
418macro_rules! dt {
419    ( $x:expr, $df:expr ) => {{
420        let x = $x as f64;
421        let df = $df as f64;
422        let t = StudentT(df);
423        t.pdf(x)
424    }};
425}
426
427/// R like `pt`
428///
429/// # Examples
430/// ```
431/// #[macro_use]
432/// extern crate peroxide;
433/// use peroxide::fuga::*;
434///
435/// fn main() {
436///     let a = pt!(1, 1);
437///     println!("{:?}", a); // 0.5
438/// }
439/// ```
440#[macro_export]
441macro_rules! pt {
442    ( $x:expr, $df:expr ) => {{
443        let x = $x as f64;
444        let df = $df as f64;
445        let t = StudentT(df);
446        t.cdf(x)
447    }};
448}
449
450/// R like lm
451///
452/// # Caution
453/// Should use single token to use this macro
454/// * `lm(y ~ x)` can be accepted
455/// * `lm(c!(1,2,3,4) ~ c!(1,2,3,4))` is not allowed!
456///
457/// # Examples
458/// ```
459/// #[macro_use]
460/// extern crate peroxide;
461/// use peroxide::fuga::*;
462///
463/// fn main() {
464///     let a = matrix!(1;5;1, 5, 1, Col);
465///     let b = matrix(c!(3.7, 4.2, 4.9, 5.7, 6.0), 5, 1, Col);
466///
467///     assert_eq!(lm!(b ~ a), matrix(c!(3.0700, 0.6100), 2, 1, Col));
468/// }
469/// ```
470#[macro_export]
471macro_rules! lm {
472    ( $y:tt ~ $x:tt ) => {
473        lm(&$x, &$y)
474    };
475}