# Data Reshaping - 2022.1 English

## AI Engine Kernel Coding Best Practices Guide (UG1079)

Document ID
UG1079
Release Date
2022-05-25
Version
2022.1 English

AI Engine API provides operations to change the location of the elements within a vector, to extract subvector from larger vector, or to combine the elements from two or more vectors.

The following APIs are provided to retrieve half of the vector by specific patterns.

`aie::filter_even`
Returns a vector of half the size by: out = { v[0:step], v[2*step:3*step], ... }
`aie::filter_odd`
Returns a vector of half the size by: out = { v[step:2*step], v[3*step:4*step], ... }
Note: The parameter `step` must be a power of two.
``````aie::vector<int32,8> result_e=aie::filter_even(xbuff, /*step=*/1);
aie::vector<int32,8> result_o=aie::filter_even(xbuff, /*step=*/4);``````

The following figures show how elements are chosen by `aie::filter_even` and `aie::filter_odd`.

Figure 1. aie::filter_even

Figure 2. aie::filter_odd

`aie::select` can be used to choose elements from two vectors (or a scalar and a vector) to form a new vector. `aie::mask` is used for specifying the element to choose.

`aie::select`
Choose elements by each bit of mask value: out = {mask[0] == 0? a[0] : b[0], …}
``aie::vector<int32,8> vc=aie::select(va,vb,msk_value);//vc[i]=(mask_value[i]==0)?va[i]:vb[i]``

AI Engine API provides following functions to shift vector elements by a specific number but maintain the vector size and element values.

`aie::shuffle_down`
Shift elements down by n: out = {v[n], v[n+1], …, v[Elems-1], undefined[0],…,undefined[n-1]}. Higher elements of output(out[n],out[n+1],…) are undefined. "Elems" is the vector size.
`aie::shuffle_up`
Shift elements up by n: out = {undefined[0],…,undefined[n-1],v[0], v[1], …}. Lower elements of output(out[0],…,out[n-1]) are undefined.
`aie::shuffle_down_rotate`
Rotate elements down by n: out = {v[n], v[n+1], …,v[Elems-1], v[0], …,v[n-1]}.
`aie::shuffle_up_rotate`
Rotate elements up by n: out = {v[Elems-n], …, v[Elems-1], v[0], …,v[n-1]}.
`aie::shuffle_down_fill`
Shift elements down by n and fill with elements from a second vector: out = {v[n], v[n+1], …, v[Elems-1], fill[0],…,fill[n-1]}. Higher elements of output(out[n],out[n+1],…) are filled with elements from second vector "fill"(fill[0],…,fill[n-1]).
`aie::shuffle_up_fill`
Shift elements up by n and fill with elements from a second vector: out = {fill[Elems-n],…,fill[Elems-1],v[0], v[1], …}. Lower elements of output(out[0],…,out[n-1]) are filled with elements from second vector "fill"(fill[Elems-n],…,fill[Elems-1]).
``````aie::vector<int32,8> v,fill;
//v_d[0:4]=v[3:7], (v_d[5],v_d[6],v_d[7] are undefined)
auto v_d=aie::shuffle_down(v,3);
//v_u[3:7]=v[0:4], (v_u[0],v_u[1],v_u[2] are undefined)
auto v_u=aie::shuffle_up(v,3);
auto vd_r=aie::shuffle_down_rotate(v,3);//vd_r[0:4]=v[3:7],vd_r[5:7]=v[0:2]
auto vu_r=aie::shuffle_up_rotate(v,3);//vu_r[3:7]=v[0:4],vu_r[0:2]=v[5:7]
//v_d_fill[0:4]=v[3:7], v_d_fill[5:7]=fill[0:2]
auto v_d_fill=aie::shuffle_down_fill(v,fill,3);
//v_u_fill[3:7]=v[0:4], v_u_fill[0:2]=fill[5:7]
auto v_u_fill=aie::shuffle_up_fill(v,fill,3);``````

A vector can be reversed by:

`aie::reverse`
Reverse elements by: out = {v[Elems-1], …, v[1], v[0]}
``aie::vector<int32,8> v_rev=aie::reverse(v,3);//v_rev[0:7]=v[7:0]``

AI Engine API provides functions to shuffle two input vectors and combine them into the larger output vectors. The two vectors must be the same type and size. The return type is `std::pair`.

`aie::interleave_zip`
Select and combine two vectors by this pattern: out = { v1[0:step], v2[0:step], v1[step:2*step], v2[step:2*step], ... }
`aie::inerleave_unzip`
Select and combine two vectors by this pattern: out = { v1[0:step], v1[2*step:3*step], ..., v2[0:step], v2[2*step:3*step], ..., v1[step:2*step], v1[3*step:4*step], ..., v2[step:2*step], v2[3*step:4*step], ... }
Note: The parameter `step` must be a power of two.

The following example takes two vectors with reals in `rva` and imaginary in `rvb` (with type `aie::vector<int32,8>`) and creates a new complex vector. It also shows how to extract real and imaginary parts back and compare them with the original values.

``````aie::vector<int32,8> rva,rvb;
auto rv=aie::interleave_zip(rva,rvb,/*step*/1);
aie::vector<cint32,8> cv=aie::concat(rv.first.cast_to<cint32>(),rv.second.cast_to<cint32>());

auto [uva,uvb]=aie::interleave_unzip(rv.first,rv.second,/*step*/1);
bool ret=aie::equal(rva,uva) && aie::equal(rvb,uvb);//return true``````