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