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}