1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17
18
19
20 //! \addtogroup op_vectorise
21 //! @{
22
23
24
25 template<typename T1>
26 inline
27 void
apply(Mat<typename T1::elem_type> & out,const Op<T1,op_vectorise_col> & in)28 op_vectorise_col::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_vectorise_col>& in)
29 {
30 arma_extra_debug_sigprint();
31
32 op_vectorise_col::apply_direct(out, in.m);
33 }
34
35
36
37 template<typename T1>
38 inline
39 void
apply_direct(Mat<typename T1::elem_type> & out,const T1 & expr)40 op_vectorise_col::apply_direct(Mat<typename T1::elem_type>& out, const T1& expr)
41 {
42 arma_extra_debug_sigprint();
43
44 typedef typename T1::elem_type eT;
45
46 // allow detection of in-place operation
47 if(is_Mat<T1>::value || (arma_config::openmp && Proxy<T1>::use_mp))
48 {
49 const unwrap<T1> U(expr);
50
51 if(&out == &(U.M))
52 {
53 // output matrix is the same as the input matrix
54
55 out.set_size(out.n_elem, 1); // set_size() doesn't destroy data as long as the number of elements in the matrix remains the same
56 }
57 else
58 {
59 out.set_size(U.M.n_elem, 1);
60
61 arrayops::copy(out.memptr(), U.M.memptr(), U.M.n_elem);
62 }
63 }
64 else
65 if(is_subview<T1>::value)
66 {
67 const subview<eT>& sv = reinterpret_cast< const subview<eT>& >(expr);
68
69 if(&out == &(sv.m))
70 {
71 Mat<eT> tmp;
72
73 op_vectorise_col::apply_subview(tmp, sv);
74
75 out.steal_mem(tmp);
76 }
77 else
78 {
79 op_vectorise_col::apply_subview(out, sv);
80 }
81 }
82 else
83 {
84 const Proxy<T1> P(expr);
85
86 const bool is_alias = P.is_alias(out);
87
88 if(is_Mat<typename Proxy<T1>::stored_type>::value)
89 {
90 const quasi_unwrap<typename Proxy<T1>::stored_type> U(P.Q);
91
92 if(is_alias)
93 {
94 Mat<eT> tmp(U.M.memptr(), U.M.n_elem, 1);
95
96 out.steal_mem(tmp);
97 }
98 else
99 {
100 out.set_size(U.M.n_elem, 1);
101
102 arrayops::copy(out.memptr(), U.M.memptr(), U.M.n_elem);
103 }
104 }
105 else
106 {
107 if(is_alias)
108 {
109 Mat<eT> tmp;
110
111 op_vectorise_col::apply_proxy(tmp, P);
112
113 out.steal_mem(tmp);
114 }
115 else
116 {
117 op_vectorise_col::apply_proxy(out, P);
118 }
119 }
120 }
121 }
122
123
124
125 template<typename eT>
126 inline
127 void
apply_subview(Mat<eT> & out,const subview<eT> & sv)128 op_vectorise_col::apply_subview(Mat<eT>& out, const subview<eT>& sv)
129 {
130 arma_extra_debug_sigprint();
131
132 const uword sv_n_rows = sv.n_rows;
133 const uword sv_n_cols = sv.n_cols;
134
135 out.set_size(sv.n_elem, 1);
136
137 eT* out_mem = out.memptr();
138
139 for(uword col=0; col < sv_n_cols; ++col)
140 {
141 arrayops::copy(out_mem, sv.colptr(col), sv_n_rows);
142
143 out_mem += sv_n_rows;
144 }
145 }
146
147
148
149 template<typename T1>
150 inline
151 void
apply_proxy(Mat<typename T1::elem_type> & out,const Proxy<T1> & P)152 op_vectorise_col::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>& P)
153 {
154 arma_extra_debug_sigprint();
155
156 typedef typename T1::elem_type eT;
157
158 const uword N = P.get_n_elem();
159
160 out.set_size(N, 1);
161
162 eT* outmem = out.memptr();
163
164 if(Proxy<T1>::use_at == false)
165 {
166 // TODO: add handling of aligned access ?
167
168 typename Proxy<T1>::ea_type A = P.get_ea();
169
170 uword i,j;
171
172 for(i=0, j=1; j < N; i+=2, j+=2)
173 {
174 const eT tmp_i = A[i];
175 const eT tmp_j = A[j];
176
177 outmem[i] = tmp_i;
178 outmem[j] = tmp_j;
179 }
180
181 if(i < N)
182 {
183 outmem[i] = A[i];
184 }
185 }
186 else
187 {
188 const uword n_rows = P.get_n_rows();
189 const uword n_cols = P.get_n_cols();
190
191 if(n_rows == 1)
192 {
193 for(uword i=0; i < n_cols; ++i)
194 {
195 outmem[i] = P.at(0,i);
196 }
197 }
198 else
199 {
200 for(uword col=0; col < n_cols; ++col)
201 for(uword row=0; row < n_rows; ++row)
202 {
203 *outmem = P.at(row,col);
204 outmem++;
205 }
206 }
207 }
208 }
209
210
211
212 template<typename T1>
213 inline
214 void
apply(Mat<typename T1::elem_type> & out,const Op<T1,op_vectorise_row> & in)215 op_vectorise_row::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_vectorise_row>& in)
216 {
217 arma_extra_debug_sigprint();
218
219 op_vectorise_row::apply_direct(out, in.m);
220 }
221
222
223
224 template<typename T1>
225 inline
226 void
apply_direct(Mat<typename T1::elem_type> & out,const T1 & expr)227 op_vectorise_row::apply_direct(Mat<typename T1::elem_type>& out, const T1& expr)
228 {
229 arma_extra_debug_sigprint();
230
231 typedef typename T1::elem_type eT;
232
233 const Proxy<T1> P(expr);
234
235 if(P.is_alias(out))
236 {
237 Mat<eT> tmp;
238
239 op_vectorise_row::apply_proxy(tmp, P);
240
241 out.steal_mem(tmp);
242 }
243 else
244 {
245 op_vectorise_row::apply_proxy(out, P);
246 }
247 }
248
249
250
251 template<typename T1>
252 inline
253 void
apply_proxy(Mat<typename T1::elem_type> & out,const Proxy<T1> & P)254 op_vectorise_row::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>& P)
255 {
256 arma_extra_debug_sigprint();
257
258 typedef typename T1::elem_type eT;
259
260 const uword n_rows = P.get_n_rows();
261 const uword n_cols = P.get_n_cols();
262 const uword n_elem = P.get_n_elem();
263
264 out.set_size(1, n_elem);
265
266 eT* outmem = out.memptr();
267
268 if(n_cols == 1)
269 {
270 if(is_Mat<typename Proxy<T1>::stored_type>::value)
271 {
272 const unwrap<typename Proxy<T1>::stored_type> tmp(P.Q);
273
274 arrayops::copy(out.memptr(), tmp.M.memptr(), n_elem);
275 }
276 else
277 {
278 for(uword i=0; i < n_elem; ++i) { outmem[i] = P.at(i,0); }
279 }
280 }
281 else
282 {
283 for(uword row=0; row < n_rows; ++row)
284 {
285 uword i,j;
286
287 for(i=0, j=1; j < n_cols; i+=2, j+=2)
288 {
289 const eT tmp_i = P.at(row,i);
290 const eT tmp_j = P.at(row,j);
291
292 *outmem = tmp_i; outmem++;
293 *outmem = tmp_j; outmem++;
294 }
295
296 if(i < n_cols)
297 {
298 *outmem = P.at(row,i); outmem++;
299 }
300 }
301 }
302 }
303
304
305
306 template<typename T1>
307 inline
308 void
apply(Mat<typename T1::elem_type> & out,const Op<T1,op_vectorise_all> & in)309 op_vectorise_all::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_vectorise_all>& in)
310 {
311 arma_extra_debug_sigprint();
312
313 const uword dim = in.aux_uword_a;
314
315 if(dim == 0)
316 {
317 op_vectorise_col::apply_direct(out, in.m);
318 }
319 else
320 {
321 op_vectorise_row::apply_direct(out, in.m);
322 }
323 }
324
325
326
327 //
328
329
330
331 template<typename T1>
332 inline
333 void
apply(Mat<typename T1::elem_type> & out,const CubeToMatOp<T1,op_vectorise_cube_col> & in)334 op_vectorise_cube_col::apply(Mat<typename T1::elem_type>& out, const CubeToMatOp<T1, op_vectorise_cube_col>& in)
335 {
336 arma_extra_debug_sigprint();
337
338 typedef typename T1::elem_type eT;
339
340 if(is_same_type< T1, subview_cube<eT> >::yes)
341 {
342 op_vectorise_cube_col::apply_subview(out, reinterpret_cast< const subview_cube<eT>& >(in.m));
343 }
344 else
345 {
346 if(is_Cube<T1>::value || (arma_config::openmp && ProxyCube<T1>::use_mp))
347 {
348 op_vectorise_cube_col::apply_unwrap(out, in.m);
349 }
350 else
351 {
352 op_vectorise_cube_col::apply_proxy(out, in.m);
353 }
354 }
355 }
356
357
358
359 template<typename eT>
360 inline
361 void
apply_subview(Mat<eT> & out,const subview_cube<eT> & sv)362 op_vectorise_cube_col::apply_subview(Mat<eT>& out, const subview_cube<eT>& sv)
363 {
364 arma_extra_debug_sigprint();
365
366 const uword sv_nr = sv.n_rows;
367 const uword sv_nc = sv.n_cols;
368 const uword sv_ns = sv.n_slices;
369
370 out.set_size(sv.n_elem, 1);
371
372 eT* out_mem = out.memptr();
373
374 for(uword s=0; s < sv_ns; ++s)
375 for(uword c=0; c < sv_nc; ++c)
376 {
377 arrayops::copy(out_mem, sv.slice_colptr(s,c), sv_nr);
378
379 out_mem += sv_nr;
380 }
381 }
382
383
384
385 template<typename T1>
386 inline
387 void
apply_unwrap(Mat<typename T1::elem_type> & out,const T1 & expr)388 op_vectorise_cube_col::apply_unwrap(Mat<typename T1::elem_type>& out, const T1& expr)
389 {
390 arma_extra_debug_sigprint();
391
392 const unwrap_cube<T1> U(expr);
393
394 out.set_size(U.M.n_elem, 1);
395
396 arrayops::copy(out.memptr(), U.M.memptr(), U.M.n_elem);
397 }
398
399
400
401 template<typename T1>
402 inline
403 void
apply_proxy(Mat<typename T1::elem_type> & out,const T1 & expr)404 op_vectorise_cube_col::apply_proxy(Mat<typename T1::elem_type>& out, const T1& expr)
405 {
406 arma_extra_debug_sigprint();
407
408 typedef typename T1::elem_type eT;
409
410 const ProxyCube<T1> P(expr);
411
412 if(is_Cube<typename ProxyCube<T1>::stored_type>::value)
413 {
414 op_vectorise_cube_col::apply_unwrap(out, P.Q);
415
416 return;
417 }
418
419 const uword N = P.get_n_elem();
420
421 out.set_size(N, 1);
422
423 eT* outmem = out.memptr();
424
425 if(ProxyCube<T1>::use_at == false)
426 {
427 typename ProxyCube<T1>::ea_type A = P.get_ea();
428
429 uword i,j;
430
431 for(i=0, j=1; j < N; i+=2, j+=2)
432 {
433 const eT tmp_i = A[i];
434 const eT tmp_j = A[j];
435
436 outmem[i] = tmp_i;
437 outmem[j] = tmp_j;
438 }
439
440 if(i < N)
441 {
442 outmem[i] = A[i];
443 }
444 }
445 else
446 {
447 const uword nr = P.get_n_rows();
448 const uword nc = P.get_n_cols();
449 const uword ns = P.get_n_slices();
450
451 for(uword s=0; s < ns; ++s)
452 for(uword c=0; c < nc; ++c)
453 for(uword r=0; r < nr; ++r)
454 {
455 *outmem = P.at(r,c,s);
456 outmem++;
457 }
458 }
459 }
460
461
462
463 //! @}
464