Skip to content

New macro, equation, to help modify Array using Seq and/or Array #241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 157 additions & 39 deletions src/core/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -204,9 +190,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)
}
};
Expand All @@ -223,26 +206,102 @@ 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;
/// Macro to evaluate individual Arrays or assignment operations
///
/// - 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::<f32>(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! eval {
( $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<i32>>::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<i32>>::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);
}
};
[$($x:expr),+] => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
$crate::eval_multiple(temp_vec)
}
};
}

#[cfg(test)]
mod tests {
use super::super::array::Array;
use super::super::data::constant;
use super::super::index::index;
use super::super::random::randu;

Expand Down Expand Up @@ -272,9 +331,15 @@ mod tests {

let a = randu::<f32>(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::<f32>(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]
Expand All @@ -286,25 +351,78 @@ 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 eval_assign_seq_indexed_array() {
let dims = dim4!(5, 5);
let mut a = randu::<f32>(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::<f32>(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);
eval!(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 eval_assign_array_to_seqd_array() {
// ANCHOR: macro_seq_assign
let mut a = randu::<f32>(dim4!(5, 5));
let b = randu::<f32>(dim4!(2, 2));
eval!(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::<f32>(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);
eval!(a[indices, seq4gen] = b);
// ANCHOR_END: macro_seq_array_assign
}
}
19 changes: 17 additions & 2 deletions tutorials-book/src/indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
```
<div style="text-align: center"> OR </div>

```rust, noplaypen
{{#include ../../src/core/macros.rs:seq_view2}}
```

### Modify a sub region of an existing Array

Expand All @@ -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
Expand All @@ -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}}
Expand All @@ -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}}
```
<div style="text-align: center"> OR </div>

```rust,noplaypen
{{#include ../../src/core/macros.rs:macro_seq_array_assign}}
```

## Extract or Set rows/coloumns of an Array

Expand Down