File: matrix_manipulation.md

package info (click to toggle)
arrayfire 3.3.2%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 109,016 kB
  • sloc: cpp: 127,909; lisp: 6,878; python: 3,923; ansic: 1,051; sh: 347; makefile: 338; xml: 175
file content (341 lines) | stat: -rw-r--r-- 11,198 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
Matrix Manipulation {#matrixmanipulation}
===================

Many different kinds of [matrix manipulation routines](\ref manip_mat) 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()](\ref af::array) to adjust the dimensions of an array
* [transpose](\ref af::array::T) a matrix or vector with shorthand notation

## flat()
The __flat()__ function flattens an array to one dimension.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [3 3 1 1]
    1.0000     4.0000     7.0000
    2.0000     5.0000     8.0000
    3.0000     6.0000     9.0000

flat(a) [9 1 1 1]
    1.0000
    2.0000
    3.0000
    4.0000
    5.0000
    6.0000
    7.0000
    8.0000
    9.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The flat function has the following overloads:
> __array af::flat(const array& in)__
> --  flatten an array

> __af_err af_flat(af_array* out, const af_array in)__
> --  C interface for flat() function


## flip()
The __flip()__ function flips the contents of an array along a chosen dimension.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [5 2 1 1]
    1.0000     6.0000
    2.0000     7.0000
    3.0000     8.0000
    4.0000     9.0000
    5.0000    10.0000

flip(a, 0) [5 2 1 1]
    5.0000    10.0000
    4.0000     9.0000
    3.0000     8.0000
    2.0000     7.0000
    1.0000     6.0000

flip(a, 1) [5 2 1 1]
    6.0000     1.0000
    7.0000     2.0000
    8.0000     3.0000
    9.0000     4.0000
   10.0000     5.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The flip function has the following overloads:
> __array af::flip(const array &in, const unsigned dim)__
> --  flips an array along a dimension 
> __af_err af_flip(af_array *out, const af_array in, const unsigned dim)__
> --  C interface for flip()

## join()
The __join()__ function can join up to 4 arrays together.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [5 1 1 1]
    1.0000
    2.0000
    3.0000
    4.0000
    5.0000

join(0, a, a) [10 1 1 1]
    1.0000
    2.0000
    3.0000
    4.0000
    5.0000
    1.0000
    2.0000
    3.0000
    4.0000
    5.0000

join(1, a, a) [5 2 1 1]
    1.0000     1.0000
    2.0000     2.0000
    3.0000     3.0000
    4.0000     4.0000
    5.0000     5.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The join function has several overloads:
> __array af::join(const int dim, const array &first, const array &second)__
> --  Joins 2 arrays along a dimension

> __array af::join(const int dim, const array &first, const array &second, const array &third)__
> --  Joins 3 arrays along a dimension.

> __array af::join(const int dim, const array &first, const array &second, const array &third, const array &fourth)__
> --  Joins 4 arrays along a dimension

> __af_err af_join(af_array *out, const int dim, const af_array first, const af_array second)__
> --  C interface function to join 2 arrays along a dimension

> __af_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs)__
> --  C interface function to join up to 10 arrays along a dimension

## 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.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [8 1 1 1]
    1.0000
    2.0000
    1.0000
    2.0000
    1.0000
    2.0000
    1.0000
    2.0000

af::dim4 new_dims(2, 4);
moddims(a, new_dims) [2 4 1 1]
    1.0000     1.0000     1.0000     1.0000
    2.0000     2.0000     2.0000     2.0000

moddims(a, a.elements(), 1, 1, 1) [8 1 1 1]
    1.0000
    2.0000
    1.0000
    2.0000
    1.0000
    2.0000
    1.0000
    2.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The moddims function has several overloads:
> __array af::moddims(const array &in, const unsigned ndims, const dim_t *const dims)__
> --  mods number of dimensions to match _ndims_ as specidied in the array _dims_

> __array af::moddims(const array &in, const dim4 &dims)__
> --  mods dimensions as specified by _dims_

> __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)__
> --  mods dimensions of an array

> __af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims)__
> --  C interface to mod dimensions of an array

## reorder()
The __reorder()__ function changes the order of the dimensions within the array.
This actually alters the underlying data of the array.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [2 2 3 1]
    1.0000     3.0000
    2.0000     4.0000

    1.0000     3.0000
    2.0000     4.0000

    1.0000     3.0000
    2.0000     4.0000


reorder(a, 1, 0, 2) [2 2 3 1]  //equivalent to a transpose
    1.0000     2.0000
    3.0000     4.0000

    1.0000     2.0000
    3.0000     4.0000

    1.0000     2.0000
    3.0000     4.0000


reorder(a, 2, 0, 1) [3 2 2 1]
    1.0000     2.0000
    1.0000     2.0000
    1.0000     2.0000

    3.0000     4.0000
    3.0000     4.0000
    3.0000     4.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reorder function the following several overloads:
> __array af::reorder(const array &in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3)__
> --  Reorders dimensions of an array

> __af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w)__
> --  C interface for reordering function

## shift()
The __shift()__ function shifts data in a circular buffer fashion along a chosen dimension.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [3 5 1 1]
    0.0000     0.0000     0.0000     0.0000     0.0000
    3.0000     4.0000     5.0000     1.0000     2.0000
    3.0000     4.0000     5.0000     1.0000     2.0000

shift(a, 0, 2 ) [3 5 1 1]
    0.0000     0.0000     0.0000     0.0000     0.0000
    1.0000     2.0000     3.0000     4.0000     5.0000
    1.0000     2.0000     3.0000     4.0000     5.0000

shift(a, -1, 2 ) [3 5 1 1]
    1.0000     2.0000     3.0000     4.0000     5.0000
    1.0000     2.0000     3.0000     4.0000     5.0000
    0.0000     0.0000     0.0000     0.0000     0.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The shift function has the following overloads:
> __array af::shift(const array &in, const int x, const int y=0, const int z=0, const int w=0)__
> --  Shifts array along specified dimensions

> __af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w)__
> --  C interface for shifting an array

## tile()
The __tile()__ function repeats an array along a dimension
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [3 1 1 1]
    1.0000
    2.0000
    3.0000

tile(a, 2) [6 1 1 1]
    1.0000
    2.0000
    3.0000
    1.0000
    2.0000
    3.0000

tile(a, 2, 2) [6 2 1 1]
    1.0000     1.0000
    2.0000     2.0000
    3.0000     3.0000
    1.0000     1.0000
    2.0000     2.0000
    3.0000     3.0000

af::dim4 tile_dims(1, 2, 3);
tile(a, tile_dims) [3 2 3 1]
    1.0000     1.0000
    2.0000     2.0000
    3.0000     3.0000

    1.0000     1.0000
    2.0000     2.0000
    3.0000     3.0000

    1.0000     1.0000
    2.0000     2.0000
    3.0000     3.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The tile function has several overloads:
> __array af::tile(const array &in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1)__
> --  Tiles array along specified dimensions

> __array af::tile(const array &in, const dim4 &dims)__  
> --  Tile an array according to a dim4 object

> __af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w)__
> --  C interface for tiling an array

## transpose()
The __transpose()__ function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
a [3 3 1 1]
    1.0000     3.0000     3.0000
    2.0000     1.0000     3.0000
    2.0000     2.0000     1.0000

transpose(a) [3 3 1 1]
    1.0000     2.0000     2.0000
    3.0000     1.0000     2.0000
    3.0000     3.0000     1.0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The transpose function has several overloads:
> __array af::transpose(const array &in, const bool conjugate=false)__
> --   Transposes a matrix.

> __void af::transposeInPlace(array &in, const bool conjugate=false)__
> --   Transposes a matrix in-place.

> __af_err af_transpose(af_array *out, af_array in, const bool conjugate)__
> --   C interface to transpose a matrix.

> __af_err af_transpose_inplace(af_array in, const bool conjugate)__
> --   C interface to transpose a matrix in-place.

[array()](\ref af::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.

\snippet test/matrix_manipulation.cpp ex_matrix_manipulation_moddims

The [T()](\ref af::array::T) and [H()](\ref af::array::H) methods can be
used to form the [matrix or vector transpose](\ref af::array::T) .

\snippet test/matrix_manipulation.cpp ex_matrix_manipulation_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.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
unsigned n=3;
af::array xy = join(1
                tile(seq(1, n), n)
                flat( transpose(tile(seq(1, n), 1, n)) )
                   );
xy [9 2 1 1]
    1.0000     1.0000
    2.0000     1.0000
    3.0000     1.0000
    1.0000     2.0000
    2.0000     2.0000
    3.0000     2.0000
    1.0000     3.0000
    2.0000     3.0000
    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!