ndarray_parallel/
zipmacro.rs

1// Copyright 2017 bluss and ndarray developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#[macro_export]
10/// Parallel version of the `azip!` macro.
11///
12/// See the `azip!` documentation for more details.
13///
14/// This example:
15///
16/// ```rust,ignore
17/// par_azip!(mut a, b, c in { *a = b + c })
18/// ```
19///
20/// Is equivalent to:
21///
22/// ```rust,ignore
23/// Zip::from(&mut a).and(&b).and(&c).par_apply(|a, &b, &c| {
24///     *a = b + c;
25/// });
26/// ```
27///
28/// **Panics** if any of the arrays are not of the same shape.
29///
30/// ## Examples
31///
32/// ```rust
33/// extern crate ndarray;
34/// #[macro_use(par_azip)]
35/// extern crate ndarray_parallel;
36///
37/// use ndarray::Array2;
38///
39/// type M = Array2<f32>;
40///
41/// fn main() {
42///     let mut a = M::zeros((16, 16));
43///     let b = M::from_elem(a.dim(), 1.);
44///     let c = M::from_elem(a.dim(), 2.);
45///
46///     // Compute a simple ternary operation:
47///     // elementwise addition of b and c, stored in a
48///
49///     par_azip!(mut a, b, c in { *a = b + c });
50///
51///     assert_eq!(a, &b + &c);
52/// }
53/// ```
54macro_rules! par_azip {
55    // Build Zip Rule (index)
56    (@parse [index => $a:expr, $($aa:expr,)*] $t1:tt in $t2:tt) => {
57        par_azip!(@finish ($crate::ndarray::Zip::indexed($a)) [$($aa,)*] $t1 in $t2)
58    };
59    // Build Zip Rule (no index)
60    (@parse [$a:expr, $($aa:expr,)*] $t1:tt in $t2:tt) => {
61        par_azip!(@finish ($crate::ndarray::Zip::from($a)) [$($aa,)*] $t1 in $t2)
62    };
63    // Build Finish Rule (both)
64    (@finish ($z:expr) [$($aa:expr,)*] [$($p:pat,)+] in { $($t:tt)*}) => {
65        use $crate::prelude::*;
66        #[allow(unused_mut)]
67        ($z)
68            $(
69                .and($aa)
70            )*
71            .par_apply(|$($p),+| {
72                $($t)*
73            })
74    };
75    // parsing stack: [expressions] [patterns] (one per operand)
76    // index uses empty [] -- must be first
77    (@parse [] [] index $i:pat, $($t:tt)*) => {
78        par_azip!(@parse [index =>] [$i,] $($t)*);
79    };
80    (@parse [$($exprs:tt)*] [$($pats:tt)*] mut $x:ident ($e:expr) $($t:tt)*) => {
81        par_azip!(@parse [$($exprs)* $e,] [$($pats)* mut $x,] $($t)*);
82    };
83    (@parse [$($exprs:tt)*] [$($pats:tt)*] mut $x:ident $($t:tt)*) => {
84        par_azip!(@parse [$($exprs)* &mut $x,] [$($pats)* mut $x,] $($t)*);
85    };
86    (@parse [$($exprs:tt)*] [$($pats:tt)*] , $($t:tt)*) => {
87        par_azip!(@parse [$($exprs)*] [$($pats)*] $($t)*);
88    };
89    (@parse [$($exprs:tt)*] [$($pats:tt)*] ref $x:ident ($e:expr) $($t:tt)*) => {
90        par_azip!(@parse [$($exprs)* $e,] [$($pats)* $x,] $($t)*);
91    };
92    (@parse [$($exprs:tt)*] [$($pats:tt)*] ref $x:ident $($t:tt)*) => {
93        par_azip!(@parse [$($exprs)* &$x,] [$($pats)* $x,] $($t)*);
94    };
95    (@parse [$($exprs:tt)*] [$($pats:tt)*] $x:ident ($e:expr) $($t:tt)*) => {
96        par_azip!(@parse [$($exprs)* $e,] [$($pats)* &$x,] $($t)*);
97    };
98    (@parse [$($exprs:tt)*] [$($pats:tt)*] $x:ident $($t:tt)*) => {
99        par_azip!(@parse [$($exprs)* &$x,] [$($pats)* &$x,] $($t)*);
100    };
101    (@parse [$($exprs:tt)*] [$($pats:tt)*] $($t:tt)*) => { };
102    ($($t:tt)*) => {
103        par_azip!(@parse [] [] $($t)*);
104    }
105}