1 Array and Matrix Manipulation {#matrixmanipulation}
4 ArrayFire provides several different methods for
5 [manipulating arrays and matrices](\ref manip_mat). The functionality includes:
7 * moddims() - change the dimensions of an array without changing the data
8 * array() - create a (shallow) copy of an array with different dimensions.
9 * flat() - flatten an array to one dimension
10 * flip() - flip an array along a dimension
11 * join() - join up to 4 arrays
12 * reorder() - changes the dimension order within the array
13 * shift() - shifts data along a dimension
14 * tile() - repeats an array along a dimension
15 * transpose() - performs a matrix transpose
16 * [T()](\ref af::array::T) - transpose a matrix or vector (shorthand notation)
17 * [H()](\ref af::array::H) - Hermitian Transpose (conjugate-transpose) a matrix
19 Below we provide several examples of these functions and their use.
23 The __flat()__ function flattens an array to one dimension:
25 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
41 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43 The flat function can be called from C and C++ as follows:
45 > __af_err af_flat(af_array* out, const af_array in)__
46 > -- C interface for flat() function
48 > __array af::flat(const array& in)__
49 > -- C++ interface for flat() function
53 The __flip()__ function flips the contents of an array along a chosen dimension.
54 In the example below, we show the 5x2 array flipped along the zeroth (i.e.
55 within a column) and first (e.g. across rows) axes:
57 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
78 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80 The flip function can be called from C and C++ as follows:
82 > __af_err af_flip(af_array *out, const af_array in, const unsigned dim)__
83 > -- C interface for flip()
85 > __array af::flip(const array &in, const unsigned dim)__
86 > -- C++ interface for flip()
90 The __join()__ function joins arrays along a specific dimension. The C++
91 interface can join up to four arrays whereas the C interface supports up to 10
92 arrays. Here is an example of how to use join an array to itself:
94 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
102 join(0, a, a) [10 1 1 1]
114 join(1, a, a) [5 2 1 1]
120 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
122 The join function has several candidate functions in C:
124 > __af_err af_join(af_array *out, const int dim, const af_array first, const af_array second)__
125 > -- C interface function to join 2 arrays along a dimension
127 > __af_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs)__
128 > -- C interface function to join up to 10 arrays along a dimension
132 > __array af::join(const int dim, const array &first, const array &second)__
133 > -- Joins 2 arrays along a dimension
135 > __array af::join(const int dim, const array &first, const array &second, const array &third)__
136 > -- Joins 3 arrays along a dimension.
138 > __array af::join(const int dim, const array &first, const array &second, const array &third, const array &fourth)__
139 > -- Joins 4 arrays along a dimension
144 The __moddims()__ function changes the dimensions of an array without changing
145 its data or order. Note that this function modifies only the _metadata_
146 associated with the array. It does not modify the content of the array.
147 Here is an example of moddims() converting an 8x1 array into a 2x4 and then
150 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
161 af::dim4 new_dims(2, 4);
162 moddims(a, new_dims) [2 4 1 1]
163 1.0000 1.0000 1.0000 1.0000
164 2.0000 2.0000 2.0000 2.0000
166 moddims(a, a.elements(), 1, 1, 1) [8 1 1 1]
175 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177 The moddims function has a single form in the C API:
179 > __af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims)__
180 > -- C interface to mod dimensions of an array
182 And several overloaded candidates in the C++ API:
184 > __array af::moddims(const array &in, const unsigned ndims, const dim_t *const dims)__
185 > -- mods number of dimensions to match _ndims_ as specidied in the array _dims_
187 > __array af::moddims(const array &in, const dim4 &dims)__
188 > -- mods dimensions as specified by _dims_
190 > __array af::moddims(const array &in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1)__
191 > -- mods dimensions of an array
195 The __reorder()__ function modifies the order of data within an array by
196 exchanging data according to the change in dimensionality. The linear ordering
197 of data within the array is preserved.
199 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
211 reorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose
222 reorder(a, 2, 0, 1) [3 2 2 1]
230 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
232 The reorder function has several candidates functions in the C/C++ APIs:
234 > __af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w)__
235 > -- C interface for reordering function
237 > __array af::reorder(const array &in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3)__
238 > -- Reorders dimensions of an array
242 The __shift()__ function shifts data in a circular buffer fashion along a
243 chosen dimension. Consider the following example:
245 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
247 0.0000 0.0000 0.0000 0.0000 0.0000
248 3.0000 4.0000 5.0000 1.0000 2.0000
249 3.0000 4.0000 5.0000 1.0000 2.0000
251 shift(a, 0, 2 ) [3 5 1 1]
252 0.0000 0.0000 0.0000 0.0000 0.0000
253 1.0000 2.0000 3.0000 4.0000 5.0000
254 1.0000 2.0000 3.0000 4.0000 5.0000
256 shift(a, -1, 2 ) [3 5 1 1]
257 1.0000 2.0000 3.0000 4.0000 5.0000
258 1.0000 2.0000 3.0000 4.0000 5.0000
259 0.0000 0.0000 0.0000 0.0000 0.0000
260 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
262 The shift function can be called from C and C++ as follows:
265 > __af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w)__
266 > -- C interface for shifting an array
268 > __array af::shift(const array &in, const int x, const int y=0, const int z=0, const int w=0)__
269 > -- Shifts array along specified dimensions
273 The __tile()__ function repeats an array along the specified dimension.
274 For example below we show how to tile an array along the zeroth and first
275 dimensions of an array:
277 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
283 // Repeat array a twice in the zeroth dimension
292 // Repeat array a twice along both the zeroth and first dimensions
293 tile(a, 2, 2) [6 2 1 1]
301 // Repeat array a twice along the first and three times along the second
303 af::dim4 tile_dims(1, 2, 3);
304 tile(a, tile_dims) [3 2 3 1]
316 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
318 The C interface for tile is as follows:
320 > __af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w)__
321 > -- C interface for tiling an array
323 The C++ interface has two overloads
325 > __array af::tile(const array &in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1)__
326 > -- Tiles array along specified dimensions
328 > __array af::tile(const array &in, const dim4 &dims)__
329 > -- Tile an array according to a dim4 object
333 The __transpose()__ function performs a standard matrix transpose. The input
334 array must have the dimensions of a 2D-matrix.
336 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
342 transpose(a) [3 3 1 1]
346 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
348 The C interfaces for transpose are as follows:
350 > __af_err af_transpose(af_array *out, af_array in, const bool conjugate)__
351 > -- C interface to transpose a matrix.
353 > __af_err af_transpose_inplace(af_array in, const bool conjugate)__
354 > -- C interface to transpose a matrix in-place.
356 The C++ interface has two primary functions and two shorthand versions:
358 > __array af::transpose(const array &in, const bool conjugate=false)__
359 > -- Transposes a matrix.
361 > __void af::transposeInPlace(array &in, const bool conjugate=false)__
362 > -- Transposes a matrix in-place.
365 > -- Transpose a matrix
368 > -- Conjugate Transpose (Hermitian transpose) of a matrix
370 Here is an example of how the shorthand versions might be used:
372 \snippet test/matrix_manipulation.cpp ex_matrix_manipulation_transpose
376 [array()](\ref af::array) can be used to create a (shallow) copy of a matrix
377 with different dimensions. The total number of elements must remain the same.
378 This function is a wrapper over the moddims() function discussed earlier.
380 # Combining re-ordering functions to enumerate grid coordinates
382 By using a combination of the array restructuring functions, one can quickly code
383 complex manipulation patterns with a few lines of code. For example, consider
384 generating (*x,y*) coordinates for a grid where each axis goes from *1 to n*.
385 Instead of using several loops to populate our arrays we can just use a small
386 combination of the above functions.
388 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
390 af::array xy = join(1,
392 flat( transpose(tile(seq(1, n), 1, n)) )
404 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~