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 spop_misc
20 //! @{
21 
22 
23 
24 namespace priv
25   {
26   template<typename eT>
27   struct functor_scalar_times
28     {
29     const eT k;
30 
functor_scalar_timespriv::functor_scalar_times31     functor_scalar_times(const eT in_k) : k(in_k) {}
32 
operator ()priv::functor_scalar_times33     arma_inline eT operator()(const eT val) const { return val * k; }
34     };
35   }
36 
37 
38 
39 template<typename T1>
40 inline
41 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_scalar_times> & in)42 spop_scalar_times::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_scalar_times>& in)
43   {
44   arma_extra_debug_sigprint();
45 
46   typedef typename T1::elem_type eT;
47 
48   if(in.aux != eT(0))
49     {
50     out.init_xform(in.m, priv::functor_scalar_times<eT>(in.aux));
51     }
52   else
53     {
54     const SpProxy<T1> P(in.m);
55 
56     out.zeros( P.get_n_rows(), P.get_n_cols() );
57     }
58   }
59 
60 
61 
62 namespace priv
63   {
64   template<typename T>
65   struct functor_cx_scalar_times
66     {
67     typedef std::complex<T> out_eT;
68 
69     const out_eT k;
70 
functor_cx_scalar_timespriv::functor_cx_scalar_times71     functor_cx_scalar_times(const out_eT in_k) : k(in_k) {}
72 
operator ()priv::functor_cx_scalar_times73     arma_inline out_eT operator()(const T val) const { return val * k; }
74     };
75   }
76 
77 
78 
79 template<typename T1>
80 inline
81 void
apply(SpMat<std::complex<typename T1::pod_type>> & out,const mtSpOp<std::complex<typename T1::pod_type>,T1,spop_cx_scalar_times> & in)82 spop_cx_scalar_times::apply(SpMat< std::complex<typename T1::pod_type> >& out, const mtSpOp< std::complex<typename T1::pod_type>, T1, spop_cx_scalar_times >& in)
83   {
84   arma_extra_debug_sigprint();
85 
86   typedef typename T1::pod_type         T;
87   typedef typename std::complex<T> out_eT;
88 
89   if(in.aux_out_eT != out_eT(0))
90     {
91     out.init_xform_mt(in.m, priv::functor_cx_scalar_times<T>(in.aux_out_eT));
92     }
93   else
94     {
95     const SpProxy<T1> P(in.m);
96 
97     out.zeros( P.get_n_rows(), P.get_n_cols() );
98     }
99   }
100 
101 
102 
103 namespace priv
104   {
105   struct functor_square
106     {
107     template<typename eT>
operator ()priv::functor_square108     arma_inline eT operator()(const eT val) const { return val*val; }
109     };
110   }
111 
112 
113 
114 template<typename T1>
115 inline
116 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_square> & in)117 spop_square::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_square>& in)
118   {
119   arma_extra_debug_sigprint();
120 
121   out.init_xform(in.m, priv::functor_square());
122   }
123 
124 
125 
126 namespace priv
127   {
128   struct functor_sqrt
129     {
130     template<typename eT>
operator ()priv::functor_sqrt131     arma_inline eT operator()(const eT val) const { return eop_aux::sqrt(val); }
132     };
133   }
134 
135 
136 
137 template<typename T1>
138 inline
139 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_sqrt> & in)140 spop_sqrt::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_sqrt>& in)
141   {
142   arma_extra_debug_sigprint();
143 
144   out.init_xform(in.m, priv::functor_sqrt());
145   }
146 
147 
148 
149 namespace priv
150   {
151   struct functor_abs
152     {
153     template<typename eT>
operator ()priv::functor_abs154     arma_inline eT operator()(const eT val) const { return eop_aux::arma_abs(val); }
155     };
156   }
157 
158 
159 
160 template<typename T1>
161 inline
162 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_abs> & in)163 spop_abs::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_abs>& in)
164   {
165   arma_extra_debug_sigprint();
166 
167   out.init_xform(in.m, priv::functor_abs());
168   }
169 
170 
171 
172 namespace priv
173   {
174   struct functor_cx_abs
175     {
176     template<typename T>
operator ()priv::functor_cx_abs177     arma_inline T operator()(const std::complex<T>& val) const { return std::abs(val); }
178     };
179   }
180 
181 
182 
183 template<typename T1>
184 inline
185 void
apply(SpMat<typename T1::pod_type> & out,const mtSpOp<typename T1::pod_type,T1,spop_cx_abs> & in)186 spop_cx_abs::apply(SpMat<typename T1::pod_type>& out, const mtSpOp<typename T1::pod_type, T1, spop_cx_abs>& in)
187   {
188   arma_extra_debug_sigprint();
189 
190   out.init_xform_mt(in.m, priv::functor_cx_abs());
191   }
192 
193 
194 
195 namespace priv
196   {
197   struct functor_arg
198     {
199     template<typename eT>
operator ()priv::functor_arg200     arma_inline eT operator()(const eT val) const { return arma_arg<eT>::eval(val); }
201     };
202   }
203 
204 
205 
206 template<typename T1>
207 inline
208 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_arg> & in)209 spop_arg::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_arg>& in)
210   {
211   arma_extra_debug_sigprint();
212 
213   out.init_xform(in.m, priv::functor_arg());
214   }
215 
216 
217 
218 namespace priv
219   {
220   struct functor_cx_arg
221     {
222     template<typename T>
operator ()priv::functor_cx_arg223     arma_inline T operator()(const std::complex<T>& val) const { return std::arg(val); }
224     };
225   }
226 
227 
228 
229 template<typename T1>
230 inline
231 void
apply(SpMat<typename T1::pod_type> & out,const mtSpOp<typename T1::pod_type,T1,spop_cx_arg> & in)232 spop_cx_arg::apply(SpMat<typename T1::pod_type>& out, const mtSpOp<typename T1::pod_type, T1, spop_cx_arg>& in)
233   {
234   arma_extra_debug_sigprint();
235 
236   out.init_xform_mt(in.m, priv::functor_cx_arg());
237   }
238 
239 
240 
241 namespace priv
242   {
243   struct functor_real
244     {
245     template<typename T>
operator ()priv::functor_real246     arma_inline T operator()(const std::complex<T>& val) const { return val.real(); }
247     };
248   }
249 
250 
251 
252 template<typename T1>
253 inline
254 void
apply(SpMat<typename T1::pod_type> & out,const mtSpOp<typename T1::pod_type,T1,spop_real> & in)255 spop_real::apply(SpMat<typename T1::pod_type>& out, const mtSpOp<typename T1::pod_type, T1, spop_real>& in)
256   {
257   arma_extra_debug_sigprint();
258 
259   out.init_xform_mt(in.m, priv::functor_real());
260   }
261 
262 
263 
264 namespace priv
265   {
266   struct functor_imag
267     {
268     template<typename T>
operator ()priv::functor_imag269     arma_inline T operator()(const std::complex<T>& val) const { return val.imag(); }
270     };
271   }
272 
273 
274 
275 template<typename T1>
276 inline
277 void
apply(SpMat<typename T1::pod_type> & out,const mtSpOp<typename T1::pod_type,T1,spop_imag> & in)278 spop_imag::apply(SpMat<typename T1::pod_type>& out, const mtSpOp<typename T1::pod_type, T1, spop_imag>& in)
279   {
280   arma_extra_debug_sigprint();
281 
282   out.init_xform_mt(in.m, priv::functor_imag());
283   }
284 
285 
286 
287 namespace priv
288   {
289   struct functor_conj
290     {
291     template<typename eT>
operator ()priv::functor_conj292     arma_inline eT operator()(const eT val) const { return eop_aux::conj(val); }
293     };
294   }
295 
296 
297 
298 template<typename T1>
299 inline
300 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_conj> & in)301 spop_conj::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_conj>& in)
302   {
303   arma_extra_debug_sigprint();
304 
305   out.init_xform(in.m, priv::functor_conj());
306   }
307 
308 
309 
310 template<typename T1>
311 inline
312 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_repelem> & in)313 spop_repelem::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1, spop_repelem>& in)
314   {
315   arma_extra_debug_sigprint();
316 
317   typedef typename T1::elem_type eT;
318 
319   const unwrap_spmat<T1> U(in.m);
320   const SpMat<eT>& X =   U.M;
321 
322   const uword copies_per_row = in.aux_uword_a;
323   const uword copies_per_col = in.aux_uword_b;
324 
325   const uword out_n_rows = X.n_rows * copies_per_row;
326   const uword out_n_cols = X.n_cols * copies_per_col;
327   const uword out_nnz    = X.n_nonzero * copies_per_row * copies_per_col;
328 
329   if( (out_n_rows > 0) && (out_n_cols > 0) && (out_nnz > 0) )
330     {
331     umat    locs(2, out_nnz, arma_nozeros_indicator());
332     Col<eT> vals(   out_nnz, arma_nozeros_indicator());
333 
334     uword* locs_mem = locs.memptr();
335     eT*    vals_mem = vals.memptr();
336 
337     typename SpMat<eT>::const_iterator X_it  = X.begin();
338     typename SpMat<eT>::const_iterator X_end = X.end();
339 
340     for(; X_it != X_end; ++X_it)
341       {
342       const uword col_base = copies_per_col * X_it.col();
343       const uword row_base = copies_per_row * X_it.row();
344 
345       const eT X_val = (*X_it);
346 
347       for(uword cols = 0; cols < copies_per_col; cols++)
348       for(uword rows = 0; rows < copies_per_row; rows++)
349         {
350         (*locs_mem) = row_base + rows;  ++locs_mem;
351         (*locs_mem) = col_base + cols;  ++locs_mem;
352 
353         (*vals_mem) = X_val;  ++vals_mem;
354         }
355       }
356 
357     out = SpMat<eT>(locs, vals, out_n_rows, out_n_cols);
358     }
359   else
360     {
361     out.zeros(out_n_rows, out_n_cols);
362     }
363   }
364 
365 
366 
367 template<typename T1>
368 inline
369 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_reshape> & in)370 spop_reshape::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1, spop_reshape>& in)
371   {
372   arma_extra_debug_sigprint();
373 
374   out = in.m;
375 
376   out.reshape(in.aux_uword_a, in.aux_uword_b);
377   }
378 
379 
380 
381 template<typename T1>
382 inline
383 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_resize> & in)384 spop_resize::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1, spop_resize>& in)
385   {
386   arma_extra_debug_sigprint();
387 
388   out = in.m;
389 
390   out.resize(in.aux_uword_a, in.aux_uword_b);
391   }
392 
393 
394 
395 namespace priv
396   {
397   struct functor_floor
398     {
399     template<typename eT>
operator ()priv::functor_floor400     arma_inline eT operator()(const eT val) const { return eop_aux::floor(val); }
401     };
402   }
403 
404 
405 
406 template<typename T1>
407 inline
408 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_floor> & in)409 spop_floor::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_floor>& in)
410   {
411   arma_extra_debug_sigprint();
412 
413   out.init_xform(in.m, priv::functor_floor());
414   }
415 
416 
417 
418 namespace priv
419   {
420   struct functor_ceil
421     {
422     template<typename eT>
operator ()priv::functor_ceil423     arma_inline eT operator()(const eT val) const { return eop_aux::ceil(val); }
424     };
425   }
426 
427 
428 
429 template<typename T1>
430 inline
431 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_ceil> & in)432 spop_ceil::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_ceil>& in)
433   {
434   arma_extra_debug_sigprint();
435 
436   out.init_xform(in.m, priv::functor_ceil());
437   }
438 
439 
440 
441 namespace priv
442   {
443   struct functor_round
444     {
445     template<typename eT>
operator ()priv::functor_round446     arma_inline eT operator()(const eT val) const { return eop_aux::round(val); }
447     };
448   }
449 
450 
451 
452 template<typename T1>
453 inline
454 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_round> & in)455 spop_round::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_round>& in)
456   {
457   arma_extra_debug_sigprint();
458 
459   out.init_xform(in.m, priv::functor_round());
460   }
461 
462 
463 
464 namespace priv
465   {
466   struct functor_trunc
467     {
468     template<typename eT>
operator ()priv::functor_trunc469     arma_inline eT operator()(const eT val) const { return eop_aux::trunc(val); }
470     };
471   }
472 
473 
474 
475 template<typename T1>
476 inline
477 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_trunc> & in)478 spop_trunc::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_trunc>& in)
479   {
480   arma_extra_debug_sigprint();
481 
482   out.init_xform(in.m, priv::functor_trunc());
483   }
484 
485 
486 
487 namespace priv
488   {
489   struct functor_sign
490     {
491     template<typename eT>
operator ()priv::functor_sign492     arma_inline eT operator()(const eT val) const { return arma_sign(val); }
493     };
494   }
495 
496 
497 
498 template<typename T1>
499 inline
500 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_sign> & in)501 spop_sign::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_sign>& in)
502   {
503   arma_extra_debug_sigprint();
504 
505   out.init_xform(in.m, priv::functor_sign());
506   }
507 
508 
509 
510 template<typename T1>
511 inline
512 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_diagvec> & in)513 spop_diagvec::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_diagvec>& in)
514   {
515   arma_extra_debug_sigprint();
516 
517   typedef typename T1::elem_type eT;
518 
519   const unwrap_spmat<T1> U(in.m);
520 
521   const SpMat<eT>& X = U.M;
522 
523   const uword a = in.aux_uword_a;
524   const uword b = in.aux_uword_b;
525 
526   const uword row_offset = (b >  0) ? a : 0;
527   const uword col_offset = (b == 0) ? a : 0;
528 
529   arma_debug_check_bounds
530     (
531     ((row_offset > 0) && (row_offset >= X.n_rows)) || ((col_offset > 0) && (col_offset >= X.n_cols)),
532     "diagvec(): requested diagonal out of bounds"
533     );
534 
535   const uword len = (std::min)(X.n_rows - row_offset, X.n_cols - col_offset);
536 
537   Col<eT> cache(len, arma_nozeros_indicator());
538   eT* cache_mem = cache.memptr();
539 
540   uword n_nonzero = 0;
541 
542   for(uword i=0; i < len; ++i)
543     {
544     const eT val = X.at(i + row_offset, i + col_offset);
545 
546     cache_mem[i] = val;
547 
548     n_nonzero += (val != eT(0)) ? uword(1) : uword(0);
549     }
550 
551   out.reserve(len, 1, n_nonzero);
552 
553   uword count = 0;
554   for(uword i=0; i < len; ++i)
555     {
556     const eT val = cache_mem[i];
557 
558     if(val != eT(0))
559       {
560       access::rw(out.row_indices[count]) = i;
561       access::rw(out.values[count])      = val;
562       ++count;
563       }
564     }
565 
566   access::rw(out.col_ptrs[0]) = 0;
567   access::rw(out.col_ptrs[1]) = n_nonzero;
568   }
569 
570 
571 
572 template<typename T1>
573 inline
574 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_flipud> & in)575 spop_flipud::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_flipud>& in)
576   {
577   arma_extra_debug_sigprint();
578 
579   out = reverse(in.m, 0);
580   }
581 
582 
583 
584 template<typename T1>
585 inline
586 void
apply(SpMat<typename T1::elem_type> & out,const SpOp<T1,spop_fliplr> & in)587 spop_fliplr::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_fliplr>& in)
588   {
589   arma_extra_debug_sigprint();
590 
591   out = reverse(in.m, 1);
592   }
593 
594 
595 
596 //! @}
597