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 SpBase
20 //! @{
21
22
23
24 template<typename elem_type, typename derived>
25 arma_inline
26 const derived&
get_ref() const27 SpBase<elem_type,derived>::get_ref() const
28 {
29 return static_cast<const derived&>(*this);
30 }
31
32
33
34 template<typename elem_type, typename derived>
35 arma_inline
36 bool
is_alias(const SpMat<elem_type> & X) const37 SpBase<elem_type,derived>::is_alias(const SpMat<elem_type>& X) const
38 {
39 return (*this).get_ref().is_alias(X);
40 }
41
42
43
44 template<typename elem_type, typename derived>
45 inline
46 arma_warn_unused
47 const SpOp<derived, spop_htrans>
t() const48 SpBase<elem_type,derived>::t() const
49 {
50 return SpOp<derived,spop_htrans>( (*this).get_ref() );
51 }
52
53
54 template<typename elem_type, typename derived>
55 inline
56 arma_warn_unused
57 const SpOp<derived, spop_htrans>
ht() const58 SpBase<elem_type,derived>::ht() const
59 {
60 return SpOp<derived, spop_htrans>( (*this).get_ref() );
61 }
62
63
64
65 template<typename elem_type, typename derived>
66 inline
67 arma_warn_unused
68 const SpOp<derived, spop_strans>
st() const69 SpBase<elem_type,derived>::st() const
70 {
71 return SpOp<derived, spop_strans>( (*this).get_ref() );
72 }
73
74
75
76 template<typename elem_type, typename derived>
77 arma_cold
78 inline
79 void
print(const std::string extra_text) const80 SpBase<elem_type,derived>::print(const std::string extra_text) const
81 {
82 arma_extra_debug_sigprint();
83
84 const unwrap_spmat<derived> tmp( (*this).get_ref() );
85
86 if(extra_text.length() != 0)
87 {
88 const std::streamsize orig_width = get_cout_stream().width();
89
90 get_cout_stream() << extra_text << '\n';
91
92 get_cout_stream().width(orig_width);
93 }
94
95 arma_ostream::print(get_cout_stream(), tmp.M, true);
96 }
97
98
99
100 template<typename elem_type, typename derived>
101 arma_cold
102 inline
103 void
print(std::ostream & user_stream,const std::string extra_text) const104 SpBase<elem_type,derived>::print(std::ostream& user_stream, const std::string extra_text) const
105 {
106 arma_extra_debug_sigprint();
107
108 const unwrap_spmat<derived> tmp( (*this).get_ref() );
109
110 if(extra_text.length() != 0)
111 {
112 const std::streamsize orig_width = user_stream.width();
113
114 user_stream << extra_text << '\n';
115
116 user_stream.width(orig_width);
117 }
118
119 arma_ostream::print(user_stream, tmp.M, true);
120 }
121
122
123
124 template<typename elem_type, typename derived>
125 arma_cold
126 inline
127 void
raw_print(const std::string extra_text) const128 SpBase<elem_type,derived>::raw_print(const std::string extra_text) const
129 {
130 arma_extra_debug_sigprint();
131
132 const unwrap_spmat<derived> tmp( (*this).get_ref() );
133
134 if(extra_text.length() != 0)
135 {
136 const std::streamsize orig_width = get_cout_stream().width();
137
138 get_cout_stream() << extra_text << '\n';
139
140 get_cout_stream().width(orig_width);
141 }
142
143 arma_ostream::print(get_cout_stream(), tmp.M, false);
144 }
145
146
147
148 template<typename elem_type, typename derived>
149 arma_cold
150 inline
151 void
raw_print(std::ostream & user_stream,const std::string extra_text) const152 SpBase<elem_type,derived>::raw_print(std::ostream& user_stream, const std::string extra_text) const
153 {
154 arma_extra_debug_sigprint();
155
156 const unwrap_spmat<derived> tmp( (*this).get_ref() );
157
158 if(extra_text.length() != 0)
159 {
160 const std::streamsize orig_width = user_stream.width();
161
162 user_stream << extra_text << '\n';
163
164 user_stream.width(orig_width);
165 }
166
167 arma_ostream::print(user_stream, tmp.M, false);
168 }
169
170
171
172 template<typename elem_type, typename derived>
173 arma_cold
174 inline
175 void
print_dense(const std::string extra_text) const176 SpBase<elem_type, derived>::print_dense(const std::string extra_text) const
177 {
178 arma_extra_debug_sigprint();
179
180 const unwrap_spmat<derived> tmp( (*this).get_ref() );
181
182 if(extra_text.length() != 0)
183 {
184 const std::streamsize orig_width = get_cout_stream().width();
185
186 get_cout_stream() << extra_text << '\n';
187
188 get_cout_stream().width(orig_width);
189 }
190
191 arma_ostream::print_dense(get_cout_stream(), tmp.M, true);
192 }
193
194
195
196 template<typename elem_type, typename derived>
197 arma_cold
198 inline
199 void
print_dense(std::ostream & user_stream,const std::string extra_text) const200 SpBase<elem_type, derived>::print_dense(std::ostream& user_stream, const std::string extra_text) const
201 {
202 arma_extra_debug_sigprint();
203
204 const unwrap_spmat<derived> tmp( (*this).get_ref() );
205
206 if(extra_text.length() != 0)
207 {
208 const std::streamsize orig_width = user_stream.width();
209
210 user_stream << extra_text << '\n';
211
212 user_stream.width(orig_width);
213 }
214
215 arma_ostream::print_dense(user_stream, tmp.M, true);
216 }
217
218
219
220 template<typename elem_type, typename derived>
221 arma_cold
222 inline
223 void
raw_print_dense(const std::string extra_text) const224 SpBase<elem_type, derived>::raw_print_dense(const std::string extra_text) const
225 {
226 arma_extra_debug_sigprint();
227
228 const unwrap_spmat<derived> tmp( (*this).get_ref() );
229
230 if(extra_text.length() != 0)
231 {
232 const std::streamsize orig_width = get_cout_stream().width();
233
234 get_cout_stream() << extra_text << '\n';
235
236 get_cout_stream().width(orig_width);
237 }
238
239 arma_ostream::print_dense(get_cout_stream(), tmp.M, false);
240 }
241
242
243
244 template<typename elem_type, typename derived>
245 arma_cold
246 inline
247 void
raw_print_dense(std::ostream & user_stream,const std::string extra_text) const248 SpBase<elem_type, derived>::raw_print_dense(std::ostream& user_stream, const std::string extra_text) const
249 {
250 arma_extra_debug_sigprint();
251
252 const unwrap_spmat<derived> tmp( (*this).get_ref() );
253
254 if(extra_text.length() != 0)
255 {
256 const std::streamsize orig_width = user_stream.width();
257
258 user_stream << extra_text << '\n';
259
260 user_stream.width(orig_width);
261 }
262
263 arma_ostream::print_dense(user_stream, tmp.M, false);
264 }
265
266
267
268 template<typename elem_type, typename derived>
269 arma_cold
270 inline
271 void
brief_print(const std::string extra_text) const272 SpBase<elem_type,derived>::brief_print(const std::string extra_text) const
273 {
274 arma_extra_debug_sigprint();
275
276 const unwrap_spmat<derived> tmp( (*this).get_ref() );
277
278 if(extra_text.length() != 0)
279 {
280 const std::streamsize orig_width = get_cout_stream().width();
281
282 get_cout_stream() << extra_text << '\n';
283
284 get_cout_stream().width(orig_width);
285 }
286
287 arma_ostream::brief_print(get_cout_stream(), tmp.M);
288 }
289
290
291
292 template<typename elem_type, typename derived>
293 arma_cold
294 inline
295 void
brief_print(std::ostream & user_stream,const std::string extra_text) const296 SpBase<elem_type,derived>::brief_print(std::ostream& user_stream, const std::string extra_text) const
297 {
298 arma_extra_debug_sigprint();
299
300 const unwrap_spmat<derived> tmp( (*this).get_ref() );
301
302 if(extra_text.length() != 0)
303 {
304 const std::streamsize orig_width = user_stream.width();
305
306 user_stream << extra_text << '\n';
307
308 user_stream.width(orig_width);
309 }
310
311 arma_ostream::brief_print(user_stream, tmp.M);
312 }
313
314
315
316 //
317 // extra functions defined in SpBase_eval_SpMat
318
319 template<typename elem_type, typename derived>
320 inline
321 arma_warn_unused
322 const derived&
eval() const323 SpBase_eval_SpMat<elem_type, derived>::eval() const
324 {
325 arma_extra_debug_sigprint();
326
327 return static_cast<const derived&>(*this);
328 }
329
330
331
332 //
333 // extra functions defined in SpBase_eval_expr
334
335 template<typename elem_type, typename derived>
336 inline
337 arma_warn_unused
338 SpMat<elem_type>
eval() const339 SpBase_eval_expr<elem_type, derived>::eval() const
340 {
341 arma_extra_debug_sigprint();
342
343 return SpMat<elem_type>( static_cast<const derived&>(*this) );
344 }
345
346
347
348 template<typename elem_type, typename derived>
349 inline
350 arma_warn_unused
351 elem_type
min() const352 SpBase<elem_type, derived>::min() const
353 {
354 return spop_min::min( (*this).get_ref() );
355 }
356
357
358
359 template<typename elem_type, typename derived>
360 inline
361 arma_warn_unused
362 elem_type
max() const363 SpBase<elem_type, derived>::max() const
364 {
365 return spop_max::max( (*this).get_ref() );
366 }
367
368
369
370 template<typename elem_type, typename derived>
371 inline
372 elem_type
min(uword & index_of_min_val) const373 SpBase<elem_type, derived>::min(uword& index_of_min_val) const
374 {
375 const SpProxy<derived> P( (*this).get_ref() );
376
377 return spop_min::min_with_index(P, index_of_min_val);
378 }
379
380
381
382 template<typename elem_type, typename derived>
383 inline
384 elem_type
max(uword & index_of_max_val) const385 SpBase<elem_type, derived>::max(uword& index_of_max_val) const
386 {
387 const SpProxy<derived> P( (*this).get_ref() );
388
389 return spop_max::max_with_index(P, index_of_max_val);
390 }
391
392
393
394 template<typename elem_type, typename derived>
395 inline
396 elem_type
min(uword & row_of_min_val,uword & col_of_min_val) const397 SpBase<elem_type, derived>::min(uword& row_of_min_val, uword& col_of_min_val) const
398 {
399 const SpProxy<derived> P( (*this).get_ref() );
400
401 uword index = 0;
402
403 const elem_type val = spop_min::min_with_index(P, index);
404
405 const uword local_n_rows = P.get_n_rows();
406
407 row_of_min_val = index % local_n_rows;
408 col_of_min_val = index / local_n_rows;
409
410 return val;
411 }
412
413
414
415 template<typename elem_type, typename derived>
416 inline
417 elem_type
max(uword & row_of_max_val,uword & col_of_max_val) const418 SpBase<elem_type, derived>::max(uword& row_of_max_val, uword& col_of_max_val) const
419 {
420 const SpProxy<derived> P( (*this).get_ref() );
421
422 uword index = 0;
423
424 const elem_type val = spop_max::max_with_index(P, index);
425
426 const uword local_n_rows = P.get_n_rows();
427
428 row_of_max_val = index % local_n_rows;
429 col_of_max_val = index / local_n_rows;
430
431 return val;
432 }
433
434
435
436 template<typename elem_type, typename derived>
437 inline
438 arma_warn_unused
439 uword
index_min() const440 SpBase<elem_type,derived>::index_min() const
441 {
442 const SpProxy<derived> P( (*this).get_ref() );
443
444 uword index = 0;
445
446 if(P.get_n_elem() == 0)
447 {
448 arma_debug_check(true, "index_min(): object has no elements");
449 }
450 else
451 {
452 spop_min::min_with_index(P, index);
453 }
454
455 return index;
456 }
457
458
459
460 template<typename elem_type, typename derived>
461 inline
462 arma_warn_unused
463 uword
index_max() const464 SpBase<elem_type,derived>::index_max() const
465 {
466 const SpProxy<derived> P( (*this).get_ref() );
467
468 uword index = 0;
469
470 if(P.get_n_elem() == 0)
471 {
472 arma_debug_check(true, "index_max(): object has no elements");
473 }
474 else
475 {
476 spop_max::max_with_index(P, index);
477 }
478
479 return index;
480 }
481
482
483
484 template<typename elem_type, typename derived>
485 inline
486 arma_warn_unused
487 bool
is_symmetric() const488 SpBase<elem_type,derived>::is_symmetric() const
489 {
490 arma_extra_debug_sigprint();
491
492 const unwrap_spmat<derived> tmp( (*this).get_ref() );
493
494 return tmp.M.is_symmetric();
495 }
496
497
498
499 template<typename elem_type, typename derived>
500 inline
501 arma_warn_unused
502 bool
is_symmetric(const typename get_pod_type<elem_type>::result tol) const503 SpBase<elem_type,derived>::is_symmetric(const typename get_pod_type<elem_type>::result tol) const
504 {
505 arma_extra_debug_sigprint();
506
507 const unwrap_spmat<derived> tmp( (*this).get_ref() );
508
509 return tmp.M.is_symmetric(tol);
510 }
511
512
513
514 template<typename elem_type, typename derived>
515 inline
516 arma_warn_unused
517 bool
is_hermitian() const518 SpBase<elem_type,derived>::is_hermitian() const
519 {
520 arma_extra_debug_sigprint();
521
522 const unwrap_spmat<derived> tmp( (*this).get_ref() );
523
524 return tmp.M.is_hermitian();
525 }
526
527
528
529 template<typename elem_type, typename derived>
530 inline
531 arma_warn_unused
532 bool
is_hermitian(const typename get_pod_type<elem_type>::result tol) const533 SpBase<elem_type,derived>::is_hermitian(const typename get_pod_type<elem_type>::result tol) const
534 {
535 arma_extra_debug_sigprint();
536
537 const unwrap_spmat<derived> tmp( (*this).get_ref() );
538
539 return tmp.M.is_hermitian(tol);
540 }
541
542
543
544 template<typename elem_type, typename derived>
545 inline
546 arma_warn_unused
547 bool
is_zero(const typename get_pod_type<elem_type>::result tol) const548 SpBase<elem_type,derived>::is_zero(const typename get_pod_type<elem_type>::result tol) const
549 {
550 arma_extra_debug_sigprint();
551
552 typedef typename get_pod_type<elem_type>::result T;
553
554 arma_debug_check( (tol < T(0)), "is_zero(): parameter 'tol' must be >= 0" );
555
556 const SpProxy<derived> P( (*this).get_ref() );
557
558 if(P.get_n_elem() == 0) { return false; }
559
560 if(P.get_n_nonzero() == 0) { return true; }
561
562 if(is_SpMat<typename SpProxy<derived>::stored_type>::value)
563 {
564 const unwrap_spmat<typename SpProxy<derived>::stored_type> U(P.Q);
565
566 return arrayops::is_zero(U.M.values, U.M.n_nonzero, tol);
567 }
568
569 typename SpProxy<derived>::const_iterator_type it = P.begin();
570 typename SpProxy<derived>::const_iterator_type it_end = P.end();
571
572 if(is_cx<elem_type>::yes)
573 {
574 while(it != it_end)
575 {
576 const elem_type val = (*it);
577
578 const T val_real = access::tmp_real(val);
579 const T val_imag = access::tmp_imag(val);
580
581 if(eop_aux::arma_abs(val_real) > tol) { return false; }
582 if(eop_aux::arma_abs(val_imag) > tol) { return false; }
583
584 ++it;
585 }
586 }
587 else // not complex
588 {
589 while(it != it_end)
590 {
591 if(eop_aux::arma_abs(*it) > tol) { return false; }
592
593 ++it;
594 }
595 }
596
597 return true;
598 }
599
600
601
602 template<typename elem_type, typename derived>
603 inline
604 arma_warn_unused
605 bool
is_trimatu() const606 SpBase<elem_type,derived>::is_trimatu() const
607 {
608 arma_extra_debug_sigprint();
609
610 const SpProxy<derived> P( (*this).get_ref() );
611
612 if(P.get_n_rows() != P.get_n_cols()) { return false; }
613
614 typename SpProxy<derived>::const_iterator_type it = P.begin();
615 typename SpProxy<derived>::const_iterator_type it_end = P.end();
616
617 while(it != it_end)
618 {
619 if(it.row() > it.col()) { return false; }
620 ++it;
621 }
622
623 return true;
624 }
625
626
627
628 template<typename elem_type, typename derived>
629 inline
630 arma_warn_unused
631 bool
is_trimatl() const632 SpBase<elem_type,derived>::is_trimatl() const
633 {
634 arma_extra_debug_sigprint();
635
636 const SpProxy<derived> P( (*this).get_ref() );
637
638 if(P.get_n_rows() != P.get_n_cols()) { return false; }
639
640 typename SpProxy<derived>::const_iterator_type it = P.begin();
641 typename SpProxy<derived>::const_iterator_type it_end = P.end();
642
643 while(it != it_end)
644 {
645 if(it.row() < it.col()) { return false; }
646 ++it;
647 }
648
649 return true;
650 }
651
652
653
654 template<typename elem_type, typename derived>
655 inline
656 arma_warn_unused
657 bool
is_diagmat() const658 SpBase<elem_type,derived>::is_diagmat() const
659 {
660 arma_extra_debug_sigprint();
661
662 const SpProxy<derived> P( (*this).get_ref() );
663
664 typename SpProxy<derived>::const_iterator_type it = P.begin();
665 typename SpProxy<derived>::const_iterator_type it_end = P.end();
666
667 while(it != it_end)
668 {
669 if(it.row() != it.col()) { return false; }
670 ++it;
671 }
672
673 return true;
674 }
675
676
677
678 template<typename elem_type, typename derived>
679 inline
680 arma_warn_unused
681 bool
is_empty() const682 SpBase<elem_type,derived>::is_empty() const
683 {
684 arma_extra_debug_sigprint();
685
686 const SpProxy<derived> P( (*this).get_ref() );
687
688 return (P.get_n_elem() == uword(0));
689 }
690
691
692
693 template<typename elem_type, typename derived>
694 inline
695 arma_warn_unused
696 bool
is_square() const697 SpBase<elem_type,derived>::is_square() const
698 {
699 arma_extra_debug_sigprint();
700
701 const SpProxy<derived> P( (*this).get_ref() );
702
703 return (P.get_n_rows() == P.get_n_cols());
704 }
705
706
707
708 template<typename elem_type, typename derived>
709 inline
710 arma_warn_unused
711 bool
is_vec() const712 SpBase<elem_type,derived>::is_vec() const
713 {
714 arma_extra_debug_sigprint();
715
716 if( (SpProxy<derived>::is_row) || (SpProxy<derived>::is_col) || (SpProxy<derived>::is_xvec) ) { return true; }
717
718 const SpProxy<derived> P( (*this).get_ref() );
719
720 return ( (P.get_n_rows() == uword(1)) || (P.get_n_cols() == uword(1)) );
721 }
722
723
724
725 template<typename elem_type, typename derived>
726 inline
727 arma_warn_unused
728 bool
is_colvec() const729 SpBase<elem_type,derived>::is_colvec() const
730 {
731 arma_extra_debug_sigprint();
732
733 if(SpProxy<derived>::is_col) { return true; }
734
735 const SpProxy<derived> P( (*this).get_ref() );
736
737 return (P.get_n_cols() == uword(1));
738 }
739
740
741
742 template<typename elem_type, typename derived>
743 inline
744 arma_warn_unused
745 bool
is_rowvec() const746 SpBase<elem_type,derived>::is_rowvec() const
747 {
748 arma_extra_debug_sigprint();
749
750 if(SpProxy<derived>::is_row) { return true; }
751
752 const SpProxy<derived> P( (*this).get_ref() );
753
754 return (P.get_n_rows() == uword(1));
755 }
756
757
758
759 template<typename elem_type, typename derived>
760 inline
761 arma_warn_unused
762 bool
is_finite() const763 SpBase<elem_type,derived>::is_finite() const
764 {
765 arma_extra_debug_sigprint();
766
767 const SpProxy<derived> P( (*this).get_ref() );
768
769 if(is_SpMat<typename SpProxy<derived>::stored_type>::value)
770 {
771 const unwrap_spmat<typename SpProxy<derived>::stored_type> U(P.Q);
772
773 return U.M.is_finite();
774 }
775 else
776 {
777 typename SpProxy<derived>::const_iterator_type it = P.begin();
778 typename SpProxy<derived>::const_iterator_type it_end = P.end();
779
780 while(it != it_end)
781 {
782 if(arma_isfinite(*it) == false) { return false; }
783 ++it;
784 }
785 }
786
787 return true;
788 }
789
790
791
792 template<typename elem_type, typename derived>
793 inline
794 arma_warn_unused
795 bool
has_inf() const796 SpBase<elem_type,derived>::has_inf() const
797 {
798 arma_extra_debug_sigprint();
799
800 const SpProxy<derived> P( (*this).get_ref() );
801
802 if(is_SpMat<typename SpProxy<derived>::stored_type>::value)
803 {
804 const unwrap_spmat<typename SpProxy<derived>::stored_type> U(P.Q);
805
806 return U.M.has_inf();
807 }
808 else
809 {
810 typename SpProxy<derived>::const_iterator_type it = P.begin();
811 typename SpProxy<derived>::const_iterator_type it_end = P.end();
812
813 while(it != it_end)
814 {
815 if(arma_isinf(*it)) { return true; }
816 ++it;
817 }
818 }
819
820 return false;
821 }
822
823
824
825 template<typename elem_type, typename derived>
826 inline
827 arma_warn_unused
828 bool
has_nan() const829 SpBase<elem_type,derived>::has_nan() const
830 {
831 arma_extra_debug_sigprint();
832
833 const SpProxy<derived> P( (*this).get_ref() );
834
835 if(is_SpMat<typename SpProxy<derived>::stored_type>::value)
836 {
837 const unwrap_spmat<typename SpProxy<derived>::stored_type> U(P.Q);
838
839 return U.M.has_nan();
840 }
841 else
842 {
843 typename SpProxy<derived>::const_iterator_type it = P.begin();
844 typename SpProxy<derived>::const_iterator_type it_end = P.end();
845
846 while(it != it_end)
847 {
848 if(arma_isnan(*it)) { return true; }
849 ++it;
850 }
851 }
852
853 return false;
854 }
855
856
857
858 template<typename elem_type, typename derived>
859 inline
860 arma_warn_unused
861 const SpOp<derived,spop_vectorise_col>
as_col() const862 SpBase<elem_type, derived>::as_col() const
863 {
864 return SpOp<derived,spop_vectorise_col>( (*this).get_ref() );
865 }
866
867
868
869 template<typename elem_type, typename derived>
870 inline
871 arma_warn_unused
872 const SpOp<derived,spop_vectorise_row>
as_row() const873 SpBase<elem_type, derived>::as_row() const
874 {
875 return SpOp<derived,spop_vectorise_row>( (*this).get_ref() );
876 }
877
878
879
880 //! @}
881