From 661f9c56e85accd74dbbb408db3f57ebf8a63424 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 4 Aug 2020 23:47:04 +0530 Subject: [PATCH 1/2] New macro, equation, to help modify Array using Seq and/or Array This macro provides some syntactic sugar hiding the logic that involves creationg of Indexer object and then setting the indexing objects for interested axes for a given Array. Updated indexing tutorial in mdbook with examples using macros also. --- src/core/macros.rs | 164 ++++++++++++++++++++++++++++----- tutorials-book/src/indexing.md | 19 +++- 2 files changed, 156 insertions(+), 27 deletions(-) diff --git a/src/core/macros.rs b/src/core/macros.rs index 95346a889..7620f2385 100644 --- a/src/core/macros.rs +++ b/src/core/macros.rs @@ -204,9 +204,6 @@ macro_rules! view { $( seq_vec.push($crate::seq!($start:$end:$step)); )* - for _span_place_holder in seq_vec.len()..AF_MAX_DIMS { - seq_vec.push($crate::seq!()); - } $crate::index(&$array_ident, &seq_vec) } }; @@ -223,19 +220,68 @@ macro_rules! view { }; ($array_ident:ident [ $($_e:expr),+ ]) => { { - #[allow(non_snake_case)] - let AF_MAX_DIMS: u32 = view!(@af_max_dims); - let span = $crate::seq!(); let mut idxrs = $crate::Indexer::default(); - view!(@set_indexer 0, idxrs, $($_e),*); + $crate::index_gen(&$array_ident, idxrs) + } + }; +} - let mut dim_ix = idxrs.len() as u32; - while dim_ix < AF_MAX_DIMS { - idxrs.set_index(&span, dim_ix, None); - dim_ix += 1; +/// This macro is syntactic sugar for modifying portions of Array with another Array using a +/// combination of [Sequences][1] and/or [Array][2] objects. +/// +/// Examples on how to use this macro are provided in the [tutorials book][3] +/// +/// [1]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Seq.html +/// [2]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Array.html +/// [3]: http://arrayfire.org/arrayfire-rust/book/indexing.html +#[macro_export] +macro_rules! equation { + ( $l:ident [ $($lb:literal : $le:literal : $ls:literal),+ ] = + $r:ident [ $($rb:literal : $re:literal : $rs:literal),+ ]) => { + { + #[allow(non_snake_case)] + let AF_MAX_DIMS: usize = view!(@af_max_dims); + let mut seq_vec = Vec::<$crate::Seq>::with_capacity(AF_MAX_DIMS); + $( + seq_vec.push($crate::seq!($lb:$le:$ls)); + )* + let mut idxrs = $crate::Indexer::default(); + for i in 0..seq_vec.len() { + idxrs.set_index(&seq_vec[i], i as u32, None); } - $crate::index_gen(&$array_ident, idxrs) + let eq_rterm = $crate::view!($r[ $($rb:$re:$rs),+ ]); + $crate::assign_gen(&mut $l, &idxrs, &eq_rterm); + } + }; + ( $l:ident [ $($lb:literal : $le:literal : $ls:literal),+ ] = $r:expr ) => { + { + #[allow(non_snake_case)] + let AF_MAX_DIMS: usize = view!(@af_max_dims); + let mut seq_vec = Vec::<$crate::Seq>::with_capacity(AF_MAX_DIMS); + $( + seq_vec.push($crate::seq!($lb:$le:$ls)); + )* + let mut idxrs = $crate::Indexer::default(); + for i in 0..seq_vec.len() { + idxrs.set_index(&seq_vec[i], i as u32, None); + } + $crate::assign_gen(&mut $l, &idxrs, &$r); + } + }; + ($lhs:ident [ $($lhs_e:expr),+ ] = $rhs:ident [ $($rhs_e:expr),+ ]) => { + { + let eq_rterm = $crate::view!($rhs[ $($rhs_e),+ ]); + let mut idxrs = $crate::Indexer::default(); + view!(@set_indexer 0, idxrs, $($lhs_e),*); + $crate::assign_gen(&mut $lhs, &idxrs, &eq_rterm); + } + }; + ($lhs:ident [ $($lhs_e:expr),+ ] = $rhs:expr) => { + { + let mut idxrs = $crate::Indexer::default(); + view!(@set_indexer 0, idxrs, $($lhs_e),*); + $crate::assign_gen(&mut $lhs, &idxrs, &$rhs); } }; } @@ -243,6 +289,7 @@ macro_rules! view { #[cfg(test)] mod tests { use super::super::array::Array; + use super::super::data::constant; use super::super::index::index; use super::super::random::randu; @@ -272,9 +319,15 @@ mod tests { let a = randu::(dim4d); let seqs = &[seq!(1:3:1), seq!()]; - let sub = index(&a, seqs); - af_print!("A", a); - af_print!("Indexed A", sub); + let _sub = index(&a, seqs); + } + + #[test] + fn seq_view2() { + // ANCHOR: seq_view2 + let a = randu::(dim4!(5, 5)); + let _sub = view!(a[1:3:1, 1:1:0]); // 1:1:0 means all elements along axis + // ANCHOR_END: seq_view2 } #[test] @@ -286,25 +339,86 @@ mod tests { let d = a.clone(); let e = a.clone(); - let v = view!(a); - af_print!("v = a[None]", v); + let _v = view!(a); - let m = view!(c[1:3:1, 1:3:2]); - af_print!("m = c[:, :]", m); + let _m = view!(c[1:3:1, 1:3:2]); let x = seq!(1:3:1); let y = seq!(1:3:2); - let u = view!(b[x, y]); - af_print!("u = b[seq(), seq()]", u); + let _u = view!(b[x, y]); let values: [u32; 3] = [1, 2, 3]; let indices = Array::new(&values, dim4!(3, 1, 1, 1)); let indices2 = Array::new(&values, dim4!(3, 1, 1, 1)); - let w = view!(d[indices, indices2]); - af_print!("w = d[Array, Array]", w); + let _w = view!(d[indices, indices2]); + + let _z = view!(e[indices, y]); + } + + #[test] + fn equation_macro1() { + let dims = dim4!(5, 5); + let mut a = randu::(dims); + //print(&a); + //[5 5 1 1] + // 0.6010 0.5497 0.1583 0.3636 0.6755 + // 0.0278 0.2864 0.3712 0.4165 0.6105 + // 0.9806 0.3410 0.3543 0.5814 0.5232 + // 0.2126 0.7509 0.6450 0.8962 0.5567 + // 0.0655 0.4105 0.9675 0.3712 0.7896 + + let b = randu::(dims); + //print(&b); + //[5 5 1 1] + // 0.8966 0.5143 0.0123 0.7917 0.2522 + // 0.0536 0.3670 0.3988 0.1654 0.9644 + // 0.5775 0.3336 0.9787 0.8657 0.4711 + // 0.2908 0.0363 0.2308 0.3766 0.3637 + // 0.9941 0.5349 0.6244 0.7331 0.9643 + + let d0 = seq!(1:2:1); + let d1 = seq!(1:2:1); + let s0 = seq!(1:2:1); + let s1 = seq!(1:2:1); + equation!(a[d0, d1] = b[s0, s1]); + //print(&a); + //[5 5 1 1] + // 0.6010 0.5497 0.1583 0.3636 0.6755 + // 0.0278 0.3670 0.3988 0.4165 0.6105 + // 0.9806 0.3336 0.9787 0.5814 0.5232 + // 0.2126 0.7509 0.6450 0.8962 0.5567 + // 0.0655 0.4105 0.9675 0.3712 0.7896 + } + + #[test] + fn equation_macro2() { + let dims = dim4!(5, 5); + let mut a = randu::(dims); + let b = randu::(dims); + equation!(a[1:2:1, 1:2:1] = b[1:2:1, 1:2:1]); + } + + #[test] + fn equation_macro3() { + // ANCHOR: macro_seq_assign + let mut a = randu::(dim4!(5, 5)); + let b = randu::(dim4!(2, 2)); + equation!(a[1:2:1, 1:2:1] = b); + // ANCHOR_END: macro_seq_assign + } + + #[test] + fn macro_seq_array_assign() { + // ANCHOR: macro_seq_array_assign + let values: [f32; 3] = [1.0, 2.0, 3.0]; + let indices = Array::new(&values, dim4!(3)); + let seq4gen = seq!(0:2:1); + let mut a = randu::(dim4!(5, 3)); + + let b = constant(2.0 as f32, dim4!(3, 3)); - let z = view!(e[indices, y]); - af_print!("z = e[Array, Seq]", z); + equation!(a[indices, seq4gen] = b); + // ANCHOR_END: macro_seq_array_assign } } diff --git a/tutorials-book/src/indexing.md b/tutorials-book/src/indexing.md index ad54eea52..1f74a1a06 100644 --- a/tutorials-book/src/indexing.md +++ b/tutorials-book/src/indexing.md @@ -18,10 +18,15 @@ We will Sequences and the function [index][3] in this approach. {{#include ../../src/core/index.rs:non_macro_seq_index}} ``` However, the same above code can be condensed into a much terse syntax with the help of [view][11] -macro. Take a look at the above code modified to use view macro. +macro. Take a look at the following two approaches using view macro. ```rust, noplaypen {{#include ../../src/core/index.rs:seq_index}} ``` +
OR
+ +```rust, noplaypen +{{#include ../../src/core/macros.rs:seq_view2}} +``` ### Modify a sub region of an existing Array @@ -32,6 +37,11 @@ Array. We will an constant value Array and the function [assign\_seq][4] in the {{#include ../../src/core/index.rs:non_macro_seq_assign}} ``` +A much terser way of doing the same using macro is shown below +```rust,noplaypen +{{#include ../../src/core/macros.rs:macro_seq_assign}} +``` + > **NOTE** Normally you want to avoid accessing individual elements of the array like this for performance reasons. ## Using Array and Seq combination @@ -44,7 +54,7 @@ generalized function [index\_gen][12]. ```rust,noplaypen {{#include ../../src/core/index.rs:non_macro_seq_array_index}} ``` -Similar to how, [view][11] macro helped with abreviating the syntax when indexing with just +Similar to how [view][11] macro helped with abreviating the syntax when indexing with just sequences, it can also help when using a combination of Seq and Array. ```rust, noplaypen {{#include ../../src/core/index.rs:seq_array_index}} @@ -58,6 +68,11 @@ We will use [assign\_gen][13] function to do it. ```rust,noplaypen {{#include ../../src/core/index.rs:non_macro_seq_array_assign}} ``` +
OR
+ + ```rust,noplaypen +{{#include ../../src/core/macros.rs:macro_seq_array_assign}} + ``` ## Extract or Set rows/coloumns of an Array From 003e91534b19509d3326236b2b0122bede324cae Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 5 Aug 2020 17:57:32 +0530 Subject: [PATCH 2/2] Refactor eval to handle patterns handled by equation macro(removed now) --- src/core/macros.rs | 66 ++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/core/macros.rs b/src/core/macros.rs index 7620f2385..69c08a8d5 100644 --- a/src/core/macros.rs +++ b/src/core/macros.rs @@ -117,20 +117,6 @@ macro_rules! af_print { }; } -/// Evaluate arbitrary number of arrays -#[macro_export] -macro_rules! eval { - [$($x:expr),+] => { - { - let mut temp_vec = Vec::new(); - $( - temp_vec.push($x); - )* - eval_multiple(temp_vec) - } - }; -} - /// Create a dim4 object from provided dimensions /// /// The user can pass 1 or more sizes and the left over values will default to 1. @@ -227,16 +213,33 @@ macro_rules! view { }; } -/// This macro is syntactic sugar for modifying portions of Array with another Array using a -/// combination of [Sequences][1] and/or [Array][2] objects. +/// Macro to evaluate individual Arrays or assignment operations /// -/// Examples on how to use this macro are provided in the [tutorials book][3] +/// - Evaluate on one or more Array identifiers: essentially calls [Array::eval][4] on each of those +/// Array objects individually. +/// +/// ```rust +/// use arrayfire::{dim4, eval, randu}; +/// let dims = dim4!(5, 5); +/// let a = randu::(dims); +/// let b = a.clone(); +/// let c = a.clone(); +/// let d = a.clone(); +/// let x = a - b; +/// let y = c * d; +/// eval!(&x, &y); +/// ``` +/// +/// - Evaluate assignment operations: This is essentially syntactic sugar for modifying portions of +/// Array with another Array using a combination of [Sequences][1] and/or [Array][2] objects. +/// Full examples for this use case are provided in the [tutorials book][3] /// /// [1]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Seq.html /// [2]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Array.html /// [3]: http://arrayfire.org/arrayfire-rust/book/indexing.html +/// [4]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Array.html#method.eval #[macro_export] -macro_rules! equation { +macro_rules! eval { ( $l:ident [ $($lb:literal : $le:literal : $ls:literal),+ ] = $r:ident [ $($rb:literal : $re:literal : $rs:literal),+ ]) => { { @@ -284,6 +287,15 @@ macro_rules! equation { $crate::assign_gen(&mut $lhs, &idxrs, &$rhs); } }; + [$($x:expr),+] => { + { + let mut temp_vec = Vec::new(); + $( + temp_vec.push($x); + )* + $crate::eval_multiple(temp_vec) + } + }; } #[cfg(test)] @@ -357,7 +369,7 @@ mod tests { } #[test] - fn equation_macro1() { + fn eval_assign_seq_indexed_array() { let dims = dim4!(5, 5); let mut a = randu::(dims); //print(&a); @@ -381,7 +393,7 @@ mod tests { let d1 = seq!(1:2:1); let s0 = seq!(1:2:1); let s1 = seq!(1:2:1); - equation!(a[d0, d1] = b[s0, s1]); + eval!(a[d0, d1] = b[s0, s1]); //print(&a); //[5 5 1 1] // 0.6010 0.5497 0.1583 0.3636 0.6755 @@ -392,19 +404,11 @@ mod tests { } #[test] - fn equation_macro2() { - let dims = dim4!(5, 5); - let mut a = randu::(dims); - let b = randu::(dims); - equation!(a[1:2:1, 1:2:1] = b[1:2:1, 1:2:1]); - } - - #[test] - fn equation_macro3() { + fn eval_assign_array_to_seqd_array() { // ANCHOR: macro_seq_assign let mut a = randu::(dim4!(5, 5)); let b = randu::(dim4!(2, 2)); - equation!(a[1:2:1, 1:2:1] = b); + eval!(a[1:2:1, 1:2:1] = b); // ANCHOR_END: macro_seq_assign } @@ -418,7 +422,7 @@ mod tests { let b = constant(2.0 as f32, dim4!(3, 3)); - equation!(a[indices, seq4gen] = b); + eval!(a[indices, seq4gen] = b); // ANCHOR_END: macro_seq_array_assign } }