zenu_matrix/slice/
macro.rs

1#[macro_export]
2macro_rules! slice(
3    (@parse [$($stack:tt)*] $r:expr;$s:expr) => {
4        $crate::slice!(@final
5            [$($stack)* $crate::slice!(@convert $r, $s)]
6        )
7    };
8    (@parse [$($stack:tt)*] $r:expr) => {
9        $crate::slice!(@final [$($stack)* $crate::slice!(@convert $r)])
10    };
11    (@parse [$($stack:tt)*] $r:expr;$s:expr ,) => {
12        $crate::slice![@parse $in_dim, $out_dim, [$($stack)*] $r;$s]
13    };
14    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr ,) => {
15        $crate::slice![@parse $in_dim, $out_dim, [$($stack)*] $r]
16    };
17    (@parse [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => {
18        match $r {
19            r => {
20                $crate::slice![@parse
21                   [$($stack)* $crate::slice!(@convert r, $s),]
22                   $($t)*
23                ]
24            }
25        }
26    };
27    (@parse [$($stack:tt)*] $r:expr, $($t:tt)*) => {
28        match $r {
29            r => {
30                $crate::slice![@parse
31                   [$($stack)* $crate::slice!(@convert r),]
32                   $($t)*
33                ]
34            }
35        }
36    };
37
38    (@parse []) => {
39        {
40            Slice0D {  }
41        }
42    };
43
44    (@parse $($t:tt)*) => { compile_error!("Invalid syntax in slice![] call.") };
45
46    (@convert $r:expr) => {
47        $crate::slice::slice_dim::SliceDim::from($r)
48    };
49    (@convert $r:expr, $s:expr) => {
50        $crate::slice::slice_dim::SliceDim::from($r).step($s)
51    };
52
53    (@final [$dim1:expr]) => {
54        match $dim1 {
55            dim1 => $crate::slice::static_dim_slice::Slice1D {
56                    index: [dim1],
57                }
58        }
59    };
60
61    (@final [$dim1:expr, $dim2:expr]) => {
62        $crate::slice::static_dim_slice::Slice2D {
63            index: [$dim1, $dim2],
64        }
65    };
66
67    (@final [$dim1:expr, $dim2:expr, $dim3:expr]) => {
68        $crate::slice::static_dim_slice::Slice3D {
69            index: [$dim1, $dim2, $dim3],
70        }
71    };
72
73    (@final [$dim1:expr, $dim2:expr, $dim3:expr, $dim4:expr]) => {
74        $crate::slice::static_dim_slice::Slice4D {
75            index: [$dim1, $dim2, $dim3, $dim4],
76        }
77    };
78
79    ($($t:tt)*) => {
80        $crate::slice![@parse
81              []
82              $($t)*
83        ]
84    };
85);
86
87#[macro_export]
88macro_rules! slice_dynamic {
89    (@parse [$($stack:tt)*] $r:expr;$s:expr) => {
90        $crate::slice_dynamic!(@final
91            [$($stack)* $crate::slice_dynamic!(@convert $r, $s)]
92        )
93    };
94    (@parse [$($stack:tt)*] $r:expr) => {
95        $crate::slice_dynamic!(@final [$($stack)* $crate::slice_dynamic!(@convert $r)])
96    };
97    (@parse [$($stack:tt)*] $r:expr;$s:expr ,) => {
98        $crate::slice_dynamic![@parse $in_dim, $out_dim, [$($stack)*] $r;$s]
99    };
100    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr ,) => {
101        $crate::slice_dynamic![@parse $in_dim, $out_dim, [$($stack)*] $r]
102    };
103    (@parse [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => {
104        match $r {
105            r => {
106                $crate::slice_dynamic![@parse
107                   [$($stack)* $crate::slice_dynamic!(@convert r, $s),]
108                   $($t)*
109                ]
110            }
111        }
112    };
113    (@parse [$($stack:tt)*] $r:expr, $($t:tt)*) => {
114        match $r {
115            r => {
116                $crate::slice_dynamic![@parse
117                   [$($stack)* $crate::slice_dynamic!(@convert r),]
118                   $($t)*
119                ]
120            }
121        }
122    };
123    (@parse []) => {
124        {
125            $crate::slice::dynamic::Slice::From(&[])
126        }
127    };
128    (@parse $($t:tt)*) => { compile_error!("Invalid syntax in slice_dynamic![] call.") };
129
130    (@convert $r:expr) => {
131        $crate::slice::slice_dim::SliceDim::from($r)
132    };
133    (@convert $r:expr, $s:expr) => {
134        $crate::slice::slice_dim::SliceDim::from($r).step($s)
135    };
136
137    (@final [$($dim:expr),*]) => {{
138        let slice = [$($dim),*];
139        let slice_ref = &slice as &[$crate::slice::SliceDim];
140        $crate::slice::dynamic::Slice::from(slice_ref)
141    }};
142
143    ($($t:tt)*) => {
144        $crate::slice_dynamic![@parse
145              []
146              $($t)*
147        ]
148    };
149}
150
151#[cfg(test)]
152mod tests {
153    use crate::slice::dynamic::Slice;
154    use crate::slice::slice_dim::SliceDim;
155    use crate::slice::static_dim_slice::{Slice1D, Slice2D, Slice3D, Slice4D};
156
157    #[test]
158    fn test_slice_dynamic() {
159        let slice = slice_dynamic!(1..3;1, ..4;2, 5..;3);
160        assert_eq!(
161            slice,
162            Slice {
163                index: [
164                    SliceDim {
165                        start: Some(1),
166                        end: Some(3),
167                        step: Some(1)
168                    },
169                    SliceDim {
170                        start: None,
171                        end: Some(4),
172                        step: Some(2)
173                    },
174                    SliceDim {
175                        start: Some(5),
176                        end: None,
177                        step: Some(3)
178                    },
179                    SliceDim {
180                        start: None,
181                        end: None,
182                        step: None
183                    },
184                    SliceDim {
185                        start: None,
186                        end: None,
187                        step: None
188                    },
189                    SliceDim {
190                        start: None,
191                        end: None,
192                        step: None
193                    }
194                ],
195                len: 3
196            }
197        );
198    }
199
200    #[test]
201    fn test_slice_macro_1d() {
202        let slice = slice!(1..5;2);
203        assert_eq!(
204            slice,
205            Slice1D {
206                index: [SliceDim {
207                    start: Some(1),
208                    end: Some(5),
209                    step: Some(2)
210                }]
211            }
212        );
213    }
214
215    #[test]
216    fn test_slice_macro_2d() {
217        let slice = slice!(..;2, 3..);
218        assert_eq!(
219            slice,
220            Slice2D {
221                index: [
222                    SliceDim {
223                        start: None,
224                        end: None,
225                        step: Some(2)
226                    },
227                    SliceDim {
228                        start: Some(3),
229                        end: None,
230                        step: None
231                    }
232                ]
233            }
234        );
235    }
236
237    #[test]
238    fn test_slice_macro_3d() {
239        let slice = slice!(1..3;1, ..4;2, 5..;3);
240        assert_eq!(
241            slice,
242            Slice3D {
243                index: [
244                    SliceDim {
245                        start: Some(1),
246                        end: Some(3),
247                        step: Some(1)
248                    },
249                    SliceDim {
250                        start: None,
251                        end: Some(4),
252                        step: Some(2)
253                    },
254                    SliceDim {
255                        start: Some(5),
256                        end: None,
257                        step: Some(3)
258                    }
259                ]
260            }
261        );
262    }
263
264    #[test]
265    fn test_slice_macro_4d() {
266        let slice = slice!(..;1, 2..5, ..6;2, 7..9;3);
267        assert_eq!(
268            slice,
269            Slice4D {
270                index: [
271                    SliceDim {
272                        start: None,
273                        end: None,
274                        step: Some(1)
275                    },
276                    SliceDim {
277                        start: Some(2),
278                        end: Some(5),
279                        step: None
280                    },
281                    SliceDim {
282                        start: None,
283                        end: Some(6),
284                        step: Some(2)
285                    },
286                    SliceDim {
287                        start: Some(7),
288                        end: Some(9),
289                        step: Some(3)
290                    }
291                ]
292            }
293        );
294    }
295}