Matrix Manipulation

Many different kinds of matrix manipulation routines are available:

  • flat() - flatten an array to one dimension
  • flip() - flip an array along a dimension
  • join() - join up to 4 arrays
  • moddims() - change the dimensions of an array without changing the data
  • reorder() - changes the dimension order within the array
  • shift() - shifts data along a dimension
  • tile() - repeats an array along a dimension
  • transpose() - performs a matrix transpose
  • array() to adjust the dimensions of an array
  • transpose a matrix or vector with shorthand notation

flat()

The flat() function flattens an array to one dimension.

1 a [3 3 1 1]
2  1.0000 4.0000 7.0000
3  2.0000 5.0000 8.0000
4  3.0000 6.0000 9.0000
5 
6 flat(a) [9 1 1 1]
7  1.0000
8  2.0000
9  3.0000
10  4.0000
11  5.0000
12  6.0000
13  7.0000
14  8.0000
15  9.0000

The flat function has the following overloads:

flip()

The flip() function flips the contents of an array along a chosen dimension.

1 a [5 2 1 1]
2  1.0000 6.0000
3  2.0000 7.0000
4  3.0000 8.0000
5  4.0000 9.0000
6  5.0000 10.0000
7 
8 flip(a, 0) [5 2 1 1]
9  5.0000 10.0000
10  4.0000 9.0000
11  3.0000 8.0000
12  2.0000 7.0000
13  1.0000 6.0000
14 
15 flip(a, 1) [5 2 1 1]
16  6.0000 1.0000
17  7.0000 2.0000
18  8.0000 3.0000
19  9.0000 4.0000
20  10.0000 5.0000

The flip function has the following overloads:

join()

The join() function can join up to 4 arrays together.

1 a [5 1 1 1]
2  1.0000
3  2.0000
4  3.0000
5  4.0000
6  5.0000
7 
8 join(0, a, a) [10 1 1 1]
9  1.0000
10  2.0000
11  3.0000
12  4.0000
13  5.0000
14  1.0000
15  2.0000
16  3.0000
17  4.0000
18  5.0000
19 
20 join(1, a, a) [5 2 1 1]
21  1.0000 1.0000
22  2.0000 2.0000
23  3.0000 3.0000
24  4.0000 4.0000
25  5.0000 5.0000

The join function has several overloads:

moddims()

The moddims() function changes the dimensions of an array without changing its data or order. It is important to remember that the function only modifies the metadata associated with the array and does not actually modify the content of the array.

1 a [8 1 1 1]
2  1.0000
3  2.0000
4  1.0000
5  2.0000
6  1.0000
7  2.0000
8  1.0000
9  2.0000
10 
11 af::dim4 new_dims(2, 4);
12 moddims(a, new_dims) [2 4 1 1]
13  1.0000 1.0000 1.0000 1.0000
14  2.0000 2.0000 2.0000 2.0000
15 
16 moddims(a, a.elements(), 1, 1, 1) [8 1 1 1]
17  1.0000
18  2.0000
19  1.0000
20  2.0000
21  1.0000
22  2.0000
23  1.0000
24  2.0000

The moddims function has several overloads:

reorder()

The reorder() function changes the order of the dimensions within the array. This actually alters the underlying data of the array.

1 a [2 2 3 1]
2  1.0000 3.0000
3  2.0000 4.0000
4 
5  1.0000 3.0000
6  2.0000 4.0000
7 
8  1.0000 3.0000
9  2.0000 4.0000
10 
11 
12 reorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose
13  1.0000 2.0000
14  3.0000 4.0000
15 
16  1.0000 2.0000
17  3.0000 4.0000
18 
19  1.0000 2.0000
20  3.0000 4.0000
21 
22 
23 reorder(a, 2, 0, 1) [3 2 2 1]
24  1.0000 2.0000
25  1.0000 2.0000
26  1.0000 2.0000
27 
28  3.0000 4.0000
29  3.0000 4.0000
30  3.0000 4.0000

The reorder function the following several overloads:

shift()

The shift() function shifts data in a circular buffer fashion along a chosen dimension.

1 a [3 5 1 1]
2  0.0000 0.0000 0.0000 0.0000 0.0000
3  3.0000 4.0000 5.0000 1.0000 2.0000
4  3.0000 4.0000 5.0000 1.0000 2.0000
5 
6 shift(a, 0, 2 ) [3 5 1 1]
7  0.0000 0.0000 0.0000 0.0000 0.0000
8  1.0000 2.0000 3.0000 4.0000 5.0000
9  1.0000 2.0000 3.0000 4.0000 5.0000
10 
11 shift(a, -1, 2 ) [3 5 1 1]
12  1.0000 2.0000 3.0000 4.0000 5.0000
13  1.0000 2.0000 3.0000 4.0000 5.0000
14  0.0000 0.0000 0.0000 0.0000 0.0000

The shift function has the following overloads:

tile()

The tile() function repeats an array along a dimension

1 a [3 1 1 1]
2  1.0000
3  2.0000
4  3.0000
5 
6 tile(a, 2) [6 1 1 1]
7  1.0000
8  2.0000
9  3.0000
10  1.0000
11  2.0000
12  3.0000
13 
14 tile(a, 2, 2) [6 2 1 1]
15  1.0000 1.0000
16  2.0000 2.0000
17  3.0000 3.0000
18  1.0000 1.0000
19  2.0000 2.0000
20  3.0000 3.0000
21 
22 af::dim4 tile_dims(1, 2, 3);
23 tile(a, tile_dims) [3 2 3 1]
24  1.0000 1.0000
25  2.0000 2.0000
26  3.0000 3.0000
27 
28  1.0000 1.0000
29  2.0000 2.0000
30  3.0000 3.0000
31 
32  1.0000 1.0000
33  2.0000 2.0000
34  3.0000 3.0000

The tile function has several overloads:

transpose()

The transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.

1 a [3 3 1 1]
2  1.0000 3.0000 3.0000
3  2.0000 1.0000 3.0000
4  2.0000 2.0000 1.0000
5 
6 transpose(a) [3 3 1 1]
7  1.0000 2.0000 2.0000
8  3.0000 1.0000 2.0000
9  3.0000 3.0000 1.0000

The transpose function has several overloads:

array() can be used to create a (shallow) copy of a matrix with different dimensions. The number of elements must remain the same as the original array.

int hA[] = {1, 2, 3, 4, 5, 6};
array A = array(3, 2, hA);
af_print(A); // 2x3 matrix
af_print(moddims(A, 2, 3)); // 2x3 matrix
af_print(moddims(A, 6, 1)); // 6x1 column vector
// moddims(A, 2, 2); // fail: wrong number of elements
// moddims(A, 8, 8); // fail: wrong number of elements

The T() and H() methods can be used to form the matrix or vector transpose .

array x = randu(2, 2, f32);
af_print(x.T()); // transpose (real)
array c = randu(2, 2, c32);
af_print(c.T()); // transpose (complex)
af_print(c.H()); // Hermitian (conjugate) transpose

Combining re-ordering functions to enumerate grid coordinates

By using a combination of the array restructuring functions, we can quickly code complex manipulation patterns with a few lines of code. For example, consider generating _(x,y)_ coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.

1 unsigned n=3;
2 af::array xy = join(1
3  tile(seq(1, n), n)
4  flat( transpose(tile(seq(1, n), 1, n)) )
5  );
6 xy [9 2 1 1]
7  1.0000 1.0000
8  2.0000 1.0000
9  3.0000 1.0000
10  1.0000 2.0000
11  2.0000 2.0000
12  3.0000 2.0000
13  1.0000 3.0000
14  2.0000 3.0000
15  3.0000 3.0000

Conclusion

Functions provided by arrayfire offer ease and flexibility for efficiently manipulating the structure of arrays. The provided functions can be used as building blocks to generate, shift, or prepare data to any form imaginable!