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