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 //! \addtogroup fn_join
20 //! @{
21 
22 
23 
24 template<typename T1, typename T2>
25 arma_warn_unused
26 inline
27 typename
28 enable_if2
29   <
30   (is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
31   const Glue<T1, T2, glue_join_cols>
32   >::result
join_cols(const T1 & A,const T2 & B)33 join_cols(const T1& A, const T2& B)
34   {
35   arma_extra_debug_sigprint();
36 
37   return Glue<T1, T2, glue_join_cols>(A, B);
38   }
39 
40 
41 
42 template<typename eT, typename T1, typename T2, typename T3>
43 arma_warn_unused
44 inline
45 Mat<eT>
join_cols(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C)46 join_cols(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C)
47   {
48   arma_extra_debug_sigprint();
49 
50   Mat<eT> out;
51 
52   glue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
53 
54   return out;
55   }
56 
57 
58 
59 template<typename eT, typename T1, typename T2, typename T3, typename T4>
60 arma_warn_unused
61 inline
62 Mat<eT>
join_cols(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C,const Base<eT,T4> & D)63 join_cols(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C, const Base<eT,T4>& D)
64   {
65   arma_extra_debug_sigprint();
66 
67   Mat<eT> out;
68 
69   glue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
70 
71   return out;
72   }
73 
74 
75 
76 template<typename T1, typename T2>
77 arma_warn_unused
78 inline
79 typename
80 enable_if2
81   <
82   (is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
83   const Glue<T1, T2, glue_join_cols>
84   >::result
join_vert(const T1 & A,const T2 & B)85 join_vert(const T1& A, const T2& B)
86   {
87   arma_extra_debug_sigprint();
88 
89   return Glue<T1, T2, glue_join_cols>(A, B);
90   }
91 
92 
93 
94 template<typename eT, typename T1, typename T2, typename T3>
95 arma_warn_unused
96 inline
97 Mat<eT>
join_vert(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C)98 join_vert(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C)
99   {
100   arma_extra_debug_sigprint();
101 
102   Mat<eT> out;
103 
104   glue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
105 
106   return out;
107   }
108 
109 
110 
111 template<typename eT, typename T1, typename T2, typename T3, typename T4>
112 arma_warn_unused
113 inline
114 Mat<eT>
join_vert(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C,const Base<eT,T4> & D)115 join_vert(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C, const Base<eT,T4>& D)
116   {
117   arma_extra_debug_sigprint();
118 
119   Mat<eT> out;
120 
121   glue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
122 
123   return out;
124   }
125 
126 
127 
128 template<typename T1, typename T2>
129 arma_warn_unused
130 inline
131 typename
132 enable_if2
133   <
134   (is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
135   const Glue<T1, T2, glue_join_rows>
136   >::result
join_rows(const T1 & A,const T2 & B)137 join_rows(const T1& A, const T2& B)
138   {
139   arma_extra_debug_sigprint();
140 
141   return Glue<T1, T2, glue_join_rows>(A, B);
142   }
143 
144 
145 
146 template<typename eT, typename T1, typename T2, typename T3>
147 arma_warn_unused
148 inline
149 Mat<eT>
join_rows(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C)150 join_rows(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C)
151   {
152   arma_extra_debug_sigprint();
153 
154   Mat<eT> out;
155 
156   glue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
157 
158   return out;
159   }
160 
161 
162 
163 template<typename eT, typename T1, typename T2, typename T3, typename T4>
164 arma_warn_unused
165 inline
166 Mat<eT>
join_rows(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C,const Base<eT,T4> & D)167 join_rows(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C, const Base<eT,T4>& D)
168   {
169   arma_extra_debug_sigprint();
170 
171   Mat<eT> out;
172 
173   glue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
174 
175   return out;
176   }
177 
178 
179 
180 template<typename T1, typename T2>
181 arma_warn_unused
182 inline
183 typename
184 enable_if2
185   <
186   (is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
187   const Glue<T1, T2, glue_join_rows>
188   >::result
join_horiz(const T1 & A,const T2 & B)189 join_horiz(const T1& A, const T2& B)
190   {
191   arma_extra_debug_sigprint();
192 
193   return Glue<T1, T2, glue_join_rows>(A, B);
194   }
195 
196 
197 
198 template<typename eT, typename T1, typename T2, typename T3>
199 arma_warn_unused
200 inline
201 Mat<eT>
join_horiz(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C)202 join_horiz(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C)
203   {
204   arma_extra_debug_sigprint();
205 
206   Mat<eT> out;
207 
208   glue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
209 
210   return out;
211   }
212 
213 
214 
215 template<typename eT, typename T1, typename T2, typename T3, typename T4>
216 arma_warn_unused
217 inline
218 Mat<eT>
join_horiz(const Base<eT,T1> & A,const Base<eT,T2> & B,const Base<eT,T3> & C,const Base<eT,T4> & D)219 join_horiz(const Base<eT,T1>& A, const Base<eT,T2>& B, const Base<eT,T3>& C, const Base<eT,T4>& D)
220   {
221   arma_extra_debug_sigprint();
222 
223   Mat<eT> out;
224 
225   glue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
226 
227   return out;
228   }
229 
230 
231 
232 //
233 // for cubes
234 
235 template<typename T1, typename T2>
236 arma_warn_unused
237 inline
238 const GlueCube<T1, T2, glue_join_slices>
join_slices(const BaseCube<typename T1::elem_type,T1> & A,const BaseCube<typename T1::elem_type,T2> & B)239 join_slices(const BaseCube<typename T1::elem_type,T1>& A, const BaseCube<typename T1::elem_type,T2>& B)
240   {
241   arma_extra_debug_sigprint();
242 
243   return GlueCube<T1, T2, glue_join_slices>(A.get_ref(), B.get_ref());
244   }
245 
246 
247 
248 template<typename T1, typename T2>
249 arma_warn_unused
250 inline
251 Cube<typename T1::elem_type>
join_slices(const Base<typename T1::elem_type,T1> & A,const Base<typename T1::elem_type,T2> & B)252 join_slices(const Base<typename T1::elem_type,T1>& A, const Base<typename T1::elem_type,T2>& B)
253   {
254   arma_extra_debug_sigprint();
255 
256   typedef typename T1::elem_type eT;
257 
258   const quasi_unwrap<T1> UA(A.get_ref());
259   const quasi_unwrap<T2> UB(B.get_ref());
260 
261   arma_debug_assert_same_size(UA.M.n_rows, UA.M.n_cols, UB.M.n_rows, UB.M.n_cols, "join_slices(): incompatible dimensions");
262 
263   Cube<eT> out(UA.M.n_rows, UA.M.n_cols, 2, arma_nozeros_indicator());
264 
265   arrayops::copy(out.slice_memptr(0), UA.M.memptr(), UA.M.n_elem);
266   arrayops::copy(out.slice_memptr(1), UB.M.memptr(), UB.M.n_elem);
267 
268   return out;
269   }
270 
271 
272 
273 template<typename T1, typename T2>
274 arma_warn_unused
275 inline
276 Cube<typename T1::elem_type>
join_slices(const Base<typename T1::elem_type,T1> & A,const BaseCube<typename T1::elem_type,T2> & B)277 join_slices(const Base<typename T1::elem_type,T1>& A, const BaseCube<typename T1::elem_type,T2>& B)
278   {
279   arma_extra_debug_sigprint();
280 
281   typedef typename T1::elem_type eT;
282 
283   const quasi_unwrap<T1> U(A.get_ref());
284 
285   const Cube<eT> M(const_cast<eT*>(U.M.memptr()), U.M.n_rows, U.M.n_cols, 1, false);
286 
287   return join_slices(M,B);
288   }
289 
290 
291 
292 template<typename T1, typename T2>
293 arma_warn_unused
294 inline
295 Cube<typename T1::elem_type>
join_slices(const BaseCube<typename T1::elem_type,T1> & A,const Base<typename T1::elem_type,T2> & B)296 join_slices(const BaseCube<typename T1::elem_type,T1>& A, const Base<typename T1::elem_type,T2>& B)
297   {
298   arma_extra_debug_sigprint();
299 
300   typedef typename T1::elem_type eT;
301 
302   const quasi_unwrap<T2> U(B.get_ref());
303 
304   const Cube<eT> M(const_cast<eT*>(U.M.memptr()), U.M.n_rows, U.M.n_cols, 1, false);
305 
306   return join_slices(A,M);
307   }
308 
309 
310 
311 //
312 // for sparse matrices
313 
314 template<typename T1, typename T2>
315 arma_warn_unused
316 inline
317 const SpGlue<T1, T2, spglue_join_cols>
join_cols(const SpBase<typename T1::elem_type,T1> & A,const SpBase<typename T1::elem_type,T2> & B)318 join_cols(const SpBase<typename T1::elem_type,T1>& A, const SpBase<typename T1::elem_type,T2>& B)
319   {
320   arma_extra_debug_sigprint();
321 
322   return SpGlue<T1, T2, spglue_join_cols>(A.get_ref(), B.get_ref());
323   }
324 
325 
326 
327 template<typename eT, typename T1, typename T2, typename T3>
328 arma_warn_unused
329 inline
330 SpMat<eT>
join_cols(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C)331 join_cols(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C)
332   {
333   arma_extra_debug_sigprint();
334 
335   SpMat<eT> out;
336 
337   spglue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
338 
339   return out;
340   }
341 
342 
343 
344 template<typename eT, typename T1, typename T2, typename T3, typename T4>
345 arma_warn_unused
346 inline
347 SpMat<eT>
join_cols(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C,const SpBase<eT,T4> & D)348 join_cols(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C, const SpBase<eT,T4>& D)
349   {
350   arma_extra_debug_sigprint();
351 
352   SpMat<eT> out;
353 
354   spglue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
355 
356   return out;
357   }
358 
359 
360 
361 template<typename T1, typename T2>
362 arma_warn_unused
363 inline
364 const SpGlue<T1, T2, spglue_join_cols>
join_vert(const SpBase<typename T1::elem_type,T1> & A,const SpBase<typename T1::elem_type,T2> & B)365 join_vert(const SpBase<typename T1::elem_type,T1>& A, const SpBase<typename T1::elem_type,T2>& B)
366   {
367   arma_extra_debug_sigprint();
368 
369   return SpGlue<T1, T2, spglue_join_cols>(A.get_ref(), B.get_ref());
370   }
371 
372 
373 
374 template<typename eT, typename T1, typename T2, typename T3>
375 arma_warn_unused
376 inline
377 SpMat<eT>
join_vert(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C)378 join_vert(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C)
379   {
380   arma_extra_debug_sigprint();
381 
382   SpMat<eT> out;
383 
384   spglue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
385 
386   return out;
387   }
388 
389 
390 
391 template<typename eT, typename T1, typename T2, typename T3, typename T4>
392 arma_warn_unused
393 inline
394 SpMat<eT>
join_vert(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C,const SpBase<eT,T4> & D)395 join_vert(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C, const SpBase<eT,T4>& D)
396   {
397   arma_extra_debug_sigprint();
398 
399   SpMat<eT> out;
400 
401   spglue_join_cols::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
402 
403   return out;
404   }
405 
406 
407 
408 template<typename T1, typename T2>
409 arma_warn_unused
410 inline
411 const SpGlue<T1, T2, spglue_join_rows>
join_rows(const SpBase<typename T1::elem_type,T1> & A,const SpBase<typename T1::elem_type,T2> & B)412 join_rows(const SpBase<typename T1::elem_type,T1>& A, const SpBase<typename T1::elem_type,T2>& B)
413   {
414   arma_extra_debug_sigprint();
415 
416   return SpGlue<T1, T2, spglue_join_rows>(A.get_ref(), B.get_ref());
417   }
418 
419 
420 
421 template<typename eT, typename T1, typename T2, typename T3>
422 arma_warn_unused
423 inline
424 SpMat<eT>
join_rows(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C)425 join_rows(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C)
426   {
427   arma_extra_debug_sigprint();
428 
429   SpMat<eT> out;
430 
431   spglue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
432 
433   return out;
434   }
435 
436 
437 
438 template<typename eT, typename T1, typename T2, typename T3, typename T4>
439 arma_warn_unused
440 inline
441 SpMat<eT>
join_rows(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C,const SpBase<eT,T4> & D)442 join_rows(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C, const SpBase<eT,T4>& D)
443   {
444   arma_extra_debug_sigprint();
445 
446   SpMat<eT> out;
447 
448   spglue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
449 
450   return out;
451   }
452 
453 
454 
455 template<typename T1, typename T2>
456 arma_warn_unused
457 inline
458 const SpGlue<T1, T2, spglue_join_rows>
join_horiz(const SpBase<typename T1::elem_type,T1> & A,const SpBase<typename T1::elem_type,T2> & B)459 join_horiz(const SpBase<typename T1::elem_type,T1>& A, const SpBase<typename T1::elem_type,T2>& B)
460   {
461   arma_extra_debug_sigprint();
462 
463   return SpGlue<T1, T2, spglue_join_rows>(A.get_ref(), B.get_ref());
464   }
465 
466 
467 
468 template<typename eT, typename T1, typename T2, typename T3>
469 arma_warn_unused
470 inline
471 SpMat<eT>
join_horiz(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C)472 join_horiz(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C)
473   {
474   arma_extra_debug_sigprint();
475 
476   SpMat<typename T1::elem_type> out;
477 
478   spglue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref());
479 
480   return out;
481   }
482 
483 
484 
485 template<typename eT, typename T1, typename T2, typename T3, typename T4>
486 arma_warn_unused
487 inline
488 SpMat<eT>
join_horiz(const SpBase<eT,T1> & A,const SpBase<eT,T2> & B,const SpBase<eT,T3> & C,const SpBase<eT,T4> & D)489 join_horiz(const SpBase<eT,T1>& A, const SpBase<eT,T2>& B, const SpBase<eT,T3>& C, const SpBase<eT,T4>& D)
490   {
491   arma_extra_debug_sigprint();
492 
493   SpMat<eT> out;
494 
495   spglue_join_rows::apply(out, A.get_ref(), B.get_ref(), C.get_ref(), D.get_ref());
496 
497   return out;
498   }
499 
500 
501 
502 //! @}
503