CVM Class Library  8.1
This C++ class library encapsulates concepts of vector and different matrices including square, band, symmetric and hermitian ones in Euclidean space of real and complex numbers.
 All Classes Files Functions Variables Typedefs Friends Macros Pages
cvm.h
Go to the documentation of this file.
1 // CVM Class Library
2 // http://cvmlib.com
3 //
4 // Copyright Sergei Nikolaev 1992-2014
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
32 #ifndef _CVM_H
33 #define _CVM_H
34 
35 // 5.7 ILP64 support
36 #if defined (CVM_ILP64)
37  typedef long long int tint;
38 # define TINT_ZERO (0LL)
39 # define TINT_ONE (1LL)
40 # define CVM_TINT_FORMAT "%lld"
41 #else
42  typedef int tint;
43 # define TINT_ZERO (0)
44 # define TINT_ONE (1)
45 # define CVM_TINT_FORMAT "%d"
46 #endif
47 
48 // 5.7 0-based indexing
49 #if defined (CVM_ZERO_BASED)
50 # define CVM0 TINT_ZERO
51 #else
52 # define CVM0 TINT_ONE
53 #endif
54 
55 #if !defined (CVM_NO_MT) // as of 5.7 it's by default
56 # define CVM_MT
57 # if !defined (_PTHREADS)
58 # define _PTHREADS
59 # endif
60 #endif
61 
62 // MSVC++ 6.0 and higher settings
63 #if defined (_MSC_VER)
64 # pragma once
65 # define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
66 # ifndef _WIN32_WINNT
67 # define _WIN32_WINNT 0x500 // at least Win2000 is required for InitializeCriticalSectionAndSpinCount
68 # endif
69 # include <windows.h>
70 # include <process.h>
71 // 6.0 TR1 dependency added
72 # include <memory>
73 
74 # if (_MSC_VER < 1400)
75 # error "Please use stable version 5.2 for older MSVC compilers"
76 # endif
77 # if (_MSC_VER >= 1700) // since VC11 aka MS Visual Studio 2012
78 # define CVM_STD_MUTEX
79 # include <mutex>
80 # include <thread>
81 # endif
82 # if (_MSC_VER >= 1800) // since VC12 aka MS Visual Studio 2013
83 # define CVM_USE_VARIADIC_TEMPLATES
84 # define CVM_USE_INITIALIZER_LISTS
85 # define CVM_USE_DELEGATING_CONSTRUCTORS
86 
87 # include <initializer_list>
88 # endif
89 # if (!defined(__INTEL_COMPILER) || !defined(_WIN64)) && !defined(CVM_ACML) && !(_MSC_VER >= 1500 && defined(_WIN64))
90 # define CVM_PASS_STRING_LENGTH_TO_FTN_SUBROUTINES
91 # endif
92 # if defined(CVM_ACML)
93 # define CVM_COMPLEX_NUMBER_RETURNED
94 # endif
95 //# if (_MSC_VER <= 1800)
96 # define noexcept throw()
97 //# endif
98 # pragma warning(disable:4290)
99 # if defined (CVM_FLOAT)
100 # pragma warning(disable:4244)
101 # endif
102 # if defined (SRC_EXPORTS) && !defined (CVM_EXPORTS)
103 # define CVM_EXPORTS
104 # endif
105 # include <unordered_map>
106 # define CVM_BLOCKS_MAP std::unordered_map
107 # ifdef CVM_STATIC
108 # define CVM_API
109 # else
110 # ifdef CVM_EXPORTS
111 # define CVM_API __declspec(dllexport)
112 # else
113 # define CVM_API __declspec(dllimport)
114 # endif
115 # endif
116 
117 # include <limits>
118 typedef __int64 CVM_LONGEST_INT;
119 
120 # if defined(_WIN64)
121 typedef unsigned long long CVM_PTR_WRAPPER;
122 # else
123 # if defined (CVM_ILP64)
124 # error "CVM_ILP64 is incompatible with 32 bit mode"
125 # endif
126 typedef unsigned long CVM_PTR_WRAPPER;
127 # endif
128 
129 # define CVM_VSNPRINTF vsnprintf_s
130 # define CVM_VSNPRINTF_S_DEFINED
131 # define CVM_STRCPY_S_DEFINED
132 
133 // GCC settings
134 #elif defined (__GNUC__)
135 # if defined (__MINGW32__)
136 # define WIN32_LEAN_AND_MEAN
137 # include <windows.h>
138 # include <process.h>
139 
140 # define CVM_USE_CRITICAL_SECTION_NOT_MUTEX
141 
142 # else
143 # ifdef __stdcall
144 # undef __stdcall
145 # endif
146 # define __stdcall
147 # include <semaphore.h> // Unix
148 # endif
149 
150 // 8.0 - since 4.7.0 we use new std::mutex features
151 # if !defined(__INTEL_COMPILER) && !defined (__MINGW32__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 7)
152 # define CVM_USE_DELEGATING_CONSTRUCTORS
153 # define CVM_USE_USER_LITERALS
154 # define CVM_STD_MUTEX
155 # include <mutex>
156 # include <thread>
157 # else
158 # define override
159 # endif
160 
161 // 8.1 - more C++11 features, see also http://gcc.gnu.org/projects/cxx0x.html
162 # if !defined (__MINGW32__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4)
163 # define CVM_USE_VARIADIC_TEMPLATES
164 # define CVM_USE_INITIALIZER_LISTS
165 # include <initializer_list>
166 # endif
167 
168 // 6.0 TR1 dependency added
169 # include <memory>
170 
171 # define CVM_API
172 # define CVM_STDEXT stdext
173 # define CVM_BLOCKS_MAP std::map
174 
175 typedef long long CVM_LONGEST_INT;
176 
177 # if defined(__AMD64__) || defined(_WIN64) || defined(__x86_64__)
178 typedef unsigned long long CVM_PTR_WRAPPER;
179 # else
180 # if defined (CVM_ILP64)
181 # error "CVM_ILP64 is incompatible with 32 bit mode"
182 # endif
183 typedef unsigned long CVM_PTR_WRAPPER;
184 # endif
185 
186 # define CVM_VSNPRINTF vsnprintf
187 
188 // 5.7 - looking for memset
189 # include <string.h>
190 // gcc 4.6.1 fix for ptrdiff_t
191 # include <cstddef>
192 
193 //clang -dM -E -x c /dev/null
194 # if defined(__clang__) && __clang_major__ <= 5
195 # define CVM_NO_DEFAULT_RANDOM_ENGINE_SUPPORTED 1
196 # endif
197 # if defined(__clang__) && __clang_major__ >= 5
198 # define CVM_USE_VARIADIC_TEMPLATES
199 # define CVM_USE_INITIALIZER_LISTS
200 # define CVM_USE_USER_LITERALS
201 # define CVM_USE_DELEGATING_CONSTRUCTORS
202 # endif
203 
204 #else
205 # error "Unsupported compiler"
206 #endif
207 
208 #include <stdlib.h>
209 #include <stdio.h>
210 #include <stdarg.h>
211 #include <math.h>
212 #include <float.h>
213 #include <time.h>
214 #include <iostream>
215 #include <list>
216 #include <map>
217 #include <string>
218 #include <limits>
219 
220 // fix for missing __builtin_clog functions
221 #if defined (__INTEL_COMPILER)
222 # if defined (_GLIBCXX_USE_C99_COMPLEX)
223 # undef _GLIBCXX_USE_C99_COMPLEX
224 # define _GLIBCXX_USE_C99_COMPLEX 0
225 # endif
226 #endif
227 
228 #include <complex>
229 #include <algorithm>
230 #include <exception>
231 #include <utility>
232 #include <new>
233 
234 #if !defined(CVM_NO_DEFAULT_RANDOM_ENGINE_SUPPORTED)
235 # include <random>
236 #endif
237 
238 #if defined (STLPORT)
239 # define CVM_USES_STLPORT
240 #endif
241 
242 #if defined (_DEBUG) || defined (DEBUG)
243 # define CVM_DEBUG
244 # include <assert.h>
245 # define CVM_ASSERT(p,n) _cvm_assert(p,n);
246 #else
247 # define CVM_ASSERT(p,n)
248 #endif
249 
250 #define CVM_OK 0
251 #define CVM_OUTOFMEMORY 1
252 #define CVM_WRONGSIZE 5
253 #define CVM_SIZESMISMATCH 6
254 #define CVM_WRONGMKLARG 7
255 #define CVM_WRONGMKLARG2 8
256 #define CVM_SINGULARMATRIX 9
257 #define CVM_NOTPOSITIVEDEFINITE 10
258 #define CVM_WRONGCHOLESKYFACTOR 11
259 #define CVM_WRONGBUNCHKAUFMANFACTOR 12
260 #define CVM_NOTPOSITIVEDIAG 13
261 #define CVM_CONVERGENCE_ERROR 14
262 #define CVM_DIVISIONBYZERO 15
263 #define CVM_SEMAPHOREERROR 16
264 #define CVM_READ_ONLY_ACCESS 17
265 #define CVM_SUBMATRIXACCESSERROR 18
266 #define CVM_SUBMATRIXNOTAVAILABLE 19
267 #define CVM_MATRIXNOTSYMMETRIC 20
268 #define CVM_MATRIXNOTHERMITIAN 21
269 #define CVM_BREAKS_HERMITIANITY 22
270 #define CVM_METHODNOTAVAILABLE 23
271 #define CVM_NOTIMPLEMENTED 24
272 #define CVM_CANT_RESIZE_SHARED_MEM 25
273 #define CVM_NOT_CONJUGATED 26
274 // 8.1
275 #define CVM_WRONGSIZE_LT 27
276 #define CVM_WRONGSIZE_LE 28
277 #define CVM_INDEX_GT 29
278 #define CVM_INDEX_GE 30
279 #define CVM_OUTOFRANGE_LTGT 31
280 #define CVM_OUTOFRANGE_LTGE 32
281 #define CVM_OUTOFRANGE_LTGE1 33
282 #define CVM_OUTOFRANGE_LTGE2 34
283 #define CVM_SIZESMISMATCH_GT 35
284 #define CVM_SIZESMISMATCH_LT 36
285 
286 #define CVM_THE_LAST_ERROR_CODE 37
287 #define CVM_MATRIX_ELEMENT_SEPARATOR " "
288 #define CVM_EOL std::endl
289 
290 typedef unsigned char tbyte;
291 
292 #ifdef CVM_NO_NAMESPACE
293 # define CVM_NAMESPACE_BEG
294 # define CVM_NAMESPACE_END
295 #else
296 # define CVM_NAMESPACE_BEG namespace cvm {
297 # define CVM_NAMESPACE_END }
298 #endif
299 
300 
302 
304 template<typename T>
306 public:
307  void operator () (T* d) const {
308  if (d != nullptr) {
309  ::delete[] d;
310  }
311  }
312 };
313 
314 template<typename TR, typename T> class basic_array;
315 template<typename TR, typename TC> class Matrix;
316 template<typename TR, typename TC> class SqMatrix;
317 template<typename TR, typename TC> class BandMatrix;
318 template<typename TR> class basic_rvector;
319 template<typename TR> class basic_rmatrix;
320 template<typename TR> class basic_srmatrix;
321 template<typename TR, typename TC> class basic_cvector;
322 template<typename TR, typename TC> class basic_cmatrix;
323 template<typename TR, typename TC> class basic_scmatrix;
324 template<typename TR> class basic_srbmatrix;
325 template<typename TR, typename TC> class basic_scbmatrix;
326 template<typename TR> class basic_srsmatrix;
327 template<typename TR, typename TC> class basic_schmatrix;
328 template<typename T, typename TR> class type_proxy;
329 
332 {
333  // message string maps
334  typedef std::map<int, std::string, std::less<int> > map_Msg;
335  typedef map_Msg::iterator itr_Msg;
336  typedef map_Msg::const_iterator citr_Msg;
337  typedef std::pair<int, std::string> pair_Msg;
338 
339 private:
340  std::string msUnknown;
341  map_Msg mmMsg;
342  CVM_API ErrMessages();
343 
344 public:
345  CVM_API const std::string& _get(int nException);
346  CVM_API bool _add(int nNewCause, const char* szNewMessage);
347 
348  static CVM_API ErrMessages& ErrMessagesInstance();
350 };
351 
352 
358 class cvmexception : public std::exception
359 {
360 protected:
361  int mnCause;
362  mutable char mszMsg[256];
363 
365  virtual const char* _get_message(int nCause) const {
366  return ErrMessages::ErrMessagesInstance()._get(nCause).c_str();
367  }
369 
370 public:
377  : mnCause(CVM_OK)
378  {
379  mszMsg[0] = '\0';
380  }
381 
389  CVM_API explicit cvmexception(int nCause, ...); // TODO
390 
394  CVM_API cvmexception(const cvmexception& e);
395 
399  virtual ~cvmexception() throw() { }
400 
409  int cause() const {
410  return mnCause;
411  }
412 
420  const char* what() const throw() override {
421  return mszMsg;
422  }
423 
431  static int getNextCause() {
433  }
434 
444  static bool add(int nNewCause, const char* szNewMessage) {
445  return ErrMessages::ErrMessagesInstance()._add(nNewCause, szNewMessage);
446  }
447 };
448 
450 template<typename T>
451 CVM_API void __copy(tint nSize, const T* pFrom, tint nFromIncr, T* pTo, tint nToIncr);
452 template<typename T>
453 CVM_API void __swap(tint nSize, T* p1, tint n1Incr, T* p2, tint n2Incr);
454 
455 template<typename TC, typename TR>
456 CVM_API TR _real(const TC& mT);
457 template<typename TC, typename TR>
458 CVM_API TR _imag(const TC& mT);
459 
460 template<typename TR>
461 CVM_API TR __dot(const TR* pDm, tint mnSize, tint mnIncr, const TR* pd, tint nIncr);
462 template<typename TC>
463 CVM_API TC __dotu(const TC* pDm, tint mnSize, tint mnIncr, const TC* pd, tint nIncr);
464 template<typename TC>
465 CVM_API TC __dotc(const TC* pDm, tint mnSize, tint mnIncr, const TC* pd, tint nIncr);
466 
467 template<typename TR, typename TC>
468 CVM_API TR __norm(const TC* pd, tint nSize, tint nIncr);
469 
470 template<typename TC>
471 CVM_API tint __idamax(const TC* pd, tint nSize, tint nIncr);
472 template<typename TC>
473 CVM_API tint __idamin(const TC* pd, tint nSize, tint nIncr);
474 
475 template<typename TC>
476 CVM_API void __add(TC* pDm, tint mnSize, tint mnIncr, const TC* pv, tint nIncr);
477 template<typename TC>
478 CVM_API void __subtract(TC* pDm, tint mnSize, tint mnIncr, const TC* pv, tint nIncr);
480 template<typename TR, typename TC>
481 CVM_API void __scal(TC* pDm, tint mnSize, tint mnIncr, TR dScal);
482 template<typename TC>
483 CVM_API void __conj(TC* pDm, tint mnSize, tint mnIncr);
484 
485 template<typename TR, typename TC>
486 CVM_API void __copy_real(TC* pDm, tint mnSize, tint mnIncr, const TR* pRe, tint nReIncr);
487 template<typename TR, typename TC>
488 CVM_API void __copy_imag(TC* pDm, tint mnSize, tint mnIncr, const TR* pRe, tint nReIncr);
489 template<typename TR, typename TC>
490 CVM_API void __copy2(TC* pDm, tint mnSize, tint mnIncr, const TR* pRe, const TR* pIm, tint nReIncr = 1, tint nImIncr = 1);
491 
492 template<typename TC, typename TM, typename TV>
493 CVM_API void __gemv(bool bLeft, const TM& m, TC dAlpha, const TV& v, TC dBeta, TV& vRes);
494 template<typename TC, typename TM, typename TV>
495 CVM_API void __gbmv(bool bLeft, const TM& m, TC dAlpha, const TV& v, TC dBeta, TV& vRes);
496 template<typename TR, typename TM, typename TV>
497 CVM_API void __symv(const TM& m, TR dAlpha, const TV& v, TR dBeta, TV& vRes);
498 template<typename TC, typename TM, typename TV>
499 CVM_API void __shmv(const TM& m, TC dAlpha, const TV& v, TC dBeta, TV& vRes);
500 template<typename TC, typename TM>
501 CVM_API void __gemm(const TM& ml, bool bTrans1, const TM& mr, bool bTrans2, TC dAlpha, TM& mRes, TC dBeta);
502 template<typename TR, typename TSM, typename TM>
503 CVM_API void __symm(bool bLeft, const TSM& ml, const TM& mr, TR dAlpha, TM& mRes, TR dBeta);
504 template<typename TC, typename TSM, typename TM>
505 CVM_API void __hemm(bool bLeft, const TSM& ml, const TM& mr, TC dAlpha, TM& mRes, TC dBeta);
506 
507 template<typename TC, typename TV>
508 CVM_API void __polynom(TC* pDm, tint ldP, tint mnM, const TC* pd, tint ldA, const TV& v);
509 template<typename T>
510 CVM_API void __inv(T& m, const T& mArg) throw(cvmexception);
511 template<typename T, typename TR>
512 CVM_API void __exp(T& m, const T& mArg, TR tol) throw(cvmexception);
513 template<typename T, typename TR>
514 CVM_API void __exp_symm(T& m, const T& mArg, TR tol) throw(cvmexception);
515 template<typename TR, typename TC, typename TRM>
516 CVM_API void __solve(const TRM& m, tint nrhs, const TC* pB, tint ldB, TC* pX, tint ldX, TR& dErr,
517  const TC* pLU, const tint* pPivots, int transp_mode) throw(cvmexception);
518 template<typename TC, typename TM, typename TSM>
519 CVM_API void __svd(TC* pd, tint nSize, tint nIncr, const TM& mArg, TSM* mU, TSM* mVH) throw(cvmexception);
520 template<typename TR, typename TM, typename TX>
521 CVM_API void __pinv(TX& mX, const TM& mArg, TR threshold) throw(cvmexception);
522 template<typename TV, typename TSM, typename TSCM>
523 CVM_API void __eig(TV& vRes, const TSM& mArg, TSCM* mEigVect, bool bRightVect) throw(cvmexception);
524 template<typename TR, typename TM>
525 CVM_API void __cond_num(const TM& mArg, TR& dCondNum) throw(cvmexception);
526 template<typename TM>
527 void __low_up(TM& m, tint* nPivots) throw(cvmexception);
528 
529 template<typename TR>
530 CVM_API void __randomize(TR* pDm, tint mnSize, tint mnIncr, TR dFrom, TR dTo);
531 template<typename TC, typename TR>
532 CVM_API void __randomize_real(TC* pDm, tint mnSize, tint mnIncr, TR dFrom, TR dTo);
533 template<typename TC, typename TR>
534 CVM_API void __randomize_imag(TC* pDm, tint mnSize, tint mnIncr, TR dFrom, TR dTo);
535 
536 template<typename TR, typename TM, typename TV>
537 CVM_API void __ger(TM& m, const TV& vCol, const TV& vRow, TR dAlpha);
538 template<typename TC, typename TM, typename TV>
539 CVM_API void __geru(TM& m, const TV& vCol, const TV& vRow, TC cAlpha);
540 template<typename TC, typename TM, typename TV>
541 CVM_API void __gerc(TM& m, const TV& vCol, const TV& vRow, TC cAlpha);
542 
543 template<typename TC, typename TSM>
544 CVM_API void __syrk(bool bTransp, TC alpha, tint k, const TC* pA, tint ldA, TC beta, TSM& m);
545 template<typename TC, typename TSM>
546 CVM_API void __syr2k(bool bTransp, TC alpha, tint k, const TC* pA, tint ldA, const TC* pB, tint ldB, TC beta, TSM& m);
547 template<typename TR, typename TC, typename TSM>
548 CVM_API void __herk(bool bTransp, TR alpha, tint k, const TC* pA, tint ldA, TR beta, TSM& m);
549 template<typename TR, typename TC, typename TSM>
550 CVM_API void __her2k(bool bTransp, TC alpha, tint k, const TC* pA, tint ldA, const TC* pB, tint ldB, TR beta, TSM& m);
551 
552 template<typename TM>
553 CVM_API tint __cholesky(TM& m);
554 template<typename TM>
555 CVM_API void __bunch_kaufman(TM& m, tint* nPivots) throw(cvmexception);
556 template<typename TR, typename TM, typename TV>
557 CVM_API void __poequ(const TM& m, TV& vScalings, TR& dCond, TR& dMax);
558 
559 template<typename TM, typename TSM>
560 CVM_API void __qre(const TM& mA, TM& mQ, TSM& mR) throw(cvmexception);
561 template<typename TM, typename TSM>
562 CVM_API void __qrf(const TM& mA, TSM& mQ, TM& mR) throw(cvmexception);
563 template<typename TM, typename TSM>
564 CVM_API void __rqe(const TM& mA, TSM& mR, TM& mQ) throw(cvmexception);
565 template<typename TM, typename TSM>
566 CVM_API void __rqf(const TM& mA, TM& mR, TSM& mQ) throw(cvmexception);
567 
568 template<typename TM, typename TSM>
569 CVM_API void __lqe(const TM& mA, TSM& mL, TM& mQ) throw(cvmexception);
570 template<typename TM, typename TSM>
571 CVM_API void __lqf(const TM& mA, TM& mL, TSM& mQ) throw(cvmexception);
572 template<typename TM, typename TSM>
573 CVM_API void __qle(const TM& mA, TM& mQ, TSM& mL) throw(cvmexception);
574 template<typename TM, typename TSM>
575 CVM_API void __qlf(const TM& mA, TSM& mQ, TM& mL) throw(cvmexception);
576 
577 // Linear Least Squares problems
578 template<typename TM, typename TV>
579 CVM_API void __gels(bool transpose, TM& mA, const TM& mB, TM& mX, TV& vErr) throw(cvmexception);
580 template<typename TR, typename TM>
581 CVM_API void __gelsy(TM& mA, const TM& mB, TM& mX, TR tol, tint& rank) throw(cvmexception);
582 template<typename TR, typename TV, typename TM>
583 CVM_API void __gelss(TM& mA, const TM& mB, TM& mX, TR rcond, TV& vSV, tint& rank) throw(cvmexception);
584 template<typename TR, typename TV, typename TM>
585 CVM_API void __gelsd(TM& mA, const TM& mB, TM& mX, TR rcond, TV& vSV, tint& rank) throw(cvmexception);
586 
587 // 8.1 Generalized Eigenvalue Problem
588 template<typename TSRM, typename TSCM, typename TRV, typename TCV>
589 CVM_API void __ggev(TSRM& mA, TSRM& mB, TCV& vAlpha, TRV& vBeta,
590  TSCM* mEigVectLeft, TSCM* mEigVectRight) throw (cvmexception);
591 
592 
593 template<typename T>
594 inline const T& _cvm_min(const T& x, const T& y) {
595  return x < y ? x : y;
596 }
597 
598 template<typename T>
599 inline const T& _cvm_max(const T& x, const T& y) {
600  return x > y ? x : y;
601 }
602 
603 template<class TR>
604 inline const TR* __get_real_p(const std::complex<TR>* c)
605 {
606 #if defined (CVM_USES_STLPORT)
607  return &c->_M_re;
608 #else
609  return reinterpret_cast<const TR*>(c);
610 #endif
611 }
612 
613 template<class TR>
614 inline const TR* __get_imag_p(const std::complex<TR>* c)
615 {
616 #if defined (CVM_USES_STLPORT)
617  return &c->_M_im;
618 #else
619  return reinterpret_cast<const TR*>(c) + 1;
620 #endif
621 }
622 
623 template<class TR>
624 inline TR* __get_real_p(std::complex<TR>* c)
625 {
626 #if defined (CVM_USES_STLPORT)
627  return &c->_M_re;
628 #else
629  return reinterpret_cast<TR*>(c);
630 #endif
631 }
632 
633 template<class TR>
634 inline TR* __get_imag_p(std::complex<TR>* c)
635 {
636 #if defined (CVM_USES_STLPORT)
637  return &c->_M_im;
638 #else
639  return reinterpret_cast<TR*>(c) + 1;
640 #endif
641 }
642 
643 template<class TR> inline const TR* __get_real_p(const TR* d) { return d; }
644 template<class TR> inline const TR* __get_imag_p(const TR* d) { return d; }
645 template<class TR> inline TR* __get_real_p(TR* d) { return d; }
646 template<class TR> inline TR* __get_imag_p(TR* d) { return d; }
647 
649 class Chars
650 {
651 protected:
652  static char mchars[15];
653 
654 public:
655  static const char* pT() {return mchars;}
656  static const char* pN() {return mchars + 1;}
657  static const char* pU() {return mchars + 2;}
658  static const char* pL() {return mchars + 3;}
659  static const char* pP() {return mchars + 4;}
660  static const char* pQ() {return mchars + 5;}
661  static const char* pB() {return mchars + 6;}
662  static const char* pE() {return mchars + 7;}
663  static const char* pR() {return mchars + 8;}
664  static const char* pA() {return mchars + 9;}
665  static const char* pS() {return mchars + 10;}
666  static const char* pV() {return mchars + 11;}
667  static const char* pO() {return mchars + 12;}
668  static const char* pI() {return mchars + 13;}
669  static const char* pC() {return mchars + 14;}
670 };
671 
672 template<class TR>
673 inline TR basic_cvmMachMin() {
674  static const TR _min = (std::numeric_limits<TR>::min)();
675  return _min;
676 }
677 
678 template<class TR>
679 inline TR basic_cvmMachSp() {
680  static const TR _eps = (std::numeric_limits<TR>::epsilon)();
681  return _eps;
682 }
683 
684 template<typename TR>
685 inline TR basic_cvmMachMax() {
686  static const TR _max((std::numeric_limits<TR>::max)());
687  return _max;
688 }
689 
690 template<typename TR>
691 inline TR basic_cvmLogMachMax() {
692  static const TR _log_max(::log(basic_cvmMachMax<TR>()));
693  return _log_max;
694 }
695 
696 // range and index checkers
697 template<typename T>
698 void _check_negative(int err_code, T val) throw(cvmexception)
699 {
700  static T zero = T(0);
701  if (val < zero) {
702  throw cvmexception(err_code, val);
703  }
704 }
705 
706 template<typename T>
707 void _check_positive(int err_code, T val) throw(cvmexception)
708 {
709  static T zero = T(0);
710  if (val > zero) {
711  throw cvmexception(err_code, val);
712  }
713 }
714 
715 template<typename T>
716 void _check_positive(int err_code, T val, const char* func, const char* file, int line) throw(cvmexception)
717 {
718  static T zero = T(0);
719  if (val > zero) {
720  throw cvmexception(err_code, func, file, line);
721  }
722 }
723 
724 template<typename T>
725 void _check_lt(int err_code, T idx, T limit) throw(cvmexception)
726 {
727  if (idx < limit) {
728  throw cvmexception(err_code, idx, limit);
729  }
730 }
731 
732 template<typename T>
733 void _check_le(int err_code, T idx, T limit) throw(cvmexception)
734 {
735  if (idx <= limit) {
736  throw cvmexception(err_code, idx, limit);
737  }
738 }
739 
740 template<typename T>
741 void _check_ge(int err_code, T idx, T limit) throw(cvmexception)
742 {
743  if (idx >= limit) {
744  throw cvmexception(err_code, idx, limit);
745  }
746 }
747 
748 template<typename T>
749 void _check_gt(int err_code, T idx, T limit) throw(cvmexception)
750 {
751  if (idx > limit) {
752  throw cvmexception(err_code, idx, limit);
753  }
754 }
755 
756 template<typename T>
757 void _check_ne(int err_code, T idx, T limit) throw(cvmexception)
758 {
759  if (idx != limit) {
760  throw cvmexception(err_code, idx, limit);
761  }
762 }
763 
764 template<typename T>
765 void _check_lt_gt(int err_code, T idx, T low_limit, T up_limit) throw(cvmexception)
766 {
767  if (idx < low_limit || idx > up_limit) {
768  throw cvmexception(err_code, idx, low_limit, up_limit);
769  }
770 }
771 
772 template<typename T>
773 void _check_lt_ge(int err_code, T idx, T low_limit, T up_limit) throw(cvmexception)
774 {
775  if (idx < low_limit || idx >= up_limit) {
776  throw cvmexception(err_code, idx, low_limit, up_limit);
777  }
778 }
780 
781 
783 #ifdef CVM_USE_POOL_MANAGER
784 
786 class CVM_API MemoryBlocks
787 {
788  struct BlockProperty
789  {
790  size_t mnSize;
791  tint mnRefCount;
792  BlockProperty(size_t nSize, tint nRefCount) : mnSize(nSize), mnRefCount(nRefCount) { }
793  };
794 
795  typedef std::map<tbyte*, BlockProperty, std::less<tbyte*> > map_Blocks;
796  typedef map_Blocks::iterator itr_Blocks;
797 
798  typedef std::multimap<size_t, tbyte*> map_FreeBs;
799  typedef map_FreeBs::iterator itr_FreeBs;
800 
801  typedef std::map<tbyte*, itr_FreeBs, std::less<tbyte*> > map_FreeIt;
802  typedef map_FreeIt::iterator itr_FreeIt;
803 
804  map_FreeBs mFreeBs;
805  map_FreeIt mFreeIt;
806 
807  map_Blocks mBlocks;
808 
809 
810 public:
811  void AddBlock(tbyte* pBlock, size_t nBytes, bool bOccupied);
812  tbyte* GetFreeBlock(size_t nBytes);
813  void AddPair(tbyte* pBlock, size_t nBytes, size_t nRest);
814 #ifdef CVM_DEBUG
815  void Assert(const void* pvBlock, size_t nBytes);
816 #endif
817  void AddNew(tbyte* pBlock, size_t nBytes);
818  tbyte* AddRef(const tbyte* pBlock);
819  tint FreeBlock(tbyte* pBlock);
820 };
821 
822 
824 class CVM_API MemoryPool
825 {
826  typedef std::list<tbyte*> list_blocks;
827 
828  struct DeletePtr {
829  template<class T>
830  void operator () (T* p) const {
831  ::delete[] p;
832  }
833  };
834 
835  list_blocks mOutBlocks;
836  MemoryBlocks mMemoryBlocks;
837 
838 public:
839  MemoryPool();
840  ~MemoryPool();
841 
842  tbyte* Malloc(size_t nBytes) throw(cvmexception);
843  tbyte* AddRef(const tbyte* pd);
844  tint Free(tbyte*& pToFree) throw(cvmexception);
845 
846 #ifdef CVM_DEBUG
847  void Assert(const void* pvBlock, size_t nBytes) {
848  mMemoryBlocks.Assert(pvBlock, nBytes);
849  }
850 #endif
851  void Clear();
852 };
853 
854 CVM_API tbyte* _cvmMalloc(size_t nBytes) throw(cvmexception);
855 CVM_API tbyte* _cvmAddRef(const tbyte* pd);
856 CVM_API tint _cvmFree(tbyte*& pd);
857 
864 template<typename T>
865 inline T* cvmMalloc(size_t nEls) throw(cvmexception) {
866  return reinterpret_cast<T*>(_cvmMalloc(nEls * sizeof(T)));
867 }
868 
875 template<typename T>
876 inline T* cvmAddRef(const T* pd) {
877  return reinterpret_cast<T*>(_cvmAddRef(reinterpret_cast<const tbyte*>(pd)));
878 }
879 
887 template<typename T>
888 inline tint cvmFree(T*& pd) {
889  return _cvmFree(reinterpret_cast<tbyte*&>(pd));
890 }
891 
892 #else // CVM_USE_POOL_MANAGER
893 
901 template<typename T>
902 inline T* cvmMalloc(tint nEls) throw(cvmexception)
903 {
904  _check_lt(CVM_WRONGSIZE_LT, nEls, TINT_ZERO);
905  return nEls > 0 ? ::new T[nEls] : nullptr;
906 }
907 
914 template<typename T>
915 inline tint cvmFree(T*& pd)
916 {
917  if (pd != nullptr) {
918  ::delete[] pd;
919  pd = nullptr;
920  }
921  return 0;
922 }
923 
924 #endif // !CVM_USE_POOL_MANAGER
925 
932 CVM_API void cvmExit();
933 
942 template<typename T>
943 inline void cvmZeroMemory(T* p, tint nEls) {
944  memset(p, 0, nEls * sizeof(T));
945 }
946 
948 CVM_API void _cvm_assert(const void* pvBlock, size_t nBytes);
949 
950 inline float _abs(const float& v) {
951  return static_cast<float>(fabs(v));
952 }
953 
954 inline double _abs(const double& v) {
955  return fabs(v);
956 }
957 
958 inline long double _abs(const long double& v) {
959  return fabs(v);
960 }
961 
962 inline float _abs(const std::complex<float>& v) {
963  return static_cast<float>(sqrt(v.real() * v.real() + v.imag() * v.imag()));
964 }
965 
966 inline double _abs(const std::complex<double>& v) {
967  return sqrt(v.real() * v.real() + v.imag() * v.imag());
968 }
969 
970 inline long double _abs(const std::complex<long double>& v) {
971  return sqrt(v.real() * v.real() + v.imag() * v.imag());
972 }
973 
974 inline tint _abs(const tint& v) {
975  return v < 0 ? -v : v;
976 }
977 
978 inline float _sqrt(const float& v) {
979  return static_cast<float>(sqrt(v));
980 }
981 
982 inline double _sqrt(const double& v) {
983  return sqrt(v);
984 }
985 
986 inline std::complex<float> _conjugate(const std::complex<float>& v) {
987  return std::complex<float>(v.real(), -v.imag());
988 }
989 
990 inline std::complex<double> _conjugate(const std::complex<double>& v) {
991  return std::complex<double>(v.real(), -v.imag());
992 }
993 
994 template<typename TR>
995 inline bool _conjugated(const std::complex<TR>& v1, const std::complex<TR>& v2, TR tol)
996 {
997  return _abs(v1.real() - v2.real()) <= tol &&
998  _abs(v1.imag() + v2.imag()) <= tol;
999 }
1001 
1002 
1004 template<typename T, typename TR>
1005 inline std::ostream& operator << (std::ostream& os, const type_proxy<T,TR>& mOut)
1006 {
1007 #if defined (_MSC_VER) && !defined (CVM_USES_STLPORT)
1008  os.imbue(std::locale::empty());
1009 #endif
1010  os << static_cast<T>(mOut);
1011  return os;
1012 }
1013 
1015 template<typename T, typename TR>
1016 inline std::istream& operator >> (std::istream& is, type_proxy<T,TR>& v)
1017 {
1018 #if defined (_MSC_VER) && !defined (CVM_USES_STLPORT)
1019  is.imbue(std::locale::empty());
1020 #endif
1021  T t;
1022  is >> t;
1023  v = t;
1024  return is;
1025 }
1026 
1060 template<typename TR, typename TC>
1061 std::istream& operator >> (std::istream& is, basic_array<TR,TC>& aIn)
1062 {
1063 #if !defined (CVM_USES_STLPORT) && defined (_MSC_VER)
1064  is.imbue(std::locale::empty());
1065 #endif
1066  const tint nSize = aIn.size() * aIn.incr();
1067  CVM_ASSERT(aIn.get(), ((aIn.size() - 1) * aIn.incr() + 1) * sizeof(TC))
1068  for (tint i = 0; i < nSize && is.good(); i += aIn.incr()) {
1069  is >> aIn.get()[i];
1070  }
1071  return is;
1072 }
1073 
1097 template<typename TR, typename TC>
1098 std::ostream& operator << (std::ostream& os, const basic_array<TR,TC>& aOut)
1099 {
1100 #if !defined (CVM_USES_STLPORT) && defined (_MSC_VER)
1101  os.imbue(std::locale::empty());
1102 #endif
1103  const tint nSize = aOut.size() * aOut.incr();
1104  CVM_ASSERT(aOut.get(), ((aOut.size() - 1) * aOut.incr() + 1) * sizeof(TC))
1105  for (tint i = 0; i < nSize && os.good(); i += aOut.incr()) {
1106  os << aOut.get()[i] << CVM_MATRIX_ELEMENT_SEPARATOR;
1107  }
1108  os << CVM_EOL;
1109  return os;
1110 }
1111 
1150 template<typename TR, typename TC>
1151 std::istream& operator >> (std::istream& is, Matrix<TR,TC>& mIn)
1152 {
1153 #if defined (_MSC_VER) && !defined (CVM_USES_STLPORT)
1154  is.imbue(std::locale::empty());
1155 #endif
1156  TC v;
1157  for (tint i = 0; i < mIn.msize(); ++i) {
1158  for (tint j = 0; j < mIn.nsize() && is.good(); ++j) {
1159  is >> v;
1160  mIn._ij_proxy_val(i, j) = v;
1161  }
1162  }
1163  return is;
1164 }
1165 
1193 template<typename TR, typename TC>
1194 std::ostream& operator << (std::ostream& os, const Matrix<TR,TC>& mOut)
1195 {
1196 #if defined (_MSC_VER) && !defined (CVM_USES_STLPORT)
1197  os.imbue(std::locale::empty());
1198 #endif
1199  for (tint i = 0; i < mOut.msize(); ++i) {
1200  for (tint j = 0; j < mOut.nsize() && os.good(); ++j) {
1201  os << mOut._ij_val(i, j) << CVM_MATRIX_ELEMENT_SEPARATOR;
1202  }
1203  os << CVM_EOL;
1204  }
1205  return os;
1206 }
1207 
1209 template<typename TR, typename TC, typename RM, typename RBM>
1210 inline void _copy_b_matrix(RM& m, RBM& mb, bool bLeftToRight)
1211 {
1212  const tint nM = mb.msize();
1213  const tint nN = mb.nsize();
1214  const tint nKL = mb.lsize();
1215  const tint nKU = mb.usize();
1216  const tint nCol = 1 + nKL + nKU;
1217  tint nS, nShiftL, nShiftR;
1218  TC* pL;
1219  TC* pR;
1220 
1221  for (tint i = 0; i < nN; ++i) {
1222  nS = nCol;
1223  nShiftL = 0;
1224  nShiftR = 0;
1225  if (i < nKU) {
1226  nShiftR = nKU - i;
1227  nS -= nShiftR;
1228  } else {
1229  nShiftL = i - nKU;
1230  }
1231  if (nN - i <= nKL) {
1232  nS -= nKL + 1 - (nN - i);
1233  }
1234 
1235  pL = m.get() + i * nM + nShiftL;
1236  pR = mb._pb() + i * nCol + nShiftR;
1237 
1238  __copy<TC>(nS,
1239  bLeftToRight ? pL : pR,
1240  1,
1241  bLeftToRight ? pR : pL,
1242  1);
1243  }
1244 }
1245 
1246 // pd = p1 + p2
1247 template<typename TR, typename TC>
1248 inline void _sum(TC* pd, tint nSize, tint nIncr,
1249  const TC* p1, tint nIncr1, const TC* p2, tint nIncr2)
1250 {
1251  if (pd == p1) {
1252  if (pd == p2) {
1253  static const TR two(2.);
1254  __scal<TR,TC>(pd, nSize, nIncr, two);
1255  } else {
1256  __add<TC>(pd, nSize, nIncr, p2, nIncr2);
1257  }
1258  } else {
1259  if (pd == p2) {
1260  __add<TC>(pd, nSize, nIncr, p1, nIncr1);
1261  } else {
1262  __copy<TC>(nSize, p1, nIncr1, pd, nIncr);
1263  __add<TC>(pd, nSize, nIncr, p2, nIncr2);
1264  }
1265  }
1266 }
1267 
1268 // pd = p1 - p2
1269 template<typename TR, typename TC>
1270 inline void _diff(TC* pd, tint nSize, tint nIncr,
1271  const TC* p1, tint nIncr1, const TC* p2, tint nIncr2)
1272 {
1273  if (pd == p1) {
1274  if (pd == p2) {
1275  static const TR zero(0.);
1276  __scal<TR,TC>(pd, nSize, nIncr, zero);
1277  } else {
1278  __subtract<TC>(pd, nSize, nIncr, p2, nIncr2);
1279  }
1280  } else {
1281  if (pd == p2) {
1282  static const TR mone(-1.);
1283  __subtract<TC>(pd, nSize, nIncr, p1, nIncr1);
1284  __scal<TR,TC>(pd, nSize, nIncr, mone);
1285  } else {
1286  __copy<TC>(nSize, p1, nIncr1, pd, nIncr);
1287  __subtract<TC>(pd, nSize, nIncr, p2, nIncr2);
1288  }
1289  }
1290 }
1291 
1292 // pDm = pDm + pd
1293 template<typename TR, typename TC>
1294 inline void _incr(TC* pDm, tint mnSize, tint mnIncr, const TC* pd, tint nIncr)
1295 {
1296  if (pDm == pd) {
1297  static const TR two(2.);
1298  __scal<TR,TC>(pDm, mnSize, mnIncr, two);
1299  } else {
1300  __add<TC>(pDm, mnSize, mnIncr, pd, nIncr);
1301  }
1302 }
1303 
1304 // pDm = pDm - pd
1305 template<typename TR, typename TC>
1306 inline void _decr(TC* pDm, tint mnSize, tint mnIncr, const TC* pd, tint nIncr)
1307 {
1308  if (pDm == pd) {
1309  static const TR zero(0.);
1310  __scal<TR,TC>(pDm, mnSize, mnIncr, zero);
1311  } else {
1312  __subtract<TC>(pDm, mnSize, mnIncr, pd, nIncr);
1313  }
1314 }
1315 
1316 // fills real part
1317 template<typename TR, typename TC>
1318 void _set_real(TC* pDm, tint mnSize, tint mnIncr, TR d)
1319 {
1320  const tint nIncr2 = 2 * mnIncr;
1321  const tint nSize = mnSize * nIncr2;
1322  TR* pd = __get_real_p<TR>(pDm);
1323  for (tint i = 0; i < nSize; i += nIncr2) {
1324  CVM_ASSERT(pd, (i + 1) * sizeof(TR))
1325  pd[i] = d;
1326  }
1327 }
1328 
1329 // fills imaginary part
1330 template<typename TR, typename TC>
1331 void _set_imag(TC* pDm, tint mnSize, tint mnIncr, TR d)
1332 {
1333  const tint nIncr2 = 2 * mnIncr;
1334  const tint nSize = mnSize * nIncr2;
1335  TR* pd = __get_imag_p<TR>(pDm);
1336  for (tint i = 0; i < nSize; i += nIncr2) {
1337  CVM_ASSERT(pd, (i + 1) * sizeof(TR))
1338  pd[i] = d;
1339  }
1340 }
1342 
1343 
1349 template<typename T, typename TR>
1351 {
1352 protected:
1353  T& mT;
1354  bool mbReadOnly;
1355 
1356 public:
1364  type_proxy(T& ref, bool read_only)
1365  : mT(ref),
1366  mbReadOnly(read_only)
1367  {
1368  }
1369 
1377  type_proxy(const T& ref, bool read_only = true)
1378  : mT(const_cast<T&>(ref)),
1379  mbReadOnly(read_only)
1380  {
1381  }
1382 
1389  type_proxy(const type_proxy& p)
1390  : mT(p.mT),
1391  mbReadOnly(p.mbReadOnly)
1392  {
1393  }
1394 
1401  operator T() const {
1402  return mT;
1403  }
1404 
1405 /*
1406  doesn't work - masks the operator above
1407  operator const T& () const
1408  {
1409  return mT;
1410  }
1411 
1412  operator T& ()
1413  {
1414  if (mbReadOnly) throw cvmexception (CVM_READ_ONLY_ACCESS);
1415  return mT;
1416  }
1417 */
1418 
1425  T val() const {
1426  return mT;
1427  }
1428 
1435  T& get() throw(cvmexception) {
1436  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1437  return mT;
1438  }
1439 
1446  const T& get() const {
1447  return mT;
1448  }
1449 
1457  type_proxy& operator = (const type_proxy& p)
1458  {
1459  mT = p.mT;
1460  mbReadOnly = p.mbReadOnly;
1461  return *this;
1462  }
1463 
1471  type_proxy& operator = (const T& v) throw(cvmexception)
1472  {
1473  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1474  mT = v;
1475  return *this;
1476  }
1477 
1484  T* operator &() throw(cvmexception)
1485  {
1486  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1487  return &mT;
1488  }
1489 
1496  const T* operator &() const {
1497  return &mT;
1498  }
1499 
1507  template<typename U>
1508  T& operator += (const U& u) throw(cvmexception)
1509  {
1510  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1511  mT += T(u);
1512  return mT;
1513  }
1514 
1522  template<typename U>
1523  T& operator -= (const U& u) throw(cvmexception)
1524  {
1525  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1526  mT -= T(u);
1527  return mT;
1528  }
1529 
1537  template<typename U>
1538  T& operator *= (const U& u) throw(cvmexception)
1539  {
1540  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1541  mT *= T(u);
1542  return mT;
1543  }
1544 
1552  template<typename U>
1553  T& operator /= (const U& u) throw(cvmexception)
1554  {
1555  if (mbReadOnly) throw cvmexception(CVM_READ_ONLY_ACCESS);
1556  mT /= T(u);
1557  return mT;
1558  }
1559 
1567  template<typename U>
1568  T operator + (const U& u) const {
1569  return mT + T(u);
1570  }
1571 
1579  template<typename U>
1580  T operator - (const U& u) const {
1581  return mT - T(u);
1582  }
1583 
1591  template<typename U>
1592  T operator * (const U& u) const {
1593  return mT * T(u);
1594  }
1595 
1603  template<typename U>
1604  T operator / (const U& u) const {
1605  return mT / T(u);
1606  }
1607 
1615  T operator + (const type_proxy<T,TR>& u) const {
1616  return mT + u.mT;
1617  }
1618 
1626  T operator - (const type_proxy<T,TR>& u) const {
1627  return mT - u.mT;
1628  }
1629 
1637  T operator * (const type_proxy<T,TR>& u) const {
1638  return mT * u.mT;
1639  }
1640 
1648  T operator / (const type_proxy<T,TR>& u) const {
1649  return mT / u.mT;
1650  }
1651 
1658  T operator - () const {
1659  return -mT;
1660  }
1661 
1669  TR real() const {
1670  return _real<T,TR>(mT);
1671  }
1672 
1680  TR imag() const {
1681  return _imag<T,TR>(mT);
1682  }
1683 };
1684 
1686 template<typename T, typename TR>
1687 inline std::complex<TR> operator + (const std::complex<TR>& u, const type_proxy<T,TR>& p) {
1688  return u + p.val();
1689 }
1690 
1692 template<typename T, typename TR>
1693 inline std::complex<TR> operator - (const std::complex<TR>& u, const type_proxy<T,TR>& p) {
1694  return u - p.val();
1695 }
1696 
1698 template<typename T, typename TR>
1699 inline std::complex<TR> operator * (const std::complex<TR>& u, const type_proxy<T,TR>& p) {
1700  return u * p.val();
1701 }
1702 
1704 template<typename T, typename TR>
1705 inline std::complex<TR> operator / (const std::complex<TR>& u, const type_proxy<T,TR>& p) {
1706  return u / p.val();
1707 }
1708 
1710 template<typename U, typename T, typename TR>
1711 inline T operator + (U u, const type_proxy<T,TR>& p) {
1712  return T(u) + p.val();
1713 }
1714 
1716 template<typename U, typename T, typename TR>
1717 inline T operator - (U u, const type_proxy<T,TR>& p) {
1718  return T(u) - p.val();
1719 }
1720 
1722 template<typename U, typename T, typename TR>
1723 inline T operator * (U u, const type_proxy<T,TR>& p) {
1724  return T(u) * p.val();
1725 }
1726 
1728 template<typename U, typename T, typename TR>
1729 inline T operator / (U u, const type_proxy<T,TR>& p) {
1730  return T(u) / p.val();
1731 }
1732 
1733 
1735 template<typename T>
1737 {
1738  T mMax;
1739 #if !defined(CVM_NO_DEFAULT_RANDOM_ENGINE_SUPPORTED)
1740  std::random_device mre;
1741  std::uniform_int_distribution<int> mDist;
1742 #endif
1743 
1748  Randomizer() noexcept
1749 #if defined(CVM_NO_DEFAULT_RANDOM_ENGINE_SUPPORTED)
1750  : mMax(static_cast<T>(RAND_MAX))
1751  {
1752  srand(static_cast<unsigned int>(time(nullptr)));
1753  }
1754 #else
1755  : mMax(static_cast<T>((std::numeric_limits<int>::max)())),
1756  mre(),
1757  mDist(0, (std::numeric_limits<int>::max)())
1758  {
1759  }
1760 #endif
1761 
1766  T _get(T dFrom, T dTo) noexcept
1767  {
1768  const T dMin = _cvm_min<T>(dFrom, dTo);
1769  const T dMax = _cvm_max<T>(dFrom, dTo);
1770 #if defined(CVM_NO_DEFAULT_RANDOM_ENGINE_SUPPORTED)
1771  unsigned int nr = static_cast<unsigned int>(rand());
1772  return dMin + static_cast<T>(nr) * (dMax - dMin) / mMax;
1773 #else
1774  return dMin + static_cast<T>(mDist(mre)) * (dMax - dMin) / mMax;
1775 #endif
1776  }
1777 
1778 public:
1783  ~Randomizer() noexcept
1784  {
1785  }
1786 
1795  static T get(T dFrom, T dTo) noexcept
1796  {
1797  static Randomizer r;
1798  return r._get(dFrom, dTo);
1799  }
1800 };
1801 
1802 
1817 template<typename TR, typename TC>
1819 {
1820 protected:
1823 
1824 #ifdef CVM_USE_POOL_MANAGER
1825  TC* mpd;
1826 #else
1827  std::shared_ptr<TC> mp;
1828  TC* mpf;
1829 #endif
1830 
1831 public:
1832  typedef TC value_type;
1833  typedef value_type* pointer;
1835  typedef const value_type* const_iterator;
1836  typedef const value_type* const_pointer;
1838  typedef const value_type& const_reference;
1839  typedef size_t size_type;
1840  typedef ptrdiff_t difference_type;
1841  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1842  typedef std::reverse_iterator<iterator> reverse_iterator;
1843 
1864  : msz(0),
1865  mincr(0),
1866 #ifdef CVM_USE_POOL_MANAGER
1867  mpd(nullptr)
1868 #else
1869  mp(),
1870  mpf(nullptr)
1871 #endif
1872  {
1873  }
1874 
1896  explicit basic_array(tint nSize, bool bZeroMemory = true)
1897  : msz(nSize), mincr(1),
1898 #ifdef CVM_USE_POOL_MANAGER
1899  mpd(cvmMalloc<TC>(static_cast<size_t>(msz)))
1900 #else
1901  mp(cvmMalloc<TC>(msz), ArrayDeleter<TC>()),
1902  mpf(nullptr)
1903 #endif
1904  {
1905  CVM_ASSERT(this->get(), msz * sizeof(TC))
1906  if (bZeroMemory) cvmZeroMemory<TC>(this->get(), msz);
1907  }
1908 
1936  basic_array(TC* pd, tint nSize, tint nIncr = 1)
1937  : msz(nSize), mincr(nIncr),
1938 #ifdef CVM_USE_POOL_MANAGER
1939  mpd(cvmAddRef<TC>(pd))
1940 #else
1941  mp(),
1942  mpf(pd)
1943 #endif
1944  {
1945  _check_le(CVM_WRONGSIZE_LE, msz, TINT_ZERO);
1946  CVM_ASSERT(this->get(), msz * sizeof(TC))
1947  }
1948 
1973  basic_array(const TC* pd, tint nSize, tint nIncr = 1)
1974  : msz(nSize), mincr(1),
1975 #ifdef CVM_USE_POOL_MANAGER
1976  mpd(cvmMalloc<TC>(static_cast<size_t>(msz)))
1977 #else
1978  mp(cvmMalloc<TC>(msz), ArrayDeleter<TC>()),
1979  mpf(nullptr)
1980 #endif
1981  {
1982  _check_le(CVM_WRONGSIZE_LE, msz, TINT_ZERO);
1983  CVM_ASSERT(this->get(), msz * sizeof(TC))
1984  __copy<TC>(msz, pd, nIncr, this->get(), this->incr());
1985  }
1986 
2010  basic_array(const TC* begin, const TC* end)
2011  : msz(tint(end - begin)), mincr(1),
2012 #ifdef CVM_USE_POOL_MANAGER
2013  mpd(cvmMalloc<TC>(static_cast<size_t>(msz)))
2014 #else
2015  mp(cvmMalloc<TC>(msz), ArrayDeleter<TC>()),
2016  mpf(nullptr)
2017 #endif
2018  {
2019  CVM_ASSERT(this->get(), msz * sizeof(TC))
2020  __copy<TC>(msz, begin, 1, this->get(), this->incr());
2021  }
2022 
2043  : msz(a.msz), mincr(1),
2044 #ifdef CVM_USE_POOL_MANAGER
2045  mpd(cvmMalloc<TC>(msz))
2046 #else
2047  mp(cvmMalloc<TC>(msz), ArrayDeleter<TC>()),
2048  mpf(nullptr)
2049 #endif
2050  {
2051  this->_assign(a.get(), a.incr());
2052  CVM_ASSERT(this->get(), msz * sizeof(TC))
2053  }
2054 
2072  basic_array(basic_array&& a) noexcept
2073  : msz(a.msz), mincr(a.mincr),
2074 #ifdef CVM_USE_POOL_MANAGER
2075  mpd(nullptr)
2076 #else
2077  mp(),
2078  mpf(nullptr)
2079 #endif
2080  {
2081  _move(std::move(a));
2082  CVM_ASSERT(this->get(), msz * sizeof(TC))
2083  }
2084 
2107  {
2108  _check_ne(CVM_SIZESMISMATCH, a.size(), this->size());
2109  this->_assign(a.get(), a.incr());
2110  return *this;
2111  }
2112 
2127  {
2128  _check_ne(CVM_SIZESMISMATCH, a.size(), this->size());
2129  _move(std::move(a));
2130  CVM_ASSERT(this->get(), msz * sizeof(TC))
2131  return *this;
2132  }
2133 
2139  virtual ~basic_array()
2140  {
2141 #ifdef CVM_USE_POOL_MANAGER
2142  cvmFree<TC>(mpd);
2143 #endif
2144  }
2145 
2164  tint size() const {
2165  return msz;
2166  }
2167 
2200  TC* get()
2201  {
2202 #ifdef CVM_USE_POOL_MANAGER
2203  return this->mpd;
2204 #else
2205  // if foreign pointer is set, this is it, shared one otherwise
2206  return this->mpf == nullptr ? this->mp.get() : this->mpf;
2207 #endif
2208  }
2209 
2242  const TC* get() const
2243  {
2244 #ifdef CVM_USE_POOL_MANAGER
2245  return this->mpd;
2246 #else
2247  // if foreign pointer is set, this is it, shared one otherwise
2248  return this->mpf == nullptr ? this->mp.get() : this->mpf;
2249 #endif
2250  }
2251 
2285  operator TC* () {
2286  return this->get();
2287  }
2288 
2322  operator const TC* () const {
2323  return this->get();
2324  }
2325 
2357  return this->at(static_cast<size_type>(n - CVM0));
2358  }
2359 
2390  TC operator () (tint n) const throw(cvmexception) {
2391  return this->at(static_cast<size_type>(n - CVM0));
2392  }
2393 
2425  return this->at(static_cast<size_type>(n - CVM0));
2426  }
2427 
2458  TC operator [] (tint n) const throw(cvmexception) {
2459  return this->at(static_cast<size_type>(n - CVM0));
2460  }
2461 
2484  basic_array& assign(const TC* p)
2485  {
2486  this->_assign(p, 1);
2487  return *this;
2488  }
2489 
2509  basic_array& set(TC x)
2510  {
2511  this->_set(x);
2512  return *this;
2513  }
2514 
2546  {
2547  this->_resize(nNewSize);
2548  return *this;
2549  }
2550 
2551 
2575  tint incr() const {
2576  return mincr;
2577  }
2578 
2605  tint indofmax() const {
2606  return this->_indofmax();
2607  }
2608 
2635  tint indofmin() const {
2636  return this->_indofmin();
2637  }
2638 
2674  virtual TR norm() const {
2675  return __norm<TR,TC>(this->get(), this->size(), this->incr());
2676  }
2677 
2711  virtual TR norminf() const
2712  {
2713  CVM_ASSERT(this->get(), ((this->_indofmax() - CVM0) * this->incr() + CVM0) * sizeof(TC))
2714  return _abs(this->get()[(this->_indofmax() - CVM0) * this->incr()]);
2715  }
2716 
2752  virtual TR norm1() const
2753  {
2754  TR dNorm(0);
2755  const tint nSize = this->size() * this->incr();
2756  for (tint i = 0; i < nSize; i += this->incr()) {
2757  dNorm += _abs(this->get()[i]);
2758  }
2759  return dNorm;
2760  }
2761 
2801  virtual TR norm2() const
2802  {
2803  return this->norm();
2804  }
2805 
2807  const tint* _pincr() const {
2808  return &this->mincr;
2809  }
2810 
2811  const tint* _psize() const {
2812  return &this->msz;
2813  }
2814 
2815  // this = this / d for real only
2816  void _div(TR d) throw(cvmexception)
2817  {
2818  static const TR one(1.);
2819  if (_abs(d) <= basic_cvmMachMin<TR>()) {
2821  }
2822  this->_scalr(one / d);
2823  }
2824 
2825  // "native pointer": to be redefined in classes with non-traditional storage, like band matrices etc.
2826  virtual TC* _pd() {
2827  return this->get();
2828  }
2829 
2830  // "native pointer": to be redefined in classes with non-traditional storage, like band matrices etc.
2831  virtual const TC* _pd() const {
2832  return this->get();
2833  }
2835 
2837  iterator begin() { return this->get();}
2839  const_iterator begin() const { return this->get();}
2841  iterator end() { return this->get() + this->size();}
2843  const_iterator end() const { return this->get() + this->size();}
2844 
2853 
2855  size_type max_size() const { return size_type(-1) / sizeof(TC);}
2857  size_type capacity() const { return static_cast<size_type>(this->size());}
2859  bool empty() const { return this->size() > 0;}
2860 
2862  reference front() { return *begin();}
2864  const_reference front() const { return *begin();}
2866  reference back() { return *(end() - 1);}
2868  const_reference back() const { return *(end() - 1);}
2869 
2870 // deprecated since 5.4.2 due to its incosistency with STL counterpart
2871 //
2872 // void reserve (size_type n) throw (cvmexception)
2873 // {
2874 // this->_resize(tint(n));
2875 // }
2876 
2878  void assign(size_type n, const TC& val) throw(cvmexception)
2879  {
2880  _check_gt(CVM_INDEX_GT, n, static_cast<size_type>(this->size()));
2881  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
2882  for (tint i = 0; i < (tint)n; ++i) {
2883  this->get()[i] = val;
2884  }
2885  }
2886 
2889  {
2890  const tint n = end - begin;
2891  _check_gt(CVM_INDEX_GT, n, this->size());
2892  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
2893  for (tint i = 0; i < n; ++i) {
2894  this->get()[i] = *(begin + i);
2895  }
2896  }
2897 
2899  void clear() {
2900  this->_resize(0);
2901  }
2902 
2905  {
2906  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
2907  __swap<TC>(this->size(), this->get(), this->incr(), v.get(), v.incr());
2908  }
2909 
2912  {
2913  _check_ge(CVM_INDEX_GE, n, static_cast<size_type>(this->size()));
2914  CVM_ASSERT(this->get(), (n + 1) * sizeof(TC))
2915  return this->get()[n * this->incr()];
2916  }
2917 
2920  {
2921  _check_ge(CVM_INDEX_GE, n, static_cast<size_type>(this->size()));
2922  CVM_ASSERT(this->get(), (n + 1) * sizeof(TC))
2923  return this->get()[n * this->incr()];
2924  }
2925 
2953  void push_back(const TC& x) throw(cvmexception)
2954  {
2955  this->_resize(this->size() + 1);
2956  this->get()[this->size() - 1] = x;
2957  }
2958 
2985  void pop_back() throw(cvmexception) {
2986  if (this->size() > 0) this->_resize(this->size() - 1);
2987  }
2988 
3023  iterator insert(iterator position, const TC& x) throw(cvmexception)
3024  {
3025  const tint n = tint(position - this->begin());
3026  _check_lt_gt(CVM_OUTOFRANGE_LTGT, n, TINT_ZERO, this->size());
3027  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
3028  this->_resize(this->size() + 1);
3029  for (tint i = this->size() - 1; i > n; --i) {
3030  this->get()[i] = this->get()[i - 1];
3031  }
3032  this->get()[n] = x;
3033  return iterator(this->get() + n);
3034  }
3035 
3070  {
3071  const tint n = tint(position - this->begin());
3072  _check_lt_gt(CVM_OUTOFRANGE_LTGT, n, TINT_ZERO, this->size());
3073 
3074  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
3075  for (tint i = n; i < this->size() - 1; ++i) {
3076  this->get()[i] = this->get()[i + 1];
3077  }
3078  if (this->size() > 0) this->_resize(this->size() - 1);
3079  return iterator(this->get() + n);
3080  }
3081 
3082 protected:
3084  // internal protected constructor to be used in Matrix
3085  basic_array(tint sz, tint incr) noexcept
3086  : msz(sz), mincr(incr),
3087 #ifdef CVM_USE_POOL_MANAGER
3088  mpd(nullptr)
3089 #else
3090  mp(),
3091  mpf(nullptr)
3092 #endif
3093  {
3094  }
3095 
3097  void _move(basic_array&& a) noexcept
3098  {
3099 #ifdef CVM_USE_POOL_MANAGER
3100  mpd = a.mpd;
3101  a.mpd = nullptr;
3102 #else
3103  if (a.mpf == nullptr) {
3104  if (mpf == nullptr) {
3105  mp = std::move(a.mp);
3106  a.msz = 0;
3107  } else {
3108  // *this has foreign array inside, no place to move to
3109  // so, this is the case where we don't even touch a, just copy its content
3110  this->_assign(a.mp.get(), a.incr());
3111  }
3112  } else {
3113  // ... and here we can't rely on foreign poiter life cycle, thus copying
3114  this->_resize(a.size());
3115  this->_assign(a.mpf, a.incr());
3116  //a.mpf = nullptr;
3117  //a.msz = 0;
3118  }
3119 #endif
3120  }
3121 
3122  // compares array elements
3123  bool _equals(const basic_array& a) const
3124  {
3125  bool bRes = false;
3126  if (this->size() == a.size()) {
3127  bRes = true;
3128  if (this->get() != a.get()) {
3129  for (tint i = 0; i < this->size(); ++i) {
3130  if (_abs(this->get()[i * this->incr()] - a.get()[i * a.incr()]) > basic_cvmMachMin<TR>()) {
3131  bRes = false;
3132  break;
3133  }
3134  }
3135  }
3136  }
3137  return bRes;
3138  }
3139 
3140  // array normalizing
3141  void _normalize()
3142  {
3143  const TR dNorm = this->norm();
3144  if (dNorm > basic_cvmMachMin<TR>()) {
3145  static const TR one(1.);
3146  this->_scalr(one / dNorm);
3147  }
3148  }
3149 
3150  // this = a (no matter what)
3151  void _replace(const basic_array& a) throw(cvmexception)
3152  {
3153 #ifdef CVM_USE_POOL_MANAGER
3154  cvmFree<TC>(this->mpd);
3155  this->mpd = cvmMalloc<TC>(a.size());
3156 #else
3157  this->mp.reset(cvmMalloc<TC>(a.size()), ArrayDeleter<TC>());
3158  this->mpf = nullptr;
3159 #endif
3160  this->msz = a.size();
3161  this->mincr = 1;
3162  CVM_ASSERT(this->get(), ((this->size() - 1) * this->incr() + 1) * sizeof(TC))
3163  }
3164 
3165  void _resize(tint nNewSize) throw(cvmexception)
3166  {
3167  _check_lt(CVM_WRONGSIZE_LT, nNewSize, TINT_ZERO);
3168  const bool is_empty = this->_is_empty();
3169  if (nNewSize != this->size() || is_empty) {
3170  TC* pd = cvmMalloc<TC>(nNewSize);
3171  if (nNewSize > this->size()) cvmZeroMemory<TC>(pd, nNewSize);
3172  const tint nMinSize = _cvm_min<tint>(nNewSize, this->size());
3173  if (nMinSize > 0 && !is_empty) {
3174  __copy<TC>(nMinSize, this->get(), this->incr(), pd, 1);
3175  }
3176 #ifdef CVM_USE_POOL_MANAGER
3177  cvmFree<TC>(this->mpd);
3178  this->mpd = pd;
3179 #else
3180  this->mp.reset(pd, ArrayDeleter<TC>());
3181  this->mpf = nullptr;
3182 #endif
3183  this->msz = nNewSize;
3184  this->mincr = 1;
3185  CVM_ASSERT(this->get(), ((this->size() - 1) * this->incr() + 1) * sizeof(TC))
3186  }
3187  }
3188 
3189  bool _is_empty() const
3190  {
3191 #ifdef CVM_USE_POOL_MANAGER
3192  return this->mpd == nullptr;
3193 #else
3194  return this->mpf == nullptr && this->mp.get() == nullptr;
3195 #endif
3196  }
3197 
3198  // virtual methods
3199  virtual void _scalr(TR d) {
3200  __scal<TR,TC>(this->get(), this->size(), this->incr(), d);
3201  }
3202 
3203  // index of max module, undefined for matrices, CVM0-based
3204  virtual tint _indofmax() const {
3205  return __idamax<TC>(this->get(), this->size(), this->incr());
3206  }
3207 
3208  // index of min module, undefined for matrices, CVM0-based
3209  virtual tint _indofmin() const {
3210  return __idamin<TC>(this->get(), this->size(), this->incr());
3211  }
3212 
3213  // fills the content
3214  virtual void _set(TC d)
3215  {
3216  CVM_ASSERT(this->get(), ((this->size() - 1) * this->incr() + 1) * sizeof(TC))
3217  const tint nSize = this->size() * this->incr();
3218  for (tint i = 0; i < nSize; i += this->incr()) {
3219  this->get()[i] = d;
3220  }
3221  }
3222 
3223  virtual void _assign(const TC* pd, tint nIncr)
3224  {
3225  if (this->get() != pd) {
3226  __copy<TC>(this->size(), pd, nIncr, this->get(), this->incr());
3227  }
3228  }
3229 
3230  virtual void _assign_shifted(TC* pDshifted, const TC* pd, tint nSize, tint nIncr, tint)
3231  {
3232  if (pDshifted != pd) {
3233  __copy<TC>(nSize, pd, nIncr, pDshifted, this->incr());
3234  }
3235  }
3237 
3271  friend std::istream& operator >> <> (std::istream& is, basic_array& aIn);
3272 
3296  friend std::ostream& operator << <> (std::ostream& os, const basic_array& aOut);
3297 };
3298 
3299 
3306 template<typename TR>
3307 class basic_rvector : public basic_array<TR,TR>
3308 {
3309  typedef std::complex<TR> TC;
3310  typedef basic_array<TR,TR> BaseArray;
3311 
3312 public:
3338  {
3339  }
3340 
3361  explicit basic_rvector(tint nSize)
3362  : BaseArray(nSize)
3363  {
3364  }
3365 
3366 #if defined(CVM_USE_INITIALIZER_LISTS)
3367 
3388  basic_rvector(std::initializer_list<TR> list)
3389  : BaseArray(static_cast<tint>(list.size()))
3390  {
3391  tint i = 0;
3392  TR* p = this->mp.get();
3393  for (auto it = list.begin(); it != list.end(); ++it) {
3394  p[i++] = *it;
3395  }
3396  }
3397 #endif
3398 
3420  basic_rvector(tint nSize, TR d)
3421  : BaseArray(nSize, false)
3422  {
3423  this->_set(d);
3424  }
3425 
3490  basic_rvector(TR* pd, tint nSize, tint nIncr = 1)
3491  : BaseArray(pd, nSize, nIncr)
3492  {
3493  }
3494 
3536  basic_rvector(const TR* pd, tint nSize, tint nIncr = 1)
3537  : BaseArray(pd, nSize, nIncr)
3538  {
3539  }
3540 
3541 
3571  : BaseArray(v.size(), false)
3572  {
3573  __copy<TR>(this->size(), v, v.incr(), this->get(), this->incr());
3574  }
3575 
3580  : BaseArray(std::move(a))
3581  {
3582  }
3583 
3617  {
3618  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
3619  this->_assign(v, v.incr());
3620  return *this;
3621  }
3622 
3627  {
3628  // size check is in BasicArray
3629  BaseArray::operator = (std::move(a));
3630  return *this;
3631  }
3632 
3664  basic_rvector& assign(const TR* pd, tint nIncr = 1)
3665  {
3666  this->_assign(pd, nIncr);
3667  return *this;
3668  }
3669 
3701  basic_rvector& assign(tint n, const TR* pd, tint nIncr = 1)
3702  {
3703  _check_lt_ge(CVM_OUTOFRANGE_LTGE, n, CVM0, this->size() + CVM0);
3704  n -= CVM0;
3705  this->_assign_shifted(this->get() + this->incr() * n, pd, this->size() - n, nIncr, 0);
3706  return *this;
3707  }
3708 
3742  basic_rvector& assign(tint n, const TR* pd, tint nSize, tint nIncr)
3743  {
3744  _check_lt_ge(CVM_OUTOFRANGE_LTGE, n, CVM0, this->size() + CVM0);
3745  n -= CVM0;
3746  this->_assign_shifted(this->get() + this->incr() * n, pd, _cvm_min<tint>(nSize, this->size() - n), nIncr, 0);
3747  return *this;
3748  }
3749 
3781  {
3782  _check_gt(CVM_SIZESMISMATCH_GT, v.size() + n, this->size());
3783  return assign(n, v, v.size(), v.incr());
3784  }
3785 
3809  basic_rvector& set(TR d)
3810  {
3811  this->_set(d);
3812  return *this;
3813  }
3814 
3853  {
3854  this->_resize(nNewSize);
3855  return *this;
3856  }
3857 
3887  bool operator == (const basic_rvector& v) const {
3888  return this->_equals(v);
3889  }
3890 
3920  bool operator != (const basic_rvector& v) const {
3921  return !(this->operator == (v));
3922  }
3923 
3962  {
3963  this->_replace(v);
3964  __copy<TR>(this->size(), v.get(), v.incr(), this->get(), this->incr());
3965  return *this;
3966  }
3967 
4006  {
4007  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
4008  basic_rvector vSum(*this);
4009  __add<TR>(vSum.get(), vSum.size(), vSum.incr(), v._pd(), v.incr());
4010  return vSum;
4011  }
4012 
4050  {
4051  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
4052  basic_rvector vDiff(*this);
4053  __subtract<TR>(vDiff.get(), vDiff.size(), vDiff.incr(), v._pd(), v.incr());
4054  return vDiff;
4055  }
4056 
4095  {
4096  _check_ne(CVM_SIZESMISMATCH, v1.size(), this->size());
4097  _check_ne(CVM_SIZESMISMATCH, v2.size(), this->size());
4098  _sum<TR,TR>(this->get(), this->size(), this->incr(), v1, v1.incr(), v2, v2.incr());
4099  return *this;
4100  }
4101 
4140  {
4141  _check_ne(CVM_SIZESMISMATCH, v1.size(), this->size());
4142  _check_ne(CVM_SIZESMISMATCH, v2.size(), this->size());
4143  _diff<TR,TR>(this->get(), this->size(), this->incr(), v1, v1.incr(), v2, v2.incr());
4144  return *this;
4145  }
4146 
4187  {
4188  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
4189  _incr<TR,TR>(this->get(), this->size(), this->incr(), v, v.incr());
4190  return *this;
4191  }
4192 
4233  {
4234  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
4235  _decr<TR,TR>(this->get(), this->size(), this->incr(), v, v.incr());
4236  return *this;
4237  }
4238 
4263  {
4264  static const TR mone(-1.);
4265  basic_rvector vRes(*this);
4266  vRes._scalr(mone);
4267  return vRes;
4268  }
4269 
4295  basic_rvector operator * (TR dMult) const throw(cvmexception)
4296  {
4297  basic_rvector vRes(*this);
4298  vRes._scalr(dMult);
4299  return vRes;
4300  }
4301 
4335  {
4336  basic_rvector vRes(*this);
4337  vRes._div(dDiv);
4338  return vRes;
4339  }
4340 
4366  {
4367  this->_scalr(dMult);
4368  return *this;
4369  }
4370 
4403  {
4404  this->_div(dDiv);
4405  return *this;
4406  }
4407 
4437  {
4438  this->_normalize();
4439  return *this;
4440  }
4441 
4473  TR operator * (const basic_rvector& v) const throw(cvmexception)
4474  {
4475  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
4476  return __dot<TR>(this->get(), this->size(), this->incr(), v.get(), v.incr());
4477  }
4478 
4513  {
4514  _check_ne(CVM_SIZESMISMATCH, m.msize(), this->size());
4515  basic_rvector vRes(m.nsize());
4516  m._multiply(vRes, *this, true);
4517  return vRes;
4518  }
4519 
4552  {
4553  _check_ne(CVM_SIZESMISMATCH, m.nsize(), this->size());
4554  _check_ne(CVM_SIZESMISMATCH, m.msize(), v.size());
4555  m._multiply(*this, v, true);
4556  return *this;
4557  }
4558 
4591  {
4592  _check_ne(CVM_SIZESMISMATCH, m.msize(), this->size());
4593  _check_ne(CVM_SIZESMISMATCH, m.nsize(), v.size());
4594  m._multiply(*this, v, false);
4595  return *this;
4596  }
4597 
4642  {
4643  basic_rmatrix<TR> mRes(this->size(), v.size());
4644  static const TR one(1.);
4645  __ger<TR,basic_rmatrix<TR>, basic_rvector>(mRes, *this, v, one);
4646  return mRes;
4647  }
4648 
4695  basic_rvector& solve(const basic_srmatrix<TR>& mA, const basic_rvector& vB, TR& dErr) throw(cvmexception) {
4696  return _solve_helper(mA, vB, dErr, 0);
4697  }
4698 
4699 // 6.1: transpose added
4746  basic_rvector& solve_tran(const basic_srmatrix<TR>& mA, const basic_rvector& vB, TR& dErr) throw(cvmexception) {
4747  return _solve_helper(mA, vB, dErr, 1);
4748  }
4749 
4792  {
4793  static TR dErr(0.);
4794  return this->solve(mA, vB, dErr);
4795  }
4796 
4797 // 6.1: transpose added
4841  {
4842  static TR dErr(0.);
4843  return this->solve_tran(mA, vB, dErr);
4844  }
4845 
4846 // 6.1: MATLAB-style operator B/A returning solution of X*A=B equation
4886  return _operator_solve_helper(mA, 1);
4887  }
4888 
4889  // 6.1: similar to operator / this one returns solution of A*X=B equation
4926  return _operator_solve_helper(mA, 0);
4927  }
4928 
4991  basic_rvector& solve_lu(const basic_srmatrix<TR>& mA, const basic_srmatrix<TR>& mLU, const tint* pPivots,
4992  const basic_rvector& vB, TR& dErr) throw(cvmexception)
4993  {
4994  _check_ne(CVM_SIZESMISMATCH, mA.msize(), this->size());
4995  _check_ne(CVM_SIZESMISMATCH, mA.msize(), vB.size());
4996  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mLU.msize());
4997  mA._solve(vB, *this, dErr, mLU, pPivots, 0);
4998  return *this;
4999  }
5000 
5056  basic_rvector& solve_lu(const basic_srmatrix<TR>& mA, const basic_srmatrix<TR>& mLU, const tint* pPivots,
5057  const basic_rvector& vB) throw(cvmexception)
5058  {
5059  static TR dErr(0.);
5060  return this->solve_lu(mA, mLU, pPivots, vB, dErr);
5061  }
5062 
5117  basic_rvector& gels(bool transpose, const basic_rmatrix<TR>& mA, const basic_rvector& vB,
5118  TR& dErr) throw(cvmexception)
5119  {
5120  _check_ne(CVM_SIZESMISMATCH, vB.size(), transpose ? mA.nsize() : mA.msize());
5121  _check_ne(CVM_SIZESMISMATCH, this->size(), transpose ? mA.msize() : mA.nsize());
5122  basic_rmatrix<TR> mA2(mA); // this algorithm overrides A
5123  basic_rmatrix<TR> mB(vB, vB.size(), 1);
5124  basic_rmatrix<TR> mX;
5125  basic_rvector vErr(1);
5126  __gels(transpose, mA2, mB, mX, vErr);
5127  dErr = vErr(CVM0);
5128  *this = mX(CVM0);
5129  return *this;
5130  }
5131 
5179  TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
5180  {
5181  _check_ne(CVM_SIZESMISMATCH, vB.size(), mA.msize());
5182  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
5183  basic_rmatrix<TR> mA2(mA); // this algorithm overrides A
5184  basic_rmatrix<TR> mB(vB, vB.size(), 1);
5185  basic_rmatrix<TR> mX;
5186  __gelsy(mA2, mB, mX, tol, rank);
5187  *this = mX(CVM0);
5188  return *this;
5189  }
5190 
5244  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
5245  {
5246  _gels_sd(true, mA, vB, sv, rank, tol);
5247  return *this;
5248  }
5249 
5304  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
5305  {
5306  _gels_sd(false, mA, vB, sv, rank, tol);
5307  return *this;
5308  }
5309 
5383  {
5384  mA._svd(*this, nullptr, nullptr);
5385  return *this;
5386  }
5387 
5461  {
5462  mA._svd(*this, nullptr, nullptr);
5463  return *this;
5464  }
5465 
5544  basic_srmatrix<TR>& mVH) throw(cvmexception)
5545  {
5546  mA._svd(*this, &mU, &mVH);
5547  return *this;
5548  }
5549 
5628  basic_scmatrix<TR,TC>& mVH) throw(cvmexception)
5629  {
5630  mA._svd(*this, &mU, &mVH);
5631  return *this;
5632  }
5633 
5634 // we don't use _eig here since this is the special case - symmetric matrix
5707  {
5708  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
5709  __eig<basic_rvector, basic_srsmatrix<TR>, basic_srmatrix<TR> >(*this, mA, nullptr, true);
5710  return *this;
5711  }
5712 
5787  {
5788  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
5789  _check_ne(CVM_SIZESMISMATCH, this->size(), mEigVect.nsize());
5790  __eig<basic_rvector, basic_srsmatrix<TR>, basic_srmatrix<TR> >(*this, mA, &mEigVect, true);
5791  return *this;
5792  }
5793 
5794 // we don't use _eig here since this is the special case - hermitian matrix
5867  {
5868  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
5869  __eig<basic_rvector, basic_schmatrix<TR,TC>, basic_scmatrix<TR,TC> >(*this, mA, nullptr, true);
5870  return *this;
5871  }
5872 
5947  {
5948  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
5949  _check_ne(CVM_SIZESMISMATCH, this->size(), mEigVect.nsize());
5950  __eig<basic_rvector, basic_schmatrix<TR,TC>, basic_scmatrix<TR,TC> >(*this, mA, &mEigVect, true);
5951  return *this;
5952  }
5953 
5954 // ?gemv routines perform a matrix-vector operation defined as
5955 // this = alpha*m*v + beta * this,
6008  basic_rvector& gemv(bool bLeft, const basic_rmatrix<TR>& m, TR dAlpha, const basic_rvector& v, TR dBeta) throw(cvmexception)
6009  {
6010  _check_ne(CVM_SIZESMISMATCH, this->size(), bLeft ? m.nsize() : m.msize());
6011  _check_ne(CVM_SIZESMISMATCH, v.size(), bLeft ? m.msize() : m.nsize());
6012  m._gemv(bLeft, dAlpha, v, dBeta, *this);
6013  return *this;
6014  }
6015 
6068  basic_rvector& gbmv(bool bLeft, const basic_srbmatrix<TR>& m, TR dAlpha, const basic_rvector& v, TR dBeta) throw(cvmexception)
6069  {
6070  _check_ne(CVM_SIZESMISMATCH, this->size(), bLeft ? m.nsize() : m.msize());
6071  _check_ne(CVM_SIZESMISMATCH, v.size(), bLeft ? m.msize() : m.nsize());
6072  m._gbmv(bLeft, dAlpha, v, dBeta, *this);
6073  return *this;
6074  }
6075 
6099  basic_rvector& randomize(TR dFrom, TR dTo)
6100  {
6101  __randomize<TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
6102  return *this;
6103  }
6104 
6105 private:
6107  basic_rvector& _solve_helper(const basic_srmatrix<TR>& mA, const basic_rvector& vB,
6108  TR& dErr, int transp_mode) throw(cvmexception)
6109  {
6110  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.msize());
6111  _check_ne(CVM_SIZESMISMATCH, vB.size(), mA.msize());
6112  mA._solve(vB, *this, dErr, nullptr, nullptr, transp_mode);
6113  return *this;
6114  }
6115 
6116  basic_rvector _operator_solve_helper(const basic_srmatrix<TR>& mA, int transp_mode) const throw(cvmexception)
6117  {
6118  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.msize());
6119  static TR dErr(0.);
6120  basic_rvector vX(this->size());
6121  mA._solve(*this, vX, dErr, nullptr, nullptr, transp_mode);
6122  return vX;
6123  }
6124 
6125  // helper for svd and divide&conquer methods
6126  void _gels_sd(bool svd, const basic_rmatrix<TR>& mA, const basic_rvector& vB,
6127  basic_rvector<TR>& sv, tint& rank, TR tol) throw(cvmexception)
6128  {
6129  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
6130  _check_ne(CVM_SIZESMISMATCH, vB.size(), mA.msize());
6131  _check_ne(CVM_SIZESMISMATCH, sv.size(), _cvm_min<tint>(mA.msize(), mA.nsize()));
6132  basic_rmatrix<TR> mA2(mA); // this algorithm overrides A
6133  basic_rmatrix<TR> mB(vB, vB.size(), 1);
6134  basic_rmatrix<TR> mX;
6135  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
6136  if (svd) {
6137  __gelss(mA2, mB, mX, tol, sv1, rank);
6138  } else {
6139  __gelsd(mA2, mB, mX, tol, sv1, rank);
6140  }
6141  sv = sv1;
6142  *this = mX(CVM0);
6143  }
6145 };
6146 
6147 
6154 template<typename TR, typename TC>
6155 class basic_cvector : public basic_array<TR,TC>
6156 {
6157  typedef basic_array<TR,TC> BaseArray;
6158 
6159 public:
6185  {
6186  }
6187 
6210  explicit basic_cvector(tint nSize)
6211  : BaseArray(nSize)
6212  {
6213  }
6214 
6215 #if defined(CVM_USE_INITIALIZER_LISTS)
6216 
6242  basic_cvector(std::initializer_list<TC> list)
6243  : BaseArray(static_cast<tint>(list.size()))
6244  {
6245  tint i = 0;
6246  TC* p = this->mp.get();
6247  for (auto it = list.begin(); it != list.end(); ++it) {
6248  p[i++] = *it;
6249  }
6250  }
6251 #endif
6252 
6274  basic_cvector(tint nSize, TC c)
6275  : BaseArray(nSize, false)
6276  {
6277  this->_set(c);
6278  }
6279 
6343  basic_cvector(TC* pd, tint nSize, tint nIncr = 1)
6344  : BaseArray(pd, nSize, nIncr)
6345  {
6346  }
6347 
6388  basic_cvector(const TC* pd, tint nSize, tint nIncr = 1)
6389  : BaseArray(pd, nSize, nIncr)
6390  {
6391  }
6392 
6422  : BaseArray(v.size(), false)
6423  {
6424  __copy<TC>(this->size(), v, v.incr(), this->get(), this->incr());
6425  }
6426 
6445  : BaseArray(std::move(a))
6446  {
6447  }
6448 
6488  basic_cvector(const TR* pRe, const TR* pIm, tint nSize, tint nIncrRe = 1, tint nIncrIm = 1)
6489  : BaseArray(nSize, pRe == nullptr || pIm == nullptr)
6490  {
6491  __copy2<TR,TC>(this->get(), this->size(), this->incr(), pRe, pIm, nIncrRe, nIncrIm);
6492  }
6493 
6528  : BaseArray(vRe.size(), false)
6529  {
6530  _check_ne(CVM_SIZESMISMATCH, vRe.size(), vIm.size());
6531  __copy2<TR,TC>(this->get(), this->size(), this->incr(), vRe, vIm, vRe.incr(), vIm.incr());
6532  }
6533 
6566  basic_cvector(const TR* pA, tint nSize, bool bRealPart = true, tint nIncr = 1)
6567  : BaseArray(nSize)
6568  {
6569  if (bRealPart) __copy2<TR,TC>(this->get(), this->size(), this->incr(), pA, nullptr, nIncr, 0);
6570  else __copy2<TR,TC>(this->get(), this->size(), this->incr(), nullptr, pA, 0, nIncr);
6571  }
6572 
6603  explicit basic_cvector(const basic_rvector<TR>& v, bool bRealPart = true)
6604  : BaseArray(v.size())
6605  {
6606  if (bRealPart) __copy2<TR,TC>(this->get(), this->size(), this->incr(), v, nullptr, v.incr(), 0);
6607  else __copy2<TR,TC>(this->get(), this->size(), this->incr(), nullptr, v, 0, v.incr());
6608  }
6609 
6638  return basic_rvector<TR>(__get_real_p<TR>(this->get()), this->size(), this->incr() * 2);
6639  }
6640 
6669  return basic_rvector<TR>(__get_imag_p<TR>(this->get()), this->size(), this->incr() * 2);
6670  }
6671 
6701  {
6702  _check_ne(CVM_SIZESMISMATCH, this->size(), v.size());
6703  this->_assign(v, v.incr());
6704  return *this;
6705  }
6706 
6721  {
6722  // size check is in BasicArray
6723  BaseArray::operator = (std::move(a));
6724  return *this;
6725  }
6726 
6757  basic_cvector& assign(const TC* pd, tint nIncr = 1)
6758  {
6759  this->_assign(pd, nIncr);
6760  return *this;
6761  }
6762 
6792  basic_cvector& assign(tint n, const TC* pd, tint nIncr = 1)
6793  {
6794  _check_lt_ge(CVM_OUTOFRANGE_LTGE, n, CVM0, this->size() + CVM0);
6795  n -= CVM0;
6796  this->_assign_shifted(this->get() + this->incr() * n, pd, this->size() - n, nIncr, 0);
6797  return *this;
6798  }
6799 
6827  basic_cvector& assign(tint n, const TC* pd, tint nSize, tint nIncr)
6828  {
6829  _check_lt_ge(CVM_OUTOFRANGE_LTGE, n, CVM0, this->size() + CVM0);
6830  n -= CVM0;
6831  this->_assign_shifted(this->get() + this->incr() * n, pd, _cvm_min<tint>(nSize, this->size() - n), nIncr, 0);
6832  return *this;
6833  }
6834 
6863  {
6864  _check_gt(CVM_SIZESMISMATCH_GT, v.size() + n, this->size());
6865  return assign(n, v, v.size(), v.incr());
6866  }
6867 
6891  basic_cvector& set(TC c)
6892  {
6893  this->_set(c);
6894  return *this;
6895  }
6896 
6924  {
6925  _check_ne(CVM_SIZESMISMATCH, vRe.size(), this->size());
6926  __copy_real<TR,TC>(this->get(), this->size(), this->incr(), vRe, vRe.incr());
6927  return *this;
6928  }
6929 
6957  {
6958  _check_ne(CVM_SIZESMISMATCH, vIm.size(), this->size());
6959  __copy_imag<TR,TC>(this->get(), this->size(), this->incr(), vIm, vIm.incr());
6960  return *this;
6961  }
6962 
6986  {
6987  this->_set_real_number(d);
6988  return *this;
6989  }
6990 
7014  {
7015  this->_set_imag_number(d);
7016  return *this;
7017  }
7018 
7055  {
7056  this->_resize(nNewSize);
7057  return *this;
7058  }
7059 
7089  bool operator == (const basic_cvector& v) const {
7090  return this->_equals(v);
7091  }
7092 
7119  bool operator != (const basic_cvector& v) const {
7120  return !(this->operator == (v));
7121  }
7122 
7161  {
7162  this->_replace(v);
7163  __copy<TC>(this->size(), v.get(), v.incr(), this->get(), this->incr());
7164  return *this;
7165  }
7166 
7204  {
7205  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7206  basic_cvector vSum(*this);
7207  __add<TC>(vSum.get(), vSum.size(), vSum.incr(), v._pd(), v.incr());
7208  return vSum;
7209  }
7210 
7247  {
7248  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7249  basic_cvector vDiff(*this);
7250  __subtract<TC>(vDiff.get(), vDiff.size(), vDiff.incr(), v._pd(), v.incr());
7251  return vDiff;
7252  }
7253 
7292  {
7293  _check_ne(CVM_SIZESMISMATCH, v1.size(), this->size());
7294  _check_ne(CVM_SIZESMISMATCH, v2.size(), this->size());
7295  _sum<TR,TC>(this->get(), this->size(), this->incr(), v1, v1.incr(), v2, v2.incr());
7296  return *this;
7297  }
7298 
7337  {
7338  _check_ne(CVM_SIZESMISMATCH, v1.size(), this->size());
7339  _check_ne(CVM_SIZESMISMATCH, v2.size(), this->size());
7340  _diff<TR,TC>(this->get(), this->size(), this->incr(), v1, v1.incr(), v2, v2.incr());
7341  return *this;
7342  }
7343 
7384  {
7385  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7386  _incr<TR,TC>(this->get(), this->size(), this->incr(), v, v.incr());
7387  return *this;
7388  }
7389 
7430  {
7431  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7432  _decr<TR,TC>(this->get(), this->size(), this->incr(), v, v.incr());
7433  return *this;
7434  }
7435 
7460  {
7461  static const TR mone(-1.);
7462  basic_cvector vRes(*this);
7463  vRes._scalr(mone);
7464  return vRes;
7465  }
7466 
7493  basic_cvector operator * (TR dMult) const
7494  {
7495  basic_cvector vRes(*this);
7496  vRes._scalr(dMult);
7497  return vRes;
7498  }
7499 
7529  {
7530  basic_cvector vRes(*this);
7531  vRes._div(dDiv);
7532  return vRes;
7533  }
7534 
7561  basic_cvector operator * (TC cMult) const
7562  {
7563  basic_cvector vRes(*this);
7564  vRes._scalc(cMult);
7565  return vRes;
7566  }
7567 
7597  {
7598  basic_cvector vRes(*this);
7599  vRes._div(cDiv);
7600  return vRes;
7601  }
7602 
7628  {
7629  this->_scalr(dMult);
7630  return *this;
7631  }
7632 
7660  {
7661  this->_div(dDiv);
7662  return *this;
7663  }
7664 
7691  {
7692  this->_scalc(cMult);
7693  return *this;
7694  }
7695 
7724  {
7725  this->_div(cDiv);
7726  return *this;
7727  }
7728 
7756  {
7757  this->_normalize();
7758  return *this;
7759  }
7760 
7790  {
7791  basic_cvector vRes(*this);
7792  __conj<TC>(vRes.get(), vRes.size(), vRes.incr());
7793  return vRes;
7794  }
7795 
7825  {
7826  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7827  this->_assign(v, v.incr());
7828  __conj<TC>(this->get(), this->size(), this->incr());
7829  return *this;
7830  }
7831 
7860  {
7861  __conj<TC>(this->get(), this->size(), this->incr());
7862  return *this;
7863  }
7864 
7890  TC operator * (const basic_cvector& v) const throw(cvmexception)
7891  {
7892  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7893  return __dotu<TC>(this->get(), this->size(), this->incr(), v.get(), v.incr());
7894  }
7895 
7923  TC operator % (const basic_cvector& v) const throw(cvmexception)
7924  {
7925  _check_ne(CVM_SIZESMISMATCH, v.size(), this->size());
7926  return __dotc<TC>(this->get(), this->size(), this->incr(), v.get(), v.incr());
7927  }
7928 
7964  {
7965  _check_ne(CVM_SIZESMISMATCH, m.msize(), this->size());
7966  basic_cvector vRes(m.nsize());
7967  m._multiply(vRes, *this, true);
7968  return vRes;
7969  }
7970 
8013  {
8014  _check_ne(CVM_SIZESMISMATCH, m.nsize(), this->size());
8015  _check_ne(CVM_SIZESMISMATCH, m.msize(), v.size());
8016  m._multiply(*this, v, true);
8017  return *this;
8018  }
8019 
8061  {
8062  _check_ne(CVM_SIZESMISMATCH, m.msize(), this->size());
8063  _check_ne(CVM_SIZESMISMATCH, v.size(), m.nsize());
8064  m._multiply(*this, v, false);
8065  return *this;
8066  }
8067 
8112  {
8113  basic_cmatrix<TR,TC> mRes(this->size(), v.size());
8114  static const TC one(1., 0.);
8115  __geru<TC, basic_cmatrix<TR,TC>, basic_cvector>(mRes, *this, v, one);
8116  return mRes;
8117  }
8118 
8169  {
8170  basic_cmatrix<TR,TC> mRes(this->size(), v.size());
8171  static const TC one(1., 0.);
8172  __gerc<TC, basic_cmatrix<TR,TC>, basic_cvector>(mRes, *this, v, one);
8173  return mRes;
8174  }
8175 
8221  basic_cvector& solve(const basic_scmatrix<TR,TC>& mA, const basic_cvector& vB, TR& dErr) throw(cvmexception) {
8222  return _solve_helper(mA, vB, dErr, 0);
8223  }
8224 
8225 // 6.1: transpose added
8274  return _solve_helper(mA, vB, dErr, 1);
8275  }
8276 
8277 // 6.1: conjugate added
8324  return _solve_helper(mA, vB, dErr, 2);
8325  }
8326 
8367  {
8368  static TR dErr(0.);
8369  return this->solve(mA, vB, dErr);
8370  }
8371 
8372 // 6.1: transpose added
8416  {
8417  static TR dErr(0.);
8418  return this->solve_tran(mA, vB, dErr);
8419  }
8420 
8421 // 6.1: conjugate added
8463  {
8464  static TR dErr(0.);
8465  return this->solve_conj(mA, vB, dErr);
8466  }
8467 
8468 // 6.1: MATLAB-style operator B/A returning solution of X*A=B equation
8508  return _operator_solve_helper(mA, 1);
8509  }
8510 
8511 // 6.1: similar to operator / this one returns solution of A*X=B equation
8548  return _operator_solve_helper(mA, 0);
8549  }
8550 
8615  const basic_cvector& vB, TR& dErr) throw(cvmexception)
8616  {
8617  _check_ne(CVM_SIZESMISMATCH, mA.msize(), this->size());
8618  _check_ne(CVM_SIZESMISMATCH, vB.size(), mA.msize());
8619  _check_ne(CVM_SIZESMISMATCH, mLU.msize(), mA.msize());
8620  mA._solve(vB, *this, dErr, mLU, pPivots, 0);
8621  return *this;
8622  }
8623 
8680  const basic_cvector& vB) throw(cvmexception)
8681  {
8682  static TR dErr(0.);
8683  return this->solve_lu(mA, mLU, pPivots, vB, dErr);
8684  }
8685 
8750  basic_cvector& gels(bool conjugate, const basic_cmatrix<TR,TC>& mA, const basic_cvector& vB,
8751  TC& cErr) throw(cvmexception)
8752  {
8753  _check_ne(CVM_SIZESMISMATCH, vB.size(), conjugate ? mA.nsize() : mA.msize());
8754  _check_ne(CVM_SIZESMISMATCH, this->size(), conjugate ? mA.msize() : mA.nsize());
8755  basic_cmatrix<TR,TC> mA2(mA); // this algorithm overrides A
8756  basic_cmatrix<TR,TC> mB(vB, vB.size(), 1);
8758  basic_cvector vErr(1);
8759  __gels(conjugate, mA2, mB, mX, vErr);
8760  cErr = vErr(CVM0);
8761  *this = mX(CVM0);
8762  return *this;
8763  }
8764 
8814  TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
8815  {
8816  _check_ne(CVM_SIZESMISMATCH, vB.size(), mA.msize());
8817  _check_ne(CVM_SIZESMISMATCH, this->size(), mA.nsize());
8818  basic_cmatrix<TR,TC> mA2(mA); // this algorithm overrides A
8819  basic_cmatrix<TR,TC> mB(vB, vB.size(), 1);
8821  __gelsy(mA2, mB, mX, tol, rank);
8822  *this = mX(CVM0);
8823  return *this;
8824  }
8825 
8881  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
8882  {
8883  _gels_sd(true, mA, vB, sv, rank, tol);
8884  return *this;
8885  }
8886 
8943  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
8944  {
8945  _gels_sd(false, mA, vB, sv, rank, tol);
8946  return *this;
8947  }
8948 
8995  {
8996  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
8997  mA._eig(*this, nullptr, true);
8998  return *this;
8999  }
9000 
9074  basic_cvector& eig(const basic_srmatrix<TR>& mA, basic_scmatrix<TR,TC>& mEigVect, bool bRightVect = true) throw(cvmexception)
9075  {
9076  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9077  _check_ne(CVM_SIZESMISMATCH, mEigVect.nsize(), this->size());
9078  mA._eig(*this, &mEigVect, bRightVect);
9079  return *this;
9080  }
9081 
9121  {
9122  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9123  mA._eig(*this, nullptr, true);
9124  return *this;
9125  }
9126 
9192  basic_cvector& eig(const basic_scmatrix<TR,TC>& mA, basic_scmatrix<TR,TC>& mEigVect, bool bRightVect = true) throw(cvmexception)
9193  {
9194  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9195  mA._eig(*this, &mEigVect, bRightVect);
9196  return *this;
9197  }
9198 
9245  {
9246  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9247  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), this->size());
9248  _check_ne(CVM_SIZESMISMATCH, vBeta.size(), this->size());
9249  basic_srmatrix<TR> ma(mA); // overriden below. also, we need to care about band ones
9250  basic_srmatrix<TR> mb(mB);
9251  __ggev<basic_srmatrix<TR>, basic_scmatrix<TR,TC>, basic_rvector<TR>, basic_cvector>(ma, mb, *this, vBeta, nullptr, nullptr);
9252  return *this;
9253  }
9254 
9329  basic_scmatrix<TR,TC>& mEigVectLeft, basic_scmatrix<TR,TC>& mEigVectRight) throw(cvmexception)
9330  {
9331  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9332  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), this->size());
9333  _check_ne(CVM_SIZESMISMATCH, vBeta.size(), this->size());
9334  _check_ne(CVM_SIZESMISMATCH, mEigVectLeft.nsize(), this->size());
9335  _check_ne(CVM_SIZESMISMATCH, mEigVectRight.nsize(), this->size());
9336  basic_srmatrix<TR> ma(mA); // overriden below. also, we need to care about band ones
9337  basic_srmatrix<TR> mb(mB);
9338  __ggev(ma, mb, *this, vBeta, &mEigVectLeft, &mEigVectRight);
9339  return *this;
9340  }
9341 
9419  basic_scmatrix<TR,TC>& mEigVect, bool bRightVect = true) throw(cvmexception)
9420  {
9421  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9422  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), this->size());
9423  _check_ne(CVM_SIZESMISMATCH, vBeta.size(), this->size());
9424  _check_ne(CVM_SIZESMISMATCH, mEigVect.nsize(), this->size());
9425  basic_srmatrix<TR> ma(mA); // overriden below. also, we need to care about band ones
9426  basic_srmatrix<TR> mb(mB);
9427  __ggev(ma, mb, *this, vBeta, bRightVect ? nullptr : &mEigVect, bRightVect ? &mEigVect : nullptr);
9428  return *this;
9429  }
9430 
9480  {
9481  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9482  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), this->size());
9483  _check_ne(CVM_SIZESMISMATCH, vBeta.size(), this->size());
9484  basic_scmatrix<TR,TC> ma(mA); // overriden below. also, we need to care about band ones
9485  basic_scmatrix<TR,TC> mb(mB);
9486  __ggev<basic_scmatrix<TR,TC>, basic_scmatrix<TR,TC>, basic_cvector, basic_cvector>(ma, mb, *this, vBeta, nullptr, nullptr);
9487  return *this;
9488  }
9489 
9567  basic_scmatrix<TR,TC>& mEigVectLeft, basic_scmatrix<TR,TC>& mEigVectRight) throw(cvmexception)
9568  {
9569  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9570  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), this->size());
9571  _check_ne(CVM_SIZESMISMATCH, vBeta.size(), this->size());
9572  _check_ne(CVM_SIZESMISMATCH, mEigVectLeft.nsize(), this->size());
9573  _check_ne(CVM_SIZESMISMATCH, mEigVectRight.nsize(), this->size());
9574  basic_scmatrix<TR,TC> ma(mA); // overriden below. also, we need to care about band ones
9575  basic_scmatrix<TR,TC> mb(mB);
9576  __ggev(ma, mb, *this, vBeta, &mEigVectLeft, &mEigVectRight);
9577  return *this;
9578  }
9579 
9660  basic_scmatrix<TR,TC>& mEigVect, bool bRightVect = true) throw(cvmexception)
9661  {
9662  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9663  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), this->size());
9664  _check_ne(CVM_SIZESMISMATCH, vBeta.size(), this->size());
9665  _check_ne(CVM_SIZESMISMATCH, mEigVect.nsize(), this->size());
9666  basic_scmatrix<TR,TC> ma(mA); // overriden below. also, we need to care about band ones
9667  basic_scmatrix<TR,TC> mb(mB);
9668  __ggev(ma, mb, *this, vBeta, bRightVect ? nullptr : &mEigVect, bRightVect ? &mEigVect : nullptr);
9669  return *this;
9670  }
9671 
9725  basic_cvector& gemv(bool bLeft, const basic_cmatrix<TR,TC>& m, TC dAlpha, const basic_cvector& v, TC dBeta) throw(cvmexception)
9726  {
9727  _check_ne(CVM_SIZESMISMATCH, v.size(), bLeft ? m.msize() : m.nsize());
9728  _check_ne(CVM_SIZESMISMATCH, this->size(), bLeft ? m.nsize() : m.msize());
9729  m._gemv(bLeft, dAlpha, v, dBeta, *this);
9730  return *this;
9731  }
9732 
9786  basic_cvector& gbmv(bool bLeft, const basic_scbmatrix<TR,TC>& m, TC dAlpha, const basic_cvector& v, TC dBeta) throw(cvmexception)
9787  {
9788  _check_ne(CVM_SIZESMISMATCH, v.size(), bLeft ? m.msize() : m.nsize());
9789  _check_ne(CVM_SIZESMISMATCH, this->size(), bLeft ? m.nsize() : m.msize());
9790  m._gbmv(bLeft, dAlpha, v, dBeta, *this);
9791  return *this;
9792  }
9793 
9817  basic_cvector& randomize_real(TR dFrom, TR dTo)
9818  {
9819  __randomize_real<TC, TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
9820  return *this;
9821  }
9822 
9846  basic_cvector& randomize_imag(TR dFrom, TR dTo)
9847  {
9848  __randomize_imag<TC, TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
9849  return *this;
9850  }
9851 
9852 protected:
9854  void _div(TC d) throw(cvmexception)
9855  {
9856  if (_abs(d) <= basic_cvmMachMin<TR>()) {
9858  }
9859  static const TC one(1., 0.);
9860  this->_scalc(one / d);
9861  }
9862 
9863  void _scalc(TC d)
9864  {
9865  __scal<TC, TC>(this->get(), this->size(), this->incr(), d);
9866  }
9867 
9868  void _set_real_number(TR d)
9869  {
9870  _set_real<TR,TC>(this->get(), this->size(), this->incr(), d);
9871  }
9872 
9873  void _set_imag_number(TR d)
9874  {
9875  _set_imag<TR,TC>(this->get(), this->size(), this->incr(), d);
9876  }
9877 
9878 private:
9879  basic_cvector& _solve_helper(const basic_scmatrix<TR,TC>& mA, const basic_cvector& vB,
9880  TR& dErr, int transp_mode) throw(cvmexception)
9881  {
9882  _check_ne(CVM_SIZESMISMATCH, mA.msize(), this->size());
9883  _check_ne(CVM_SIZESMISMATCH, mA.msize(), vB.size());
9884  mA._solve(vB, *this, dErr, nullptr, nullptr, transp_mode);
9885  return *this;
9886  }
9887 
9888  basic_cvector _operator_solve_helper(const basic_scmatrix<TR,TC>& mA, int transp_mode) const throw(cvmexception)
9889  {
9890  _check_ne(CVM_SIZESMISMATCH, mA.msize(), this->size());
9891  static TR dErr(0.);
9892  basic_cvector vX(this->size());
9893  mA._solve(*this, vX, dErr, nullptr, nullptr, transp_mode);
9894  return vX;
9895  }
9896 
9897  // helper for svd and divide&conquer methods
9898  void _gels_sd(bool svd, const basic_cmatrix<TR,TC>& mA, const basic_cvector& vB,
9899  basic_rvector<TR>& sv, tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
9900  {
9901  _check_ne(CVM_SIZESMISMATCH, mA.nsize(), this->size());
9902  _check_ne(CVM_SIZESMISMATCH, mA.msize(), vB.size());
9903  _check_ne(CVM_SIZESMISMATCH, sv.size(), _cvm_min<tint>(mA.msize(), mA.nsize()));
9904  basic_cmatrix<TR,TC> mA2(mA); // this algorithm overrides A
9905  basic_cmatrix<TR,TC> mB(vB, vB.size(), 1);
9907  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
9908  if (svd) {
9909  __gelss(mA2, mB, mX, tol, sv1, rank);
9910  } else {
9911  __gelsd(mA2, mB, mX, tol, sv1, rank);
9912  }
9913  sv = sv1;
9914  *this = mX(CVM0);
9915  }
9917 };
9918 
9926 template<typename TR, typename TC>
9927 class Matrix : public basic_array<TR,TC>
9928 {
9929  typedef basic_array<TR,TC> BaseArray;
9930 
9931 protected:
9935 
9942  : mm(0),
9943  mn(0),
9944  mld(0)
9945  {
9946  }
9947 
9957  Matrix(tint nM, tint nN, tint nLD, bool bZeroMemory)
9958  : BaseArray(nLD * nN, bZeroMemory),
9959  mm(nM),
9960  mn(nN),
9961  mld(nLD)
9962  {
9963  }
9964 
9977  Matrix(TC* pd, tint nM, tint nN, tint nLD, tint nSize)
9978  : BaseArray(pd, nSize, 1),
9979  mm(nM),
9980  mn(nN),
9981  mld(nLD)
9982  {
9983  }
9984 
9998  Matrix(const TC* pd, tint nM, tint nN, tint nLD, tint nSize)
9999  : BaseArray(pd, nSize, 1),
10000  mm(nM),
10001  mn(nN),
10002  mld(nLD)
10003  {
10004  }
10005 
10014  Matrix(const BaseArray& v, bool bBeColumn)
10015  : BaseArray(v.size()),
10016  mm(bBeColumn ? v.size() : 1),
10017  mn(bBeColumn ? 1 : v.size()),
10018  mld(mm)
10019  {
10020  __copy<TC>(this->size(), v, v.incr(), this->get(), this->incr());
10021  }
10022 
10040  Matrix(Matrix&& m) noexcept
10041 #if defined(CVM_USE_DELEGATING_CONSTRUCTORS)
10042  : Matrix(m.size(), m.incr(), m.msize(), m.nsize(), m.ld())
10043 #else
10044  : BaseArray(m.size(), m.incr()),
10045  mm(m.msize()),
10046  mn(m.nsize()),
10047  mld(m.ld())
10048 #endif
10049  {
10050  _mmove(std::move(m));
10051  }
10052 
10066  Matrix& operator = (Matrix&& m) throw(cvmexception)
10067  {
10068  _check_ne(CVM_SIZESMISMATCH, m.msize(), this->msize());
10069  _check_ne(CVM_SIZESMISMATCH, m.nsize(), this->nsize());
10070  _mmove(std::move(m));
10071  return *this;
10072  }
10073 
10074 public:
10092  tint msize() const {
10093  return mm;
10094  }
10095 
10113  tint nsize() const {
10114  return mn;
10115  }
10116 
10138  tint ld() const {
10139  return mld;
10140  }
10141 
10165  tint rowofmax() const {
10166  return (this->_indofmax() - CVM0) % mm + CVM0;
10167  }
10168 
10192  tint rowofmin() const {
10193  return (this->_indofmin() - CVM0) % mm + CVM0;
10194  }
10195 
10219  tint colofmax() const {
10220  return (this->_indofmax() - CVM0) / mm + CVM0;
10221  }
10222 
10246  tint colofmin() const {
10247  return (this->_indofmin() - CVM0) / mm + CVM0;
10248  }
10249 
10250  TR norm1() const override
10251  {
10252  tint i, j, k;
10253  TR rSum, rNorm(0.);
10254 
10255  for (j = 0; j < this->nsize(); ++j) {
10256  rSum = TR(0.);
10257 
10258  k = j * this->ld();
10259  for (i = 0; i < this->msize(); ++i) {
10260  CVM_ASSERT(this->get(), (k + i + 1) * sizeof(TC))
10261  rSum += _abs(this->get()[k + i]);
10262  }
10263 
10264  if (rSum > rNorm) {
10265  rNorm = rSum;
10266  }
10267  }
10268  return rNorm;
10269  }
10270 
10271  TR norminf() const override
10272  {
10273  tint i, j;
10274  TR rSum, rNorm(0.);
10275 
10276  for (i = 0; i < this->msize(); ++i) {
10277  rSum = TR(0.);
10278 
10279  for (j = 0; j < this->nsize(); ++j) {
10280  CVM_ASSERT(this->get(), (j * this->ld() + i + 1) * sizeof(TC))
10281  rSum += _abs(this->get()[j * this->ld() + i]);
10282  }
10283 
10284  if (rSum > rNorm) {
10285  rNorm = rSum;
10286  }
10287  }
10288  return rNorm;
10289  }
10290 
10292  const tint* _pm() const {
10293  return &mm;
10294  }
10295 
10296  const tint* _pn() const {
10297  return &mn;
10298  }
10299 
10300  const tint* _pld() const {
10301  return &mld;
10302  }
10303 
10304  TC* _sub_pointer_nocheck(tint row, tint col) {
10305  return this->_pd() + ((col - CVM0) * this->ld() + row - CVM0);
10306  }
10307 
10308  TC* _sub_pointer(tint row, tint col, tint height, tint width) throw(cvmexception)
10309  {
10310  _check_lt(CVM_SIZESMISMATCH_LT, row, CVM0);
10311  _check_lt(CVM_SIZESMISMATCH_LT, col, CVM0);
10312  _check_lt(CVM_SIZESMISMATCH_LT, height, CVM0);
10313  _check_lt(CVM_SIZESMISMATCH_LT, width, CVM0);
10314  _check_gt(CVM_SIZESMISMATCH_GT, row + height, this->msize() + CVM0);
10315  _check_gt(CVM_SIZESMISMATCH_GT, col + width, this->nsize() + CVM0);
10316  return _sub_pointer_nocheck(row, col);
10317  }
10318 
10319  virtual tint _ldm() const {
10320  return this->ld();
10321  }
10322 
10323  virtual const tint* _pldm() const {
10324  return this->_pld();
10325  }
10326 
10327  virtual bool _continuous() const {
10328  return this->msize() == this->ld();
10329  }
10330 
10331  void _check_ld() const
10332  {
10333  if (!this->_continuous()) {
10334  throw cvmexception(CVM_SUBMATRIXACCESSERROR);
10335  }
10336  }
10337 
10338  void _scalr(TR d) override
10339  {
10340  if (this->_continuous()) {
10341  __scal<TR,TC>(this->get(), this->size(), this->incr(), d);
10342  } else for (tint i = 0; i < this->nsize(); ++i) {
10343  __scal<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), d);
10344  }
10345  }
10346 
10347 protected:
10348  Matrix(tint size, tint incr, tint msize, tint nsize, tint ld) noexcept
10349  : BaseArray(size, incr),
10350  mm(msize),
10351  mn(nsize),
10352  mld(ld)
10353  {
10354  }
10355 
10356  // move semantics implementation for matrices
10357  void _mmove(Matrix&& m) noexcept
10358  {
10359  // no size checks here
10360 #ifdef CVM_USE_POOL_MANAGER
10361  mpd = m.mpd;
10362  m.mpd = nullptr;
10363 #else
10364  if (m.mpf == nullptr) {
10365  if (this->mpf == nullptr && this->_continuous() && m._continuous()) {
10366  this->mp = std::move(m.mp);
10367  m.msz = m.mm = m.mn = m.mld = 0;
10368  } else {
10369  // *this has foreign array inside or not continuous; no place to move to
10370  // i.e. this is the case where we don't even touch m, just copy its content
10371  this->_massign(m);
10372  }
10373  } else {
10374  // ... and here we can't rely on foreign poiter life cycle, thus copying
10375  this->_resize2(m.msize(), m.nsize());
10376  this->_massign(m);
10377  }
10378 #endif
10379  }
10380 
10381  void _diag_helper(tint nDiag, tint& nShift, tint& nSize) const throw(cvmexception)
10382  {
10383  if (nDiag >= 0) {
10384  _check_ge(CVM_INDEX_GE, nDiag, this->nsize());
10385  nShift = nDiag * this->ld();
10386  nSize = this->nsize() > this->msize() ? (nDiag > this->nsize() - this->msize() ? this->nsize() - nDiag : this->msize()) :
10387  this->nsize() - nDiag;
10388  } else {
10389  nShift = -nDiag;
10390  _check_ge(CVM_INDEX_GE, nShift, this->msize());
10391  nSize = this->msize() > this->nsize() ? (nShift > this->msize() - this->nsize() ? this->msize() - nShift : this->nsize()) :
10392  this->msize() - nShift;
10393  }
10394  }
10395 
10396  tint _indofmax() const override
10397  {
10398  this->_check_ld();
10399  return __idamax<TC>(this->get(), this->size(), this->incr());
10400  }
10401 
10402  tint _indofmin() const override
10403  {
10404  this->_check_ld();
10405  return __idamin<TC>(this->get(), this->size(), this->incr());
10406  }
10407 
10408  void _assign(const TC* pd, tint nIncr) override
10409  {
10410  if (this->get() != pd) {
10411  if (this->_continuous()) {
10412  __copy<TC>(this->size(), pd, nIncr, this->get(), this->incr());
10413  } else for (tint i = 0; i < this->nsize(); ++i) {
10414  __copy<TC>(this->msize(), pd + this->msize() * i * nIncr, nIncr, this->get() + this->ld() * i, this->incr());
10415  }
10416  }
10417  }
10418 
10419  void _assign_shifted(TC* pDshifted, const TC* pd, tint nRows, tint nCols, tint nLD) override // reusing nSise and nIncr parameter
10420  {
10421  if (pDshifted != pd) {
10422  for (tint i = 0; i < nCols; ++i) {
10423  __copy<TC>(nRows, pd + nLD * i, 1, pDshifted + this->ld() * i, this->incr());
10424  }
10425  }
10426  }
10427 
10428  void _set(TC d) override
10429  {
10430  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
10431  tint i, j, k;
10432  for (j = 0; j < this->nsize(); ++j) {
10433  k = j * this->ld();
10434  for (i = 0; i < this->msize(); ++i) {
10435  this->get()[k + i] = d;
10436  }
10437  }
10438  }
10439 
10440  virtual void _massign(const Matrix& m)
10441  {
10442  if (this->get() != m.get()) {
10443  if (this->_continuous() && m._continuous()) {
10444  __copy<TC>(this->size(), m._pd(), m.incr(), this->get(), this->incr());
10445  } else {
10446  const TC* p = m._pd();
10447  const tint nLD = m._ldm();
10448  for (tint i = 0; i < this->nsize(); ++i) {
10449  __copy<TC>(this->msize(), p + nLD * i, m.incr(), this->get() + this->ld() * i, this->incr());
10450  }
10451  }
10452  }
10453  }
10454 
10455  virtual void _resize2(tint nNewM, tint nNewN) throw(cvmexception)
10456  {
10457  _check_lt(CVM_WRONGSIZE_LT, nNewM, TINT_ZERO);
10458  _check_lt(CVM_WRONGSIZE_LT, nNewN, TINT_ZERO);
10459  const bool is_empty = this->_is_empty();
10460  if (nNewM != this->msize() || nNewN != this->nsize() || is_empty) {
10461  if (!is_empty) {
10462  this->_check_ld();
10463  }
10464  const tint nNewSize = nNewM * nNewN;
10465  TC* pd = cvmMalloc<TC>(nNewSize);
10466  cvmZeroMemory<TC>(pd, nNewSize);
10467  const tint nMinM = _cvm_min<tint>(nNewM, this->msize());
10468  const tint nMinN = _cvm_min<tint>(nNewN, this->nsize());
10469  if (nNewSize > 0 && !is_empty) {
10470  for (tint i = 0; i < nMinN; ++i) {
10471  __copy<TC>(nMinM, this->get() + i * this->msize(), this->incr(), pd + i * nNewM, 1);
10472  }
10473  }
10474 #ifdef CVM_USE_POOL_MANAGER
10475  cvmFree<TC>(this->mpd);
10476  this->mpd = pd;
10477 #else
10478  this->mp.reset(pd, ArrayDeleter<TC>());
10479  this->mpf = nullptr;
10480 #endif
10481  this->msz = nNewSize;
10482  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
10483  this->mm = nNewM;
10484  this->mn = nNewN;
10485  this->mld = nNewM;
10486  this->mincr = 1;
10487  }
10488  }
10489 
10490  virtual tint _ld_for_replace() const {
10491  return this->mld;
10492  }
10493 
10494  virtual tint _size_for_replace() const {
10495  return this->size();
10496  }
10497 
10498  void _replace(const Matrix& m) throw(cvmexception)
10499  {
10500  // submatrix replacement is obviously not possible
10501  this->_check_ld();
10502 #ifdef CVM_USE_POOL_MANAGER
10503  cvmFree<TC>(this->mpd);
10504  this->msz = m._size_for_replace();
10505  this->mpd = cvmMalloc<TC>(this->size());
10506 #else
10507  this->msz = m._size_for_replace();
10508  this->mp.reset(cvmMalloc<TC>(this->size()), ArrayDeleter<TC>());
10509  this->mpf = nullptr;
10510 #endif
10511  this->mincr = 1;
10512  CVM_ASSERT(this->get(), (this->size() * sizeof(TC)))
10513  this->mm = m.msize();
10514  this->mn = m.nsize();
10515  this->mld = m._ld_for_replace();
10516  }
10517 
10518  void _transp_m(const Matrix& m)
10519  {
10520  tint i;
10521  if (this->msize() > this->nsize()) for (i = 0; i < this->nsize(); ++i) {
10522  __copy<TC>(m.nsize(), m.get() + i, m.ld(), this->get() + i * this->ld(), 1);
10523  }
10524  else for (i = 0; i < this->msize(); ++i) {
10525  __copy<TC>(m.msize(), m.get() + i * m.ld(), 1, this->get() + i, this->ld());
10526  }
10527  }
10528 
10529  virtual type_proxy<TC, TR> _ij_proxy_val(tint i, tint j) { // always zero based
10530  CVM_ASSERT(this->get(), (this->ld() * j + i + 1) * sizeof(TC))
10531  return type_proxy<TC, TR>(this->get()[this->ld() * j + i], false);
10532  }
10533 
10534  virtual TC _ij_val(tint i, tint j) const { // always zero based
10535  CVM_ASSERT(this->get(), (this->ld() * j + 1) * sizeof(TC))
10536  return this->get()[this->ld() * j + i];
10537  }
10538 
10539  virtual void _swap_rows(tint n1, tint n2) throw(cvmexception)
10540  {
10541  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, n1, CVM0, this->msize() + CVM0);
10542  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, n2, CVM0, this->msize() + CVM0);
10543  if (n1 != n2) {
10544  __swap<TC>(this->nsize(), this->get() + n1 - CVM0, this->ld(), this->get() + n2 - CVM0, this->ld());
10545  }
10546  }
10547 
10548  virtual void _swap_cols(tint n1, tint n2) throw(cvmexception)
10549  {
10550  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, n1, CVM0, this->nsize() + CVM0);
10551  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, n2, CVM0, this->nsize() + CVM0);
10552  if (n1 != n2) {
10553  __swap<TC>(this->msize(), this->get() + (n1 - CVM0) * this->ld(), 1, this->get() + (n2 - CVM0) * this->ld(), 1);
10554  }
10555  }
10556 
10557  virtual const TC* _pp(const Matrix& m) const {
10558  return m._pd();
10559  }
10560 
10561  // matrix cleaning (we ALWAYS have mincr = 1 for matrices)
10562  virtual void _vanish()
10563  {
10564  CVM_ASSERT(this->get(), this->size() * sizeof(TC))
10565  if (this->_continuous()) {
10566  memset(this->get(), 0, this->size() * sizeof(TC));
10567  } else for (tint i = 0; i < this->nsize(); ++i) {
10568  memset(this->get() + this->ld() * i, 0, this->msize() * sizeof(TC));
10569  }
10570  }
10571 
10572  void _msum(const Matrix& m1, const Matrix& m2)
10573  {
10574  if (this->_continuous() && m1._continuous() && m2._continuous()) {
10575  _sum<TR,TC>(this->get(), this->size(), this->incr(), _pp(m1), m1.incr(), _pp(m2), m2.incr());
10576  } else for (tint i = 0; i < this->nsize(); ++i) {
10577  _sum<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), _pp(m1) + m1._ldm() * i, m1.incr(), _pp(m2) + m2._ldm() * i, m2.incr());
10578  }
10579  }
10580 
10581  void _mdiff(const Matrix& m1, const Matrix& m2)
10582  {
10583  if (this->_continuous() && m1._continuous() && m2._continuous()) {
10584  _diff<TR,TC>(this->get(), this->size(), this->incr(), _pp(m1), m1.incr(), _pp(m2), m2.incr());
10585  } else for (tint i = 0; i < this->nsize(); ++i) {
10586  _diff<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), _pp(m1) + m1._ldm() * i, m1.incr(), _pp(m2) + m2._ldm() * i, m2.incr());
10587  }
10588  }
10589 
10590  void _mincr(const Matrix& m)
10591  {
10592  if (this->_continuous() && m._continuous()) {
10593  _incr<TR,TC>(this->get(), this->size(), this->incr(), _pp(m), m.incr());
10594  } else for (tint i = 0; i < this->nsize(); ++i) {
10595  _incr<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), _pp(m) + m._ldm() * i, m.incr());
10596  }
10597  }
10598 
10599  void _mdecr(const Matrix& m)
10600  {
10601  if (this->_continuous() && m._continuous()) {
10602  _decr<TR,TC>(this->get(), this->size(), this->incr(), _pp(m), m.incr());
10603  } else for (tint i = 0; i < this->nsize(); ++i) {
10604  _decr<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), _pp(m) + m._ldm() * i, m.incr());
10605  }
10606  }
10608 
10609  public:
10610  friend std::ostream& operator << <> (std::ostream& os, const Matrix<TR,TC>& mOut);
10611  friend std::istream& operator >> <> (std::istream& is, Matrix<TR,TC>& mIn);
10612 };
10613 
10614 
10622 template<typename TR, typename TC>
10624 {
10625  typedef Matrix<TR,TC> BaseMatrix;
10626 
10627 protected:
10630  {
10631  }
10632 
10633  virtual ~SqMatrix()
10634  {
10635  }
10636 
10638  virtual tint _size() const = 0;
10639  virtual tint _msize() const = 0;
10640  virtual tint _nsize() const = 0;
10641  virtual tint _ld() const = 0;
10642 
10643  // it's the same as get, but let's keep get not virtual for performance sake
10644  virtual const TC* _pv() const = 0;
10645  virtual TC* _pv() = 0;
10646 
10647  // it differs from Matrix::_transp_m because in this case we can do it in-place.
10648  void _sq_transp()
10649  {
10650  const tint mm = this->_msize();
10651  const tint mld = this->_ld();
10652  TC* pd = this->_pv();
10653  if (mm > 1) {
10654  const tint nM1 = mld + 1, nM1m = mld - 1, nM2m = mm - 1;
10655  tint i = 1, j = 1, m;
10656  for (;;) {
10657  m = mm - i;
10658  __swap<TC>(m, pd + j, 1, pd + j + nM1m, mld);
10659  if (i >= nM2m) {
10660  break;
10661  }
10662  ++i;
10663  j += nM1;
10664  }
10665  }
10666  }
10667 
10668  // plus identity
10669  void _sq_plus_plus()
10670  {
10671  TC* pd = this->_pv();
10672  static const TC one(1.);
10673  const tint nSize = this->_size();
10674  const tint nNext = this->_msize() + 1;
10675  CVM_ASSERT(pd, nSize * sizeof(TC))
10676  for (tint i = 0; i < nSize; i += nNext) {
10677  pd[i] += one;
10678  }
10679  }
10680 
10681  // minus identity
10682  void _sq_minus_minus()
10683  {
10684  TC* pd = this->_pv();
10685  static const TC one(1.);
10686  const tint nSize = this->_size();
10687  const tint nNext = this->_msize() + 1;
10688  CVM_ASSERT(pd, nSize * sizeof(TC))
10689  for (tint i = 0; i < nSize; i += nNext) {
10690  pd[i] -= one;
10691  }
10692  }
10693 
10694 public:
10695  void _clean_low_triangle()
10696  {
10697  const tint mm = this->_msize();
10698  const tint mld = this->_ld();
10699  TC* pd = this->_pv();
10700  tint n = 1;
10701  static const TR zero(0.);
10702  for (tint i = 1; i < mm; ++i) {
10703  __scal<TR,TC>(pd + n, mm - i, 1, zero); // column by column
10704  n += mld + 1;
10705  }
10706  }
10708 };
10709 
10716 template<typename TR>
10717 class basic_rmatrix : public Matrix<TR,TR>
10718 {
10719  typedef std::complex<TR> TC;
10720  typedef basic_array<TR,TR> BaseArray;
10721  typedef Matrix<TR,TR> BaseMatrix;
10722  typedef basic_rvector<TR> RVector;
10723 
10724  friend class basic_rvector<TR>; // _multiply
10725 
10726 public:
10750  {
10751  }
10752 
10780  : BaseMatrix(nM, nN, nM, true)
10781  {
10782  }
10783 
10816  basic_rmatrix(TR* pd, tint nM, tint nN)
10817  : BaseMatrix(pd, nM, nN, nM, nM * nN)
10818  {
10819  }
10820 
10855  basic_rmatrix(const TR* pd, tint nM, tint nN)
10856  : BaseMatrix(pd, nM, nN, nM, nM * nN)
10857  {
10858  }
10859 
10888  : BaseMatrix(m.msize(), m.nsize(), m.msize(), false)
10889  {
10890  this->_massign(m);
10891  }
10892 
10911  : BaseMatrix(std::move(m))
10912  {
10913  }
10914 
10949  explicit basic_rmatrix(const RVector& v, bool bBeColumn = true)
10950  : BaseMatrix(v, bBeColumn)
10951  {
10952  }
10953 
10984  basic_rmatrix(basic_rmatrix& m, tint nRow, tint nCol, tint nHeight, tint nWidth)
10985  : BaseMatrix(m._sub_pointer(nRow, nCol, nHeight, nWidth), nHeight, nWidth, m.ld(), nHeight * nWidth)
10986  {
10987  m._check_submatrix();
10988  }
10989 
11028  type_proxy<TR,TR> operator () (tint nRow, tint nCol) throw(cvmexception)
11029  {
11030  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
11031  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
11032  return this->_ij_proxy_val(nRow - CVM0, nCol - CVM0);
11033  }
11034 
11065  TR operator () (tint nRow, tint nCol) const throw(cvmexception)
11066  {
11067  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
11068  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
11069  return this->_ij_val(nRow - CVM0, nCol - CVM0);
11070  }
11071 
11107  RVector operator () (tint nCol) throw(cvmexception)
11108  {
11109  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
11110  return this->_col(nCol - CVM0);
11111  }
11112 
11149  RVector operator [] (tint nRow) throw(cvmexception)
11150  {
11151  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
11152  return this->_row(nRow - CVM0);
11153  }
11154 
11181  const RVector operator () (tint nCol) const throw(cvmexception)
11182  {
11183  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
11184  return this->_col(nCol - CVM0);
11185  }
11186 
11213  const RVector operator [] (tint nRow) const throw(cvmexception)
11214  {
11215  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
11216  return this->_row(nRow - CVM0);
11217  }
11218 
11252  RVector diag(tint nDiag) throw(cvmexception) {
11253  return this->_diag(nDiag);
11254  }
11255 
11288  const RVector diag(tint nDiag) const throw(cvmexception) {
11289  return this->_diag(nDiag);
11290  }
11291 
11325  basic_rmatrix& operator = (const basic_rmatrix& m) throw(cvmexception)
11326  {
11327  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
11328  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
11329  this->_massign(m);
11330  return *this;
11331  }
11332 
11346  basic_rmatrix& operator = (basic_rmatrix&& m) throw(cvmexception)
11347  {
11348  // size check is in BaseMatrix
11349  BaseMatrix::operator = (std::move(m));
11350  return *this;
11351  }
11352 
11382  basic_rmatrix& assign(const RVector& v) throw(cvmexception)
11383  {
11384  _check_gt(CVM_SIZESMISMATCH_GT, this->size(), v.size());
11385  this->_assign(v, v.incr());
11386  return *this;
11387  }
11388 
11416  basic_rmatrix& assign(const TR* pd)
11417  {
11418  this->_assign(pd, 1);
11419  return *this;
11420  }
11421 
11452  basic_rmatrix& assign(tint nRow, tint nCol, const basic_rmatrix& m) throw(cvmexception)
11453  {
11454  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
11455  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
11456  _check_gt(CVM_SIZESMISMATCH_GT, m.msize() + nRow - CVM0, this->msize());
11457  _check_gt(CVM_SIZESMISMATCH_GT, m.nsize() + nCol - CVM0, this->nsize());
11458  this->_assign_shifted(this->_sub_pointer_nocheck(nRow, nCol), m._pd(), m.msize(), m.nsize(), m.ld());
11459  return *this;
11460  }
11461 
11484  basic_rmatrix& set(TR d)
11485  {
11486  this->_set(d);
11487  return *this;
11488  }
11489 
11533  basic_rmatrix& resize(tint nNewM, tint nNewN) throw(cvmexception)
11534  {
11535  this->_resize2(nNewM, nNewN);
11536  return *this;
11537  }
11538 
11565  bool operator == (const basic_rmatrix& m) const {
11566  return this->msize() == m.msize() && this->nsize() == m.nsize() && this->_mequals(m);
11567  }
11568 
11595  bool operator != (const basic_rmatrix& m) const {
11596  return !operator == (m);
11597  }
11598 
11639  basic_rmatrix& operator << (const basic_rmatrix& m) throw(cvmexception)
11640  {
11641  this->_replace(m);
11642  this->_massign(m);
11643  return *this;
11644  }
11645 
11682  basic_rmatrix operator + (const basic_rmatrix& m) const throw(cvmexception)
11683  {
11684  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
11685  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
11686  basic_rmatrix mSum(*this);
11687  mSum._mincr(m);
11688  return mSum;
11689  }
11690 
11726  basic_rmatrix operator - (const basic_rmatrix& m) const throw(cvmexception)
11727  {
11728  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
11729  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
11730  basic_rmatrix mDiff(*this);
11731  mDiff._mdecr(m);
11732  return mDiff;
11733  }
11734 
11771  basic_rmatrix& sum(const basic_rmatrix& m1, const basic_rmatrix& m2) throw(cvmexception)
11772  {
11773  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
11774  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m1.nsize());
11775  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
11776  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
11777  this->_msum(m1, m2);
11778  return *this;
11779  }
11780 
11817  basic_rmatrix& diff(const basic_rmatrix& m1, const basic_rmatrix& m2) throw(cvmexception)
11818  {
11819  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
11820  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m1.nsize());
11821  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
11822  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
11823  this->_mdiff(m1, m2);
11824  return *this;
11825  }
11826 
11866  basic_rmatrix& operator += (const basic_rmatrix& m) throw(cvmexception)
11867  {
11868  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
11869  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
11870  this->_mincr(m);
11871  return *this;
11872  }
11873 
11913  basic_rmatrix& operator -= (const basic_rmatrix& m) throw(cvmexception)
11914  {
11915  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
11916  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
11917  this->_mdecr(m);
11918  return *this;
11919  }
11920 
11942  static const TR mone(-1.);
11943  basic_rmatrix mRes(*this);
11944  mRes._scalr(mone);
11945  return mRes;
11946  }
11947 
11970  basic_rmatrix operator * (TR dMult) const {
11971  basic_rmatrix mRes(*this);
11972  mRes._scalr(dMult);
11973  return mRes;
11974  }
11975 
12008  basic_rmatrix operator / (TR dDiv) const throw(cvmexception)
12009  {
12010  basic_rmatrix mRes(*this);
12011  mRes._div(dDiv);
12012  return mRes;
12013  }
12014 
12038  {
12039  this->_scalr(dMult);
12040  return *this;
12041  }
12042 
12075  basic_rmatrix& operator /= (TR dDiv) throw(cvmexception)
12076  {
12077  this->_div(dDiv);
12078  return *this;
12079  }
12080 
12107  {
12108  this->_normalize();
12109  return *this;
12110  }
12111 
12139  basic_rmatrix operator ~() const throw(cvmexception)
12140  {
12141  basic_rmatrix mRes(this->nsize(), this->msize());
12142  mRes._transp_m(*this);
12143  return mRes;
12144  }
12145 
12178  basic_rmatrix& transpose(const basic_rmatrix& m) throw(cvmexception)
12179  {
12180  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.nsize());
12181  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
12182  if (this->get() == m.get()) {
12183  basic_rmatrix mTmp(m);
12184  this->_transp_m(mTmp);
12185  } else {
12186  this->_transp_m(m);
12187  }
12188  return *this;
12189  }
12190 
12220  basic_rmatrix& transpose() throw(cvmexception)
12221  {
12222  basic_rmatrix mTmp(*this);
12223  this->_resize2(this->nsize(), this->msize());
12224  this->_transp_m(mTmp);
12225  return *this;
12226  }
12227 
12257  RVector operator * (const RVector& v) const throw(cvmexception)
12258  {
12259  _check_ne(CVM_SIZESMISMATCH, this->nsize(), v.size());
12260  RVector vRes(this->msize());
12261  this->_multiply(vRes, v, false);
12262  return vRes;
12263  }
12264 
12294  basic_rmatrix operator * (const basic_rmatrix& m) const throw(cvmexception)
12295  {
12296  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
12297  basic_rmatrix mRes(this->msize(), m.nsize());
12298  mRes.mult(*this, m);
12299  return mRes;
12300  }
12301 
12336  basic_rmatrix& mult(const basic_rmatrix& m1, const basic_rmatrix& m2) throw(cvmexception)
12337  {
12338  this->_mult(m1, m2);
12339  return *this;
12340  }
12341 
12394  basic_rmatrix& rank1update(const RVector& vCol, const RVector& vRow) throw(cvmexception)
12395  {
12396  static const TR one(1.);
12397  this->_check_rank1update();
12398  _check_ne(CVM_SIZESMISMATCH, this->msize(), vCol.size());
12399  _check_ne(CVM_SIZESMISMATCH, this->nsize(), vRow.size());
12400  this->_vanish();
12401  __ger<TR,basic_rmatrix, RVector>(*this, vCol, vRow, one);
12402  return *this;
12403  }
12404 
12438  basic_rmatrix& swap_rows(tint n1, tint n2) throw(cvmexception)
12439  {
12440  this->_swap_rows(n1, n2);
12441  return *this;
12442  }
12443 
12475  basic_rmatrix& swap_cols(tint n1, tint n2) throw(cvmexception)
12476  {
12477  this->_swap_cols(n1, n2);
12478  return *this;
12479  }
12480 
12522  basic_rmatrix& solve(const basic_srmatrix<TR>& mA, const basic_rmatrix& mB, TR& dErr) throw(cvmexception) {
12523  return _solve_helper(mA, mB, dErr, 0);
12524  }
12525 
12526 // 6.1: transpose added
12574  basic_rmatrix& solve_tran(const basic_srmatrix<TR>& mA, const basic_rmatrix& mB, TR& dErr) throw(cvmexception) {
12575  return _solve_helper(mA, mB, dErr, 1);
12576  }
12577 
12615  basic_rmatrix& solve(const basic_srmatrix<TR>& mA, const basic_rmatrix& mB) throw(cvmexception)
12616  {
12617  static TR dErr(0.);
12618  return this->solve(mA, mB, dErr);
12619  }
12620 
12621 // 6.1: transpose added
12666  basic_rmatrix& solve_tran(const basic_srmatrix<TR>& mA, const basic_rmatrix& mB) throw(cvmexception)
12667  {
12668  static TR dErr(0.);
12669  return this->solve_tran(mA, mB, dErr);
12670  }
12671 
12741  basic_rmatrix& solve_lu(const basic_srmatrix<TR>& mA, const basic_srmatrix<TR>& mLU, const tint* pPivots,
12742  const basic_rmatrix& mB, TR& dErr) throw(cvmexception)
12743  {
12744  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.msize());
12745  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
12746  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
12747  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mLU.msize());
12748  mA._solve(mB, *this, dErr, mLU, pPivots, 0);
12749  return *this;
12750  }
12751 
12818  basic_rmatrix& solve_lu(const basic_srmatrix<TR>& mA, const basic_srmatrix<TR>& mLU, const tint* pPivots,
12819  const basic_rmatrix& mB) throw(cvmexception)
12820  {
12821  static TR dErr(0.);
12822  return this->solve_lu(mA, mLU, pPivots, mB, dErr);
12823  }
12824 
12867  RVector svd() const throw(cvmexception)
12868  {
12869  RVector vRes(_cvm_min<tint>(this->msize(), this->nsize()));
12870  this->_svd(vRes, nullptr, nullptr);
12871  return vRes;
12872  }
12873 
12949  RVector svd(basic_srmatrix<TR>& mU, basic_srmatrix<TR>& mVH) const throw(cvmexception)
12950  {
12951  RVector vRes(_cvm_min<tint>(this->msize(), this->nsize()));
12952  this->_svd(vRes, &mU, &mVH);
12953  return vRes;
12954  }
12955 
13009  basic_rmatrix pinv(TR threshold = basic_cvmMachSp<TR>()) const throw(cvmexception)
13010  {
13011  basic_rmatrix mAx(this->nsize(), this->msize());
13012  this->_pinv(mAx, threshold);
13013  return mAx;
13014  }
13015 
13073  basic_rmatrix& pinv(const basic_rmatrix& mA, TR threshold = basic_cvmMachSp<TR>()) throw(cvmexception)
13074  {
13075  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mA.msize());
13076  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.nsize());
13077  mA._pinv(*this, threshold);
13078  return *this;
13079  }
13080 
13146  basic_rmatrix gels(bool transpose, const basic_rmatrix& mB, basic_rvector<TR>& vErr) const throw(cvmexception)
13147  {
13148  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), vErr.size());
13149  _check_ne(CVM_SIZESMISMATCH, mB.msize(), transpose ? this->nsize() : this->msize());
13150  basic_rmatrix mA(*this); // this algorithm overrides A
13151  basic_rmatrix mX;
13152  __gels(transpose, mA, mB, mX, vErr);
13153  return mX;
13154  }
13155 
13222  basic_rmatrix& gels(bool transpose, const basic_rmatrix& mA, const basic_rmatrix& mB,
13223  basic_rvector<TR>& vErr) throw(cvmexception)
13224  {
13225  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
13226  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), vErr.size());
13227  _check_ne(CVM_SIZESMISMATCH, this->msize(), transpose ? mA.msize() : mA.nsize());
13228  _check_ne(CVM_SIZESMISMATCH, mB.msize(), transpose ? mA.nsize() : mA.msize());
13229  basic_rmatrix mA2(mA); // this algorithm overrides A
13230  __gels(transpose, mA2, mB, *this, vErr);
13231  return *this;
13232  }
13233 
13295  basic_rvector<TR> gels(bool transpose, const basic_rvector<TR>& vB, TR& dErr) const throw(cvmexception)
13296  {
13297  _check_ne(CVM_SIZESMISMATCH, vB.size(), transpose ? this->nsize() : this->msize());
13298  basic_rmatrix mA(*this); // this algorithm overrides A
13299  basic_rmatrix mB(vB, vB.size(), 1);
13300  basic_rmatrix mX;
13301  basic_rvector<TR> vErr(1);
13302  __gels(transpose, mA, mB, mX, vErr);
13303  dErr = vErr(CVM0);
13304  const TR* pResult = mX;
13305  return basic_rvector<TR>(pResult, mX.msize());
13306  }
13307 
13361  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13362  {
13363  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
13364  basic_rmatrix mA(*this); // this algorithm overrides A
13365  basic_rmatrix mX;
13366  __gelsy(mA, mB, mX, tol, rank);
13367  return mX;
13368  }
13369 
13425  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
13426  {
13427  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.nsize());
13428  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
13429  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
13430  basic_rmatrix mA2(mA); // this algorithm overrides A
13431  __gelsy(mA2, mB, *this, tol, rank);
13432  return *this;
13433  }
13434 
13488  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13489  {
13490  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
13491  basic_rmatrix mA(*this); // this algorithm overrides A
13492  basic_rmatrix mB(vB, vB.size(), 1);
13493  basic_rmatrix mX;
13494  __gelsy(mA, mB, mX, tol, rank);
13495  const TR* pResult = mX;
13496  return basic_rvector<TR>(pResult, mX.msize());
13497  }
13498 
13558  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13559  {
13560  return _gels_sd(true, mB, sv, rank, tol);
13561  }
13562 
13624  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
13625  {
13626  _gels_sd(true, mA, mB, sv, rank, tol);
13627  return *this;
13628  }
13629 
13689  tint& rank, TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13690  {
13691  return _gels_sd(true, vB, sv, rank, tol);
13692  }
13693 
13753  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13754  {
13755  return _gels_sd(false, mB, sv, rank, tol);
13756  }
13757 
13819  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
13820  {
13821  _gels_sd(false, mA, mB, sv, rank, tol);
13822  return *this;
13823  }
13824 
13885  tint& rank, TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13886  {
13887  return _gels_sd(false, vB, sv, rank, tol);
13888  }
13889 
13927  tint rank(TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
13928  {
13929  tint nRank = 0;
13930  RVector vS(_cvm_min<tint>(this->msize(), this->nsize()));
13931  this->_svd(vS, nullptr, nullptr);
13932  vS.normalize();
13933  for (; nRank < vS.size(); ++nRank) {
13934  if (vS[nRank * this->incr() + CVM0] < tol) break;
13935  }
13936  return nRank;
13937  }
13938 
13939 // QR factorization
13940 // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and R is (n x n)
13989  void qr(basic_rmatrix<TR>& mQ, basic_srmatrix<TR>& mR) const throw(cvmexception) {
13990  this->_qr_rs(mQ, mR);
13991  }
13992 
13993 // Case 2: full mode, A is (m x n) and Q is (m x m) and R is (m x n)
14041  void qr(basic_srmatrix<TR>& mQ, basic_rmatrix<TR>& mR) const throw(cvmexception) {
14042  this->_qr_sr(mQ, mR);
14043  }
14044 
14045 // LQ factorization
14046 // Case 1: "economy" mode, A is (m x n) and L is (m x m) and Q is (m x n)
14093  void lq(basic_srmatrix<TR>& mL, basic_rmatrix<TR>& mQ) const throw(cvmexception) {
14094  this->_lq_sr(mL, mQ);
14095  }
14096 
14097 // Case 2: full mode, A is (m x n) and L is (m x n) and Q is (n x n)
14144  void lq(basic_rmatrix<TR>& mL, basic_srmatrix<TR>& mQ) const throw(cvmexception) {
14145  this->_lq_rs(mL, mQ);
14146  }
14147 
14148 // RQ factorization
14149 // Case 1: "economy" mode, A is (m x n) and R is (m x m) and Q is (m x n)
14191  void rq(basic_srmatrix<TR>& mR, basic_rmatrix<TR>& mQ) const throw(cvmexception) {
14192  this->_rq_sr(mR, mQ);
14193  }
14194 
14195 // Case 2: full mode, A is (m x n) and R is (m x n) and Q is (n x n)
14237  void rq(basic_rmatrix<TR>& mR, basic_srmatrix<TR>& mQ) const throw(cvmexception) {
14238  this->_rq_rs(mR, mQ);
14239  }
14240 
14241 // QL factorization
14242 // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and L is (n x n)
14283  void ql(basic_rmatrix<TR>& mQ, basic_srmatrix<TR>& mL) const throw(cvmexception) {
14284  this->_ql_rs(mQ, mL);
14285  }
14286 
14287 // Case 2: full mode, A is (m x n) and Q is (m x m) and L is (m x n)
14328  void ql(basic_srmatrix<TR>& mQ, basic_rmatrix<TR>& mL) const throw(cvmexception) {
14329  this->_ql_sr(mQ, mL);
14330  }
14331 
14332 // this += alpha * v_col * v_row (rank-1 update)
14392  basic_rmatrix& ger(TR alpha, const RVector& vCol, const RVector& vRow) throw(cvmexception)
14393  {
14394  this->_check_ger();
14395  _check_ne(CVM_SIZESMISMATCH, this->msize(), vCol.size());
14396  _check_ne(CVM_SIZESMISMATCH, this->nsize(), vRow.size());
14397  __ger<TR,basic_rmatrix, RVector>(*this, vCol, vRow, alpha);
14398  return *this;
14399  }
14400 
14401 // this = alpha * m1 * m2 + beta * this
14458  basic_rmatrix& gemm(const basic_rmatrix& m1, bool bTrans1, const basic_rmatrix& m2,
14459  bool bTrans2, TR dAlpha, TR dBeta) throw(cvmexception)
14460  {
14461  this->_check_gemm();
14462  _check_ne(CVM_SIZESMISMATCH, this->msize(), bTrans1 ? m1.nsize() : m1.msize());
14463  _check_ne(CVM_SIZESMISMATCH, this->nsize(), bTrans2 ? m2.msize() : m2.nsize());
14464  _check_ne(CVM_SIZESMISMATCH, bTrans1 ? m1.msize() : m1.nsize(), bTrans2 ? m2.nsize() : m2.msize());
14465  this->_gemm(bTrans1, m1, bTrans2, m2, dAlpha, dBeta);
14466  return *this;
14467  }
14468 
14469 // this = alpha*a*b + beta*this or this = alpha*b*a + beta*this where a is symmetric
14541  basic_rmatrix& symm(bool bLeft, const basic_srsmatrix<TR>& ms, const basic_rmatrix& m,
14542  TR dAlpha, TR dBeta) throw(cvmexception)
14543  {
14544  this->_check_symm();
14545  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
14546  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
14547  _check_ne(CVM_SIZESMISMATCH, bLeft ? this->msize() : this->nsize(), ms.msize());
14548  this->_symm(bLeft, ms, m, dAlpha, dBeta);
14549  return *this;
14550  }
14551 
14580  basic_rmatrix& vanish()
14581  {
14582  this->_vanish();
14583  return *this;
14584  }
14585 
14611  basic_rmatrix& randomize(TR dFrom, TR dTo)
14612  {
14613  this->_randomize(dFrom, dTo);
14614  return *this;
14615  }
14616 
14617  // 2-norm (maximum singular value)
14618  TR norm2() const override
14619  {
14620  RVector vS(_cvm_min<tint>(this->msize(), this->nsize()));
14621  this->_svd(vS, nullptr, nullptr);
14622  return vS[CVM0];
14623  }
14624 
14626  // ?gemm routines perform a matrix-matrix operation with general matrices. The operation is defined as
14627  // c := alpha*op(a)*op(b) + beta*c,
14628  // where: op(x) is one of op(x) = x or op(x) = x' or op(x) = conjg(x'),
14629  void _gemm(bool bTrans1, const basic_rmatrix& m1, bool bTrans2, const basic_rmatrix& m2, TR dAlpha, TR dBeta) throw(cvmexception) { // this = m1 * m2
14630  basic_rmatrix mTmp1, mTmp2;
14631  const TR* pD1 = m1.get();
14632  const TR* pD2 = m2.get();
14633  if (this->get() == pD1) mTmp1 << m1;
14634  if (this->get() == pD2) mTmp2 << m2;
14635  __gemm<TR,basic_rmatrix>(this->get() == pD1 ? mTmp1 : m1, bTrans1, this->get() == pD2 ? mTmp2 : m2,
14636  bTrans2, dAlpha, *this, dBeta);
14637  }
14638 
14639  // this = alpha*a*b + beta*this or this = alpha*b*a + beta*this where a is symmetric
14640  void _symm(bool bLeft, const basic_srsmatrix<TR>& ms, const basic_rmatrix& m, TR dAlpha, TR dBeta) throw(cvmexception)
14641  {
14642  basic_rmatrix mTmp;
14643  basic_srsmatrix<TR> msTmp;
14644  const TR* pD1 = ms.get();
14645  const TR* pD2 = m._pd();
14646  if (this->get() == pD1) msTmp << ms;
14647  if (this->get() == pD2) mTmp << m;
14648  __symm<TR,basic_srsmatrix<TR>, basic_rmatrix>(bLeft, this->get() == pD1 ? msTmp : ms,
14649  this->get() == pD2 ? mTmp : m, dAlpha, *this, dBeta);
14650  }
14651 
14652  // singular values in decreasing order
14653  virtual void _svd(RVector& vRes, basic_srmatrix<TR>* pmU, basic_srmatrix<TR>* pmVH) const throw(cvmexception)
14654  {
14655  if (pmU != nullptr && pmVH != nullptr) {
14656  _check_ne(CVM_SIZESMISMATCH, this->msize(), pmU->msize());
14657  _check_ne(CVM_SIZESMISMATCH, this->nsize(), pmVH->msize());
14658  }
14659  __svd<TR,basic_rmatrix, basic_srmatrix<TR> >(vRes, vRes.size(), vRes.incr(), *this, pmU, pmVH);
14660  }
14661 
14662  virtual void _pinv(basic_rmatrix& mX, TR threshold) const throw(cvmexception) {
14663  __pinv<TR,basic_rmatrix, basic_rmatrix>(mX, *this, threshold);
14664  }
14665 
14666  virtual void _check_submatrix() const {
14667  }
14668 
14669 protected:
14670  // protected constructors for inherited stuff
14671  basic_rmatrix(tint nM, tint nN, tint nLD, bool bZeroMemory)
14672  : BaseMatrix(nM, nN, nLD, bZeroMemory)
14673  {
14674  }
14675 
14676  basic_rmatrix(tint size, tint incr, tint msize, tint nsize, tint ld)
14677  : BaseMatrix(size, incr, msize, nsize, ld)
14678  {
14679  }
14680 
14681  // non-const version shares memory
14682  basic_rmatrix(TR* pd, tint nM, tint nN, tint nLD, tint nSize)
14683  : BaseMatrix(pd, nM, nN, nLD, nSize)
14684  {
14685  }
14686 
14687  // const version makes a copy
14688  basic_rmatrix(const TR* pd, tint nM, tint nN, tint nLD, tint nSize)
14689  : BaseMatrix(pd, nM, nN, nLD, nSize)
14690  {
14691  }
14692 
14693  // returns diagonal which IS l-value (shares memory)
14694  // 0 - main, negative - low, positive - up
14695  virtual RVector _diag(tint nDiag) throw(cvmexception)
14696  {
14697  tint nShift = 0;
14698  tint nSize = 0;
14699  this->_diag_helper(nDiag, nShift, nSize);
14700  return RVector(this->get() + nShift, nSize, this->ld() + 1);
14701  }
14702 
14703  // returns diagonal which IS NOT l-value (creates a copy)
14704  // 0 - main, negative - low, positive - up
14705  virtual const RVector _diag(tint nDiag) const throw(cvmexception)
14706  {
14707  tint nShift = 0;
14708  tint nSize = 0;
14709  this->_diag_helper(nDiag, nShift, nSize);
14710  return RVector(this->get() + nShift, nSize, this->ld() + 1);
14711  }
14712 
14713  // compares matrix elements (equal sizes assumed)
14714  bool _mequals(const basic_rmatrix& m) const {
14715  return ((*this) - m).norminf() <= basic_cvmMachMin<TR>();
14716  }
14717 
14718  // ?gemv routines perform a matrix-vector operation defined as
14719  // vRes = alpha*m*v + beta * vRes or vRes = alpha*v'*m + beta * vRes
14720  // not virtual since __gemv calls all virtual methods inside
14721  void _gemv(bool bLeft, TR dAlpha, const RVector& v, TR dBeta, RVector& vRes) const
14722 {
14723  RVector vTmp;
14724  basic_rmatrix mTmp;
14725  const TR* pDv = v;
14726  if (vRes.get() == pDv) vTmp << v;
14727  if (vRes.get() == this->get()) mTmp << *this;
14728  __gemv<TR,basic_rmatrix, RVector>(bLeft, vRes.get() == this->get() ? mTmp : *this, dAlpha,
14729  vRes.get() == pDv ? vTmp : v, dBeta, vRes);
14730  }
14731 
14732  // 0-based, returns l-value sharing memory
14733  virtual RVector _row(tint m) {
14734  return RVector(this->get() + m, this->nsize(), this->ld());
14735  }
14736 
14737  // 0-based, returns NOT l-value (copies memory)
14738  // looks like cut-n-paste, but it's not
14739  virtual const RVector _row(tint m) const {
14740  return RVector(this->get() + m, this->nsize(), this->ld());
14741  }
14742 
14743  // 0-based, returns l-value sharing memory
14744  virtual RVector _col(tint n) {
14745  return RVector(this->get() + this->ld() * n, this->msize());
14746  }
14747 
14748  // 0-based, returns NOT l-value (copies memory)
14749  // looks like cut-n-paste, but it's not
14750  virtual const RVector _col(tint n) const {
14751  return RVector(this->get() + this->ld() * n, this->msize());
14752  }
14753 
14754  virtual void _mult(const basic_rmatrix& m1, const basic_rmatrix& m2) throw(cvmexception)
14755  {
14756  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
14757  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
14758  _check_ne(CVM_SIZESMISMATCH, m1.nsize(), m2.msize());
14759  static const TR zero = TR(0.);
14760  static const TR one = TR(1.);
14761  this->_gemm(false, m1, false, m2, one, zero);
14762  }
14763 
14764  virtual void _multiply(RVector& vRes, const RVector& v, bool bLeft) const
14765  {
14766  static const TR zero = TR(0.);
14767  static const TR one = TR(1.);
14768  this->_gemv(bLeft, one, v, zero, vRes);
14769  }
14770 
14771  virtual void _randomize(TR dFrom, TR dTo)
14772  {
14773  if (this->_continuous()) {
14774  __randomize<TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
14775  } else for (tint i = 0; i < this->nsize(); ++i) {
14776  __randomize<TR>(this->get() + this->ld() * i, this->msize(), this->incr(), dFrom, dTo);
14777  }
14778  }
14779 
14780  // QR factorization
14781  // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and R is (n x n)
14782  void _qr_rs(basic_rmatrix<TR>& mQ, basic_srmatrix<TR>& mR) const throw(cvmexception)
14783  {
14784  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
14785  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
14786  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mR.msize());
14787  __qre<basic_rmatrix, basic_srmatrix<TR> >(*this, mQ, mR);
14788  }
14789 
14790  // Case 2: full mode, A is (m x n) and Q is (m x m) and R is (m x n)
14791  void _qr_sr(basic_srmatrix<TR>& mQ, basic_rmatrix<TR>& mR) const throw(cvmexception)
14792  {
14793  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
14794  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
14795  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mR.nsize());
14796  __qrf<basic_rmatrix, basic_srmatrix<TR> >(*this, mQ, mR);
14797  }
14798 
14799  // RQ factorization
14800  // Case 1: "economy" mode, A is (m x n) and R is (m x m) and Q is (m x n)
14801  void _rq_sr(basic_srmatrix<TR>& mR, basic_rmatrix<TR>& mQ) const throw(cvmexception)
14802  {
14803  _check_gt(CVM_SIZESMISMATCH_GT, this->msize(), this->nsize());
14804  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
14805  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
14806  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
14807  __rqe<basic_rmatrix, basic_srmatrix<TR> >(*this, mR, mQ);
14808  }
14809 
14810  // Case 2: full mode, A is (m x n) and R is (m x n) and Q is (n x n)
14811  void _rq_rs(basic_rmatrix<TR>& mR, basic_srmatrix<TR>& mQ) const throw(cvmexception)
14812  {
14813  _check_gt(CVM_SIZESMISMATCH_GT, this->msize(), this->nsize());
14814  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.msize());
14815  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
14816  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mR.nsize());
14817  __rqf<basic_rmatrix, basic_srmatrix<TR> >(*this, mR, mQ);
14818  }
14819 
14820  // LQ factorization
14821  // Case 1: "economy" mode, A is (m x n) and L is (m x m) and Q is (m x n)
14822  void _lq_sr(basic_srmatrix<TR>& mL, basic_rmatrix<TR>& mQ) const throw(cvmexception)
14823  {
14824  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
14825  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
14826  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
14827  __lqe<basic_rmatrix, basic_srmatrix<TR> >(*this, mL, mQ);
14828  }
14829 
14830  // Case 2: full mode, A is (m x n) and L is (m x n) and Q is (n x n)
14831  void _lq_rs(basic_rmatrix<TR>& mL, basic_srmatrix<TR>& mQ) const throw(cvmexception)
14832  {
14833  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
14834  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mL.nsize());
14835  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
14836  __lqf<basic_rmatrix, basic_srmatrix<TR> >(*this, mL, mQ);
14837  }
14838 
14839  // QL factorization
14840  // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and L is (n x n)
14841  void _ql_rs(basic_rmatrix<TR>& mQ, basic_srmatrix<TR>& mL) const throw(cvmexception)
14842  {
14843  _check_lt(CVM_SIZESMISMATCH_LT, this->msize(), this->nsize());
14844  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
14845  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
14846  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mL.msize());
14847  __qle<basic_rmatrix, basic_srmatrix<TR> >(*this, mQ, mL);
14848  }
14849 
14850  // Case 2: full mode, A is (m x n) and Q is (m x m) and L is (m x n)
14851  void _ql_sr(basic_srmatrix<TR>& mQ, basic_rmatrix<TR>& mL) const throw(cvmexception)
14852  {
14853  _check_lt(CVM_SIZESMISMATCH_LT, this->msize(), this->nsize());
14854  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
14855  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
14856  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mL.nsize());
14857  __qlf<basic_rmatrix, basic_srmatrix<TR> >(*this, mQ, mL);
14858  }
14859 
14860  virtual void _check_ger() { }
14861  virtual void _check_rank1update() { }
14862  virtual void _check_gemm() { }
14863  virtual void _check_symm() { }
14864 
14865 private:
14866  basic_rmatrix& _solve_helper(const basic_srmatrix<TR>& mA, const basic_rmatrix& mB,
14867  TR& dErr, int transp_mode) throw(cvmexception)
14868  {
14869  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.msize());
14870  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
14871  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
14872  mA._solve(mB, *this, dErr, nullptr, nullptr, transp_mode);
14873  return *this;
14874  }
14875 
14876  // helper for svd and divide&conquer methods
14877  basic_rmatrix _gels_sd(bool svd, const basic_rmatrix& mB, basic_rvector<TR>& sv,
14878  tint& rank, TR tol) const throw(cvmexception)
14879  {
14880  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
14881  _check_ne(CVM_SIZESMISMATCH, sv.size(), _cvm_min<tint>(this->msize(), this->nsize()));
14882  basic_rmatrix mA(*this); // this algorithm overrides A
14883  basic_rmatrix mX;
14884  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
14885  if (svd) {
14886  __gelss(mA, mB, mX, tol, sv1, rank);
14887  } else {
14888  __gelsd(mA, mB, mX, tol, sv1, rank);
14889  }
14890  sv = sv1;
14891  return mX;
14892  }
14893 
14894  void _gels_sd(bool svd, const basic_rmatrix& mA, const basic_rmatrix& mB, basic_rvector<TR>& sv,
14895  tint& rank, TR tol) throw(cvmexception)
14896  {
14897  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.nsize());
14898  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
14899  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
14900  _check_ne(CVM_SIZESMISMATCH, sv.size(), _cvm_min<tint>(mA.msize(), mA.nsize()));
14901  basic_rmatrix mA2(mA); // this algorithm overrides A
14902  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
14903  if (svd) {
14904  __gelss(mA2, mB, *this, tol, sv1, rank);
14905  } else {
14906  __gelsd(mA2, mB, *this, tol, sv1, rank);
14907  }
14908  sv = sv1;
14909  }
14910 
14911  basic_rvector<TR> _gels_sd(bool svd, const basic_rvector<TR>& vB, basic_rvector<TR>& sv,
14912  tint& rank, TR tol) const throw(cvmexception)
14913  {
14914  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
14915  _check_ne(CVM_SIZESMISMATCH, _cvm_min<tint>(this->msize(), this->nsize()), sv.size());
14916  basic_rmatrix mA(*this); // this algorithm overrides A
14917  basic_rmatrix mB(vB, vB.size(), 1);
14918  basic_rmatrix mX;
14919  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
14920  if (svd) {
14921  __gelss(mA, mB, mX, tol, sv1, rank);
14922  } else {
14923  __gelsd(mA, mB, mX, tol, sv1, rank);
14924  }
14925  sv = sv1;
14926  const TR* pResult = mX;
14927  return basic_rvector<TR>(pResult, mX.msize());
14928  }
14930 };
14931 
14932 
14939 template<typename TR>
14940 class basic_srmatrix : public basic_rmatrix<TR>, public SqMatrix<TR,TR>
14941 {
14942  typedef std::complex<TR> TC;
14943  typedef basic_rvector<TR> RVector;
14944  typedef basic_cvector<TR,TC> CVector;
14945  typedef basic_array<TR,TR> BaseArray;
14946  typedef Matrix<TR,TR> BaseMatrix;
14947  typedef SqMatrix<TR,TR> BaseSqMatrix;
14948  typedef basic_rmatrix<TR> BaseRMatrix;
14949 
14950 public:
14977  {
14978  }
14979 
15006  explicit basic_srmatrix(tint nDim)
15007  : BaseRMatrix(nDim, nDim)
15008  {
15009  }
15010 
15041  basic_srmatrix(TR* pd, tint nDim)
15042  : BaseRMatrix(pd, nDim, nDim)
15043  {
15044  }
15045 
15077  basic_srmatrix(const TR* pd, tint nDim)
15078  : BaseRMatrix(pd, nDim, nDim)
15079  {
15080  }
15081 
15111  : BaseRMatrix(m.msize(), m.nsize(), m.msize(), false), BaseSqMatrix()
15112  {
15113  this->_massign(m);
15114  }
15115 
15134  : BaseRMatrix(std::move(m))
15135  {
15136  }
15137 
15170  : BaseRMatrix(m.msize(), m.nsize(), m.msize(), false)
15171  {
15172  _check_ne(CVM_SIZESMISMATCH, this->msize(), this->nsize());
15173  this->_massign(m);
15174  }
15175 
15201  explicit basic_srmatrix(const RVector& v)
15202  : BaseRMatrix(v.size(), v.size(), v.size(), true)
15203  {
15204  __copy<TR>(this->msize(), v, v.incr(), this->get(), this->msize() + 1);
15205  }
15206 
15235  basic_srmatrix(BaseRMatrix& m, tint nRow, tint nCol, tint nDim)
15236  : BaseRMatrix(m, nRow, nCol, nDim, nDim)
15237  {
15238  m._check_submatrix();
15239  }
15240 
15241  type_proxy<TR,TR> operator () (tint nRow, tint nCol) throw(cvmexception)
15242  {
15243  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
15244  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
15245  return this->_ij_proxy_val(nRow - CVM0, nCol - CVM0);
15246  }
15247 
15248  TR operator () (tint nRow, tint nCol) const throw(cvmexception)
15249  {
15250  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
15251  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
15252  return this->_ij_val(nRow - CVM0, nCol - CVM0);
15253  }
15254 
15255  // returns column which IS l-value
15256  RVector operator () (tint nCol) throw(cvmexception)
15257  {
15258  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
15259  return this->_col(nCol - CVM0);
15260  }
15261 
15262  // returns column which is NOT l-value
15263  const RVector operator () (tint nCol) const throw(cvmexception)
15264  {
15265  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
15266  return this->_col(nCol - CVM0);
15267  }
15268 
15269  // returns row which IS l-value
15270  RVector operator [] (tint nRow) throw(cvmexception)
15271  {
15272  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
15273  return this->_row(nRow - CVM0);
15274  }
15275 
15276  // returns row which is NOT l-value
15277  const RVector operator [] (tint nRow) const throw(cvmexception)
15278  {
15279  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
15280  return this->_row(nRow - CVM0);
15281  }
15282 
15316  basic_srmatrix& operator = (const basic_srmatrix& m) throw(cvmexception)
15317  {
15318  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
15319  this->_massign(m);
15320  return *this;
15321  }
15322 
15336  basic_srmatrix& operator = (basic_srmatrix&& m) throw(cvmexception)
15337  {
15338  // size check is in BaseRMatrix
15339  BaseRMatrix::operator = (std::move(m));
15340  return *this;
15341  }
15342 
15343  // assigns vector
15344  basic_srmatrix& assign(const RVector& v) throw(cvmexception)
15345  {
15346  _check_ne(CVM_SIZESMISMATCH, this->size(), v.size());
15347  this->_assign(v, v.incr());
15348  return *this;
15349  }
15350 
15351  // assigns external array (nIncr = 1)
15352  basic_srmatrix& assign(const TR* pd)
15353  {
15354  this->_assign(pd, 1);
15355  return *this;
15356  }
15357 
15389  basic_srmatrix& assign(tint nRow, tint nCol, const BaseRMatrix& m) throw(cvmexception)
15390  {
15391  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
15392  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
15393  _check_gt(CVM_SIZESMISMATCH_GT, m.msize() + nRow - CVM0, this->msize());
15394  _check_gt(CVM_SIZESMISMATCH_GT, m.nsize() + nCol - CVM0, this->nsize());
15395  this->_assign_shifted(this->_sub_pointer_nocheck(nRow, nCol), m._pd(), m.msize(), m.nsize(), m.ld());
15396  return *this;
15397  }
15398 
15399  // fills the content
15400  basic_srmatrix& set(TR d)
15401  {
15402  this->_set(d);
15403  return *this;
15404  }
15405 
15441  basic_srmatrix& resize(tint nNewDim) throw(cvmexception)
15442  {
15443  this->_resize2(nNewDim, nNewDim);
15444  return *this;
15445  }
15446 
15487  basic_srmatrix& operator << (const basic_srmatrix& m) throw(cvmexception)
15488  {
15489  this->_replace(m);
15490  this->_massign(m);
15491  return *this;
15492  }
15493 
15530  basic_srmatrix operator + (const basic_srmatrix& m) const throw(cvmexception)
15531  {
15532  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
15533  basic_srmatrix mSum(*this);
15534  mSum._mincr(m);
15535  return mSum;
15536  }
15537 
15573  basic_srmatrix operator - (const basic_srmatrix& m) const throw(cvmexception)
15574  {
15575  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
15576  basic_srmatrix mDiff(*this);
15577  mDiff._mdecr(m);
15578  return mDiff;
15579  }
15580 
15618  basic_srmatrix& sum(const basic_srmatrix& m1, const basic_srmatrix& m2) throw(cvmexception)
15619  {
15620  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
15621  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
15622  this->_msum(m1, m2);
15623  return *this;
15624  }
15625 
15663  basic_srmatrix& diff(const basic_srmatrix& m1, const basic_srmatrix& m2) throw(cvmexception)
15664  {
15665  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
15666  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
15667  this->_mdiff(m1, m2);
15668  return *this;
15669  }
15670 
15710  basic_srmatrix& operator += (const basic_srmatrix& m) throw(cvmexception)
15711  {
15712  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
15713  this->_mincr(m);
15714  return *this;
15715  }
15716 
15758  basic_srmatrix& operator -= (const basic_srmatrix& m) throw(cvmexception)
15759  {
15760  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
15761  this->_mdecr(m);
15762  return *this;
15763  }
15764 
15787  {
15788  static const TR mone(-1.);
15789  basic_srmatrix mRes(*this);
15790  mRes._scalr(mone);
15791  return mRes;
15792  }
15793 
15819  basic_srmatrix& operator ++ ()
15820  {
15821  this->_plus_plus();
15822  return *this;
15823  }
15824 
15850  basic_srmatrix operator ++ (int)
15851  {
15852  this->_plus_plus();
15853  return *this;
15854  }
15855 
15881  basic_srmatrix& operator -- ()
15882  {
15883  this->_minus_minus();
15884  return *this;
15885  }
15886 
15912  basic_srmatrix operator -- (int)
15913  {
15914  this->_minus_minus();
15915  return *this;
15916  }
15917 
15941  basic_srmatrix operator * (TR dMult) const
15942  {
15943  basic_srmatrix mRes(*this);
15944  mRes._scalr(dMult);
15945  return mRes;
15946  }
15947 
15978  basic_srmatrix operator / (TR dDiv) const throw(cvmexception)
15979  {
15980  basic_srmatrix mRes(*this);
15981  mRes._div(dDiv);
15982  return mRes;
15983  }
15984 
15985  basic_srmatrix& operator *= (TR dMult)
15986  {
15987  this->_scalr(dMult);
15988  return *this;
15989  }
15990 
15991  basic_srmatrix& operator /= (TR dDiv)
15992  {
15993  this->_div(dDiv);
15994  return *this;
15995  }
15996 
15997  basic_srmatrix& normalize()
15998  {
15999  this->_normalize();
16000  return *this;
16001  }
16002 
16040  basic_srmatrix operator ~() const throw(cvmexception)
16041  {
16042  basic_srmatrix mRes(*this);
16043  return mRes.transpose();
16044  }
16045 
16085  basic_srmatrix& transpose(const basic_srmatrix& m) throw(cvmexception)
16086  {
16087  (*this) = m;
16088  return this->transpose();
16089  }
16090 
16091  basic_srmatrix& transpose()
16092  {
16093  this->_transp();
16094  return *this;
16095  }
16096 
16097  RVector operator * (const RVector& v) const throw(cvmexception) {
16098  return this->BaseRMatrix::operator * (v);
16099  }
16100 
16101 // special exclusion since matrix product is not commutative
16132  BaseRMatrix operator * (const BaseRMatrix& m) const throw(cvmexception) {
16133  return this->BaseRMatrix::operator * (m);
16134  }
16135 
16166  basic_srmatrix operator * (const basic_srmatrix& m) const throw(cvmexception)
16167  {
16168  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
16169  basic_srmatrix mRes(this->msize());
16170  mRes.mult(*this, m);
16171  return mRes;
16172  }
16173 
16210  basic_srmatrix& operator *= (const basic_srmatrix& m) throw(cvmexception)
16211  {
16212  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
16213  const basic_srmatrix mTmp(*this);
16214  this->mult(mTmp, m);
16215  return *this;
16216  }
16217 
16218  basic_srmatrix& swap_rows(tint n1, tint n2) throw(cvmexception)
16219  {
16220  this->_swap_rows(n1, n2);
16221  return *this;
16222  }
16223 
16224  basic_srmatrix& swap_cols(tint n1, tint n2) throw(cvmexception)
16225  {
16226  this->_swap_cols(n1, n2);
16227  return *this;
16228  }
16229 
16230 // linear solvers Ax=b. Also return solution flavor.
16291  RVector solve(const RVector& vB, TR& dErr) const throw(cvmexception) {
16292  return _solve_helper(vB, dErr, 0);
16293  }
16294 
16295 // 6.1: transpose added
16356  RVector solve_tran(const RVector& vB, TR& dErr) const throw(cvmexception) {
16357  return _solve_helper(vB, dErr, 1);
16358  }
16359 
16415  RVector solve(const RVector& vB) const throw(cvmexception)
16416  {
16417  static TR dErr(0.);
16418  return this->solve(vB, dErr);
16419  }
16420 
16421 // 6.1: transpose added
16477  RVector solve_tran(const RVector& vB) const throw(cvmexception)
16478  {
16479  static TR dErr(0.);
16480  return this->solve_tran(vB, dErr);
16481  }
16482 
16542  BaseRMatrix solve(const BaseRMatrix& mB, TR& dErr) const throw(cvmexception) {
16543  return _solve_helper(mB, dErr, 0);
16544  }
16545 
16546 // 6.1: transpose added
16605  BaseRMatrix solve_tran(const BaseRMatrix& mB, TR& dErr) const throw(cvmexception) {
16606  return _solve_helper(mB, dErr, 1);
16607  }
16608 
16664  BaseRMatrix solve(const BaseRMatrix& mB) const throw(cvmexception)
16665  {
16666  static TR dErr(0.);
16667  return this->solve(mB, dErr);
16668  }
16669 
16670 // 6.1: transpose added
16727  BaseRMatrix solve_tran(const BaseRMatrix& mB) const throw(cvmexception)
16728  {
16729  static TR dErr(0.);
16730  return this->solve_tran(mB, dErr);
16731  }
16732 
16733 // 6.1: reversed MATLAB-style operator B/A returning solution of X*A=B equation
16770  RVector operator % (const RVector& vB) const throw(cvmexception) {
16771  return vB / (*this);
16772  }
16773 
16774 // 6.1: reversed vector operator % returns solution of A*X=B equation
16811  RVector operator / (const RVector& vB) const throw(cvmexception) {
16812  return vB % (*this);
16813  }
16814 
16899  RVector solve_lu(const basic_srmatrix& mLU, const tint* pPivots, const RVector& vB, TR& dErr) const throw(cvmexception)
16900  {
16901  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
16902  _check_ne(CVM_SIZESMISMATCH, this->msize(), mLU.msize());
16903  RVector vX(this->msize());
16904  this->_solve(vB, vX, dErr, mLU, pPivots, 0);
16905  return vX;
16906  }
16907 
16990  RVector solve_lu(const basic_srmatrix& mLU, const tint* pPivots, const RVector& vB) const throw(cvmexception)
16991  {
16992  static TR dErr(0.);
16993  return this->solve_lu(mLU, pPivots, vB, dErr);
16994  }
16995 
17079  BaseRMatrix solve_lu(const basic_srmatrix& mLU, const tint* pPivots, const BaseRMatrix& mB, TR& dErr) const throw(cvmexception)
17080  {
17081  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
17082  _check_ne(CVM_SIZESMISMATCH, this->msize(), mLU.msize());
17083  BaseRMatrix mX(mB.msize(), mB.nsize());
17084  this->_solve(mB, mX, dErr, mLU, pPivots, 0);
17085  return mX;
17086  }
17087 
17169  BaseRMatrix solve_lu(const basic_srmatrix& mLU, const tint* pPivots, const BaseRMatrix& mB) const throw(cvmexception)
17170  {
17171  static TR dErr(0.);
17172  return this->solve_lu(mLU, pPivots, mB, dErr);
17173  }
17174 
17205  TR det() const throw(cvmexception) {
17206  return this->_det();
17207  }
17208 
17284  basic_srmatrix& low_up(const basic_srmatrix& m, tint* nPivots) throw(cvmexception)
17285  {
17286  (*this) = m;
17287  this->_low_up(nPivots);
17288  return *this;
17289  }
17290 
17361  basic_srmatrix low_up(tint* nPivots) const throw(cvmexception)
17362  {
17363  basic_srmatrix mRes(*this);
17364  mRes._low_up(nPivots);
17365  return mRes;
17366  }
17367 
17409  TR cond() const throw(cvmexception)
17410  {
17411  TR dCondNum(0.);
17412  __cond_num<TR,basic_srmatrix>(*this, dCondNum); // universal method, no need to virtualize
17413  return dCondNum;
17414  }
17415 
17457  basic_srmatrix& inv(const basic_srmatrix& m) throw(cvmexception)
17458  {
17459  __inv<basic_srmatrix>(*this, m); // overridden in srsmatrix, no need to virtualize
17460  return *this;
17461  }
17462 
17503  basic_srmatrix inv() const throw(cvmexception)
17504  {
17505  basic_srmatrix mRes(this->msize());
17506  __inv<basic_srmatrix>(mRes, *this); // overridden in srsmatrix, no need to virtualize
17507  return mRes;
17508  }
17509 
17571  basic_srmatrix& exp(const basic_srmatrix& m, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
17572  {
17573  __exp<basic_srmatrix, TR>(*this, m, tol); // uses universal code inside - no need to virtualize
17574  return *this;
17575  }
17576 
17635  basic_srmatrix exp(TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
17636  {
17637  basic_srmatrix mRes(this->msize());
17638  __exp<basic_srmatrix, TR>(mRes, *this, tol);
17639  return mRes;
17640  }
17641 
17642 // this = v(1)*I + v(2)*m + v(3)*m^2 + ... + v(N)*m^(N-1)
17706  basic_srmatrix& polynom(const basic_srmatrix& m, const RVector& v) throw(cvmexception)
17707  {
17708  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
17709  RVector v1;
17710  if (v.incr() > 1) v1 << v; // to make sure incr = 1
17711  __polynom<TR,RVector>(this->get(), this->ld(), this->msize(), m._pd(), m._ldm(), v.incr() > 1 ? v1 : v);
17712  return *this;
17713  }
17714 
17715  // returns v(1)*I + v(2)*this + v(3)*this^2 + ... + v(N)*this^(N-1)
17778  basic_srmatrix polynom(const RVector& v) const
17779  {
17780  basic_srmatrix mRes(this->msize());
17781  RVector v1;
17782  if (v.incr() > 1) v1 << v; // to make sure incr = 1
17783  __polynom<TR,RVector>(mRes.get(), mRes.ld(), this->msize(), this->get(), this->ld(), v.incr() > 1 ? v1 : v);
17784  return mRes;
17785  }
17786 
17853  CVector eig(basic_scmatrix<TR,TC>& mEigVect, bool bRightVect = true) const throw(cvmexception) {
17854  CVector vEig(this->msize());
17855  this->_eig(vEig, &mEigVect, bRightVect);
17856  return vEig;
17857  }
17858 
17899  CVector eig() const throw(cvmexception) {
17900  CVector vEig(this->msize());
17901  this->_eig(vEig, nullptr, true);
17902  return vEig;
17903  }
17904 
17947  basic_srmatrix& cholesky(const basic_srsmatrix<TR>& m) throw(cvmexception)
17948  {
17949  this->_check_cholesky(); // doesn't work for band matrices
17950  *this = m;
17951  tint nOutInfo = __cholesky<basic_srmatrix>(*this);
17952  _check_negative(CVM_WRONGMKLARG, nOutInfo);
17953  _check_positive(CVM_NOTPOSITIVEDEFINITE, nOutInfo);
17954  this->_clean_low_triangle();
17955  return *this;
17956  }
17957 
17987  basic_srmatrix& bunch_kaufman(const basic_srsmatrix<TR>& m, tint* nPivots) throw(cvmexception)
17988  {
17989  this->_check_bunch_kaufman(); // doesn't work for band matrices
17990  *this = m;
17991  __bunch_kaufman<basic_srmatrix>(*this, nPivots);
17992  return *this;
17993  }
17994 
18022  void qr(basic_srmatrix<TR>& mQ, basic_srmatrix<TR>& mR) const throw(cvmexception) {
18023  this->_qr_ss(mQ, mR);
18024  }
18025 
18053  void lq(basic_srmatrix<TR>& mL, basic_srmatrix<TR>& mQ) const throw(cvmexception) {
18054  this->_lq_ss(mL, mQ);
18055  }
18056 
18084  void ql(basic_srmatrix<TR>& mQ, basic_srmatrix<TR>& mL) const throw(cvmexception) {
18085  this->_ql_ss(mQ, mL);
18086  }
18087 
18115  void rq(basic_srmatrix<TR>& mR, basic_srmatrix<TR>& mQ) const throw(cvmexception) {
18116  this->_rq_ss(mR, mQ);
18117  }
18118 
18145  basic_srmatrix& identity()
18146  {
18147  this->_vanish();
18148  this->_plus_plus();
18149  return *this;
18150  }
18151 
18180  basic_srmatrix& vanish()
18181  {
18182  this->_vanish();
18183  return *this;
18184  }
18185 
18186  basic_srmatrix& randomize(TR dFrom, TR dTo)
18187  {
18188  this->_randomize(dFrom, dTo);
18189  return *this;
18190  }
18191 
18193  virtual void _eig(CVector& vEig, basic_scmatrix<TR,TC>* mEigVect, bool bRightVect) const throw(cvmexception)
18194  {
18195  __eig<CVector, basic_srmatrix, basic_scmatrix<TR,TC> >(vEig, *this, mEigVect, bRightVect);
18196  }
18197 
18198  virtual void _solve(const RVector& vB, RVector& vX,
18199  TR& dErr, const TR* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception)
18200  {
18201  vX = vB;
18202  RVector vB1;
18203  RVector vX1;
18204  if (vB.incr() > 1) vB1 << vB; // to make sure incr = 1
18205  if (vX.incr() > 1) vX1 << vX;
18206  __solve<TR,TR, basic_srmatrix>(*this, 1, vB.incr() > 1 ? vB1 : vB, vB.size(),
18207  vX.incr() > 1 ? vX1 : vX, vX.size(), dErr, pLU, pPivots, transp_mode);
18208  if (vX.incr() > 1) vX = vX1;
18209  }
18210 
18211  virtual void _solve(const BaseRMatrix& mB, BaseRMatrix& mX,
18212  TR& dErr, const TR* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception)
18213  {
18214  mX = mB;
18215  __solve<TR,TR, basic_srmatrix>(*this, mB.nsize(), mB, mB.ld(), mX, mX.ld(), dErr, pLU, pPivots, transp_mode);
18216  }
18217 
18218  const TR* _pv() const override {return this->get();}
18219  TR* _pv() override {return this->get();}
18220 
18221 protected:
18222  // protected constructors for inherited stuff
18223  basic_srmatrix(tint nDim, tint nLD, bool bZeroMemory)
18224  : BaseRMatrix(nDim, nDim, nLD, bZeroMemory)
18225  {
18226  }
18227 
18228  basic_srmatrix(tint size, tint incr, tint msize, tint nsize, tint ld)
18229  : BaseRMatrix(size, incr, msize, nsize, ld)
18230  {
18231  }
18232 
18233  // non-const version shares memory
18234  basic_srmatrix(TR* pd, tint nDim, tint nLD, tint nSize)
18235  : BaseRMatrix(pd, nDim, nDim, nLD, nSize)
18236  {
18237  }
18238 
18239  // const version makes a copy
18240  basic_srmatrix(const TR* pd, tint nDim, tint nLD, tint nSize)
18241  : BaseRMatrix(pd, nDim, nDim, nLD, nSize)
18242  {
18243  }
18244 
18245  tint _size() const override {return this->size();}
18246  tint _msize() const override {return this->msize();}
18247  tint _nsize() const override {return this->nsize();}
18248  tint _ld() const override {return this->ld();}
18249 
18250  // returns diagonal which IS l-value (shares memory)
18251  // 0 - main, negative - low, positive - up
18252  RVector _diag(tint nDiag) throw(cvmexception) override
18253  {
18254  const tint nD = _abs(nDiag);
18255  _check_ge(CVM_INDEX_GE, nD, this->msize());
18256  return RVector(this->get() + (nDiag > 0 ? nDiag * this->ld() : nD), this->msize() - nD, this->ld() + 1);
18257  }
18258 
18259  // returns diagonal which is NOT l-value (creates a copy)
18260  // 0 - main, negative - low, positive - up
18261  const RVector _diag(tint nDiag) const throw(cvmexception) override
18262  {
18263  const tint nD = _abs(nDiag);
18264  _check_ge(CVM_INDEX_GE, nD, this->msize());
18265  return RVector(this->get() + (nDiag > 0 ? nDiag * this->ld() : nD), this->msize() - nD, this->ld() + 1);
18266  }
18267 
18268  // returns main diagonal of low_up factorization
18269  virtual RVector _low_up_diag(basic_array<tint,tint>& naPivots) const throw(cvmexception)
18270  {
18271  // let temp matrix be const to get a copy of its main diagonal
18272  const basic_srmatrix lu = this->low_up(naPivots);
18273  return lu.diag(0);
18274  }
18275 
18276  virtual void _transp() {
18277  this->_sq_transp();
18278  }
18279 
18280  virtual void _plus_plus() {
18281  this->_sq_plus_plus();
18282  }
18283 
18284  virtual void _minus_minus() {
18285  this->_sq_minus_minus();
18286  }
18287 
18288  virtual TR _det() const throw(cvmexception)
18289  {
18290  TR dDet(0.);
18291  switch (this->msize()) {
18292  case 0:
18293  break;
18294  case 1:
18295  dDet = this->_ij_val(0, 0);
18296  break;
18297  case 2:
18298  dDet = this->_ij_val(0, 0) * this->_ij_val(1, 1) -
18299  this->_ij_val(1, 0) * this->_ij_val(0, 1);
18300  break;
18301  default:
18302  try {
18303  static const TR one(1.);
18304  basic_array<tint,tint> naPivots(this->msize());
18305  RVector vUpDiag = this->_low_up_diag(naPivots);
18306 
18307  dDet = one;
18308  for (tint i = CVM0; i <= this->msize() - (1 - CVM0); ++i) {
18309  dDet *= vUpDiag[i];
18310  if (i + (1 - CVM0) != naPivots[i]) {
18311  dDet = -dDet;
18312  }
18313  }
18314  }
18315  catch (const cvmexception& e) {
18316  if (e.cause() != CVM_SINGULARMATRIX) throw e;
18317  }
18318  break;
18319  }
18320  return dDet;
18321  }
18322 
18323  virtual void _low_up(tint* nPivots) throw(cvmexception) {
18324  __low_up<basic_srmatrix>(*this, nPivots);
18325  }
18326 
18327  // QR - "economy" mode here
18328  void _qr_ss(basic_srmatrix<TR>& mQ, basic_srmatrix<TR>& mR) const throw(cvmexception)
18329  {
18330  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
18331  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
18332  __qre<basic_rmatrix<TR>, basic_srmatrix<TR> >(*this, mQ, mR);
18333  }
18334 
18335  // RQ - "economy" mode here
18336  void _rq_ss(basic_srmatrix<TR>& mR, basic_srmatrix<TR>& mQ) const throw(cvmexception)
18337  {
18338  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
18339  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
18340  __rqe<basic_rmatrix<TR>, basic_srmatrix<TR> >(*this, mR, mQ);
18341  }
18342 
18343  // LQ - "economy" mode here
18344  void _lq_ss(basic_srmatrix<TR>& mL, basic_srmatrix<TR>& mQ) const throw(cvmexception)
18345  {
18346  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
18347  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
18348  __lqe<basic_rmatrix<TR>, basic_srmatrix<TR> >(*this, mL, mQ);
18349  }
18350 
18351  // QL - "economy" mode here
18352  void _ql_ss(basic_srmatrix<TR>& mQ, basic_srmatrix<TR>& mL) const throw(cvmexception)
18353  {
18354  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
18355  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
18356  __qle<basic_rmatrix<TR>, basic_srmatrix<TR> >(*this, mQ, mL);
18357  }
18358 
18359  virtual void _check_cholesky() { }
18360  virtual void _check_bunch_kaufman() { }
18361 
18362 private:
18363  RVector _solve_helper(const RVector& vB, TR& dErr, int transp_mode) const throw(cvmexception)
18364  {
18365  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
18366  RVector vX(this->msize());
18367  this->_solve(vB, vX, dErr, nullptr, nullptr, transp_mode);
18368  return vX;
18369  }
18370 
18371  BaseRMatrix _solve_helper(const BaseRMatrix& mB, TR& dErr, int transp_mode) const throw(cvmexception)
18372  {
18373  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
18374  BaseRMatrix mX(mB.msize(), mB.nsize());
18375  this->_solve(mB, mX, dErr, nullptr, nullptr, transp_mode);
18376  return mX;
18377  }
18379 };
18380 
18381 
18388 template<typename TR, typename TC>
18389 class basic_cmatrix : public Matrix<TR,TC>
18390 {
18391  typedef basic_rvector<TR> RVector;
18392  typedef basic_cvector<TR,TC> CVector;
18393  typedef basic_array<TR,TC> BaseArray;
18394  typedef Matrix<TR,TC> BaseMatrix;
18395 
18396  friend class basic_cvector<TR,TC>; // for _multiply
18397 
18398 public:
18422  {
18423  }
18424 
18453  : BaseMatrix(nM, nN, nM, true)
18454  {
18455  }
18456 
18489  basic_cmatrix(TC* pd, tint nM, tint nN)
18490  : BaseMatrix(pd, nM, nN, nM, nM * nN)
18491  {
18492  }
18493 
18527  basic_cmatrix(const TC* pd, tint nM, tint nN)
18528  : BaseMatrix(pd, nM, nN, nM, nM * nN)
18529  {
18530  }
18531 
18558  : BaseMatrix(m.msize(), m.nsize(), m.msize(), false)
18559  {
18560  this->_massign(m);
18561  }
18562 
18581  : BaseMatrix(std::move(m))
18582  {
18583  }
18584 
18615  explicit basic_cmatrix(const CVector& v, bool bBeColumn = true)
18616  : BaseMatrix(v, bBeColumn)
18617  {
18618  }
18619 
18645  explicit basic_cmatrix(const basic_rmatrix<TR>& m, bool bRealPart = true)
18646  : BaseMatrix(m.msize(), m.nsize(), m.msize(), true)
18647  {
18648  if (bRealPart) {
18649  __copy2<TR,TC>(this->get(), this->size(), this->incr(), m._pd(), nullptr);
18650  }
18651  else {
18652  __copy2<TR,TC>(this->get(), this->size(), this->incr(), nullptr, m._pd());
18653  }
18654  }
18655 
18695  basic_cmatrix(const TR* pRe, const TR* pIm, tint nM, tint nN)
18696  : BaseMatrix(nM, nN, nM, true)
18697  {
18698  __copy2<TR,TC>(this->get(), this->size(), this->incr(), pRe, pIm, 1, 1);
18699  }
18700 
18732  : BaseMatrix(mRe.msize(), mRe.nsize(), mRe.msize(), false)
18733  {
18734  _check_ne(CVM_SIZESMISMATCH, mRe.msize(), mIm.msize());
18735  _check_ne(CVM_SIZESMISMATCH, mRe.nsize(), mIm.nsize());
18736  _check_ne(CVM_SIZESMISMATCH, mRe.ld(), mIm.ld());
18737  __copy2<TR,TC>(this->get(), this->size(), this->incr(), mRe, mIm, mRe.incr(), mIm.incr());
18738  }
18739 
18769  basic_cmatrix(basic_cmatrix& m, tint nRow, tint nCol, tint nHeight, tint nWidth)
18770  : BaseMatrix(m._sub_pointer(nRow, nCol, nHeight, nWidth), nHeight, nWidth, m.ld(), nHeight * nWidth)
18771  {
18772  m._check_submatrix();
18773  }
18774 
18811  type_proxy<TC, TR> operator () (tint nRow, tint nCol) throw(cvmexception)
18812  {
18813  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
18814  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
18815  return this->_ij_proxy_val(nRow - CVM0, nCol - CVM0);
18816  }
18817 
18846  TC operator () (tint nRow, tint nCol) const throw(cvmexception)
18847  {
18848  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
18849  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
18850  return this->_ij_val(nRow - CVM0, nCol - CVM0);
18851  }
18852 
18887  CVector operator () (tint nCol) throw(cvmexception)
18888  {
18889  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
18890  return this->_col(nCol - CVM0);
18891  }
18892 
18927  CVector operator [] (tint nRow) throw(cvmexception)
18928  {
18929  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
18930  return this->_row(nRow - CVM0);
18931  }
18932 
18958  const CVector operator () (tint nCol) const throw(cvmexception)
18959  {
18960  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
18961  return this->_col(nCol - CVM0);
18962  }
18963 
18990  const CVector operator [] (tint nRow) const throw(cvmexception) {
18991  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
18992  return this->_row(nRow - CVM0);
18993  }
18994 
19039  CVector diag(tint nDiag) throw(cvmexception) {
19040  return this->_diag(nDiag);
19041  }
19042 
19076  const CVector diag(tint nDiag) const throw(cvmexception) {
19077  return this->_diag(nDiag);
19078  }
19079 
19104  const basic_rmatrix<TR> real() const
19105  {
19106  basic_rmatrix<TR> mRet(this->msize(), this->nsize());
19107  __copy<TR>(this->size(), __get_real_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
19108  return mRet;
19109  }
19110 
19135  const basic_rmatrix<TR> imag() const
19136  {
19137  basic_rmatrix<TR> mRet(this->msize(), this->nsize());
19138  __copy<TR>(this->size(), __get_imag_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
19139  return mRet;
19140  }
19141 
19172  basic_cmatrix& operator = (const basic_cmatrix& m) throw(cvmexception)
19173  {
19174  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
19175  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
19176  this->_massign(m);
19177  return *this;
19178  }
19179 
19193  basic_cmatrix& operator = (basic_cmatrix&& m) throw(cvmexception)
19194  {
19195  // size check is in BaseMatrix
19196  BaseMatrix::operator = (std::move(m));
19197  return *this;
19198  }
19199 
19224  basic_cmatrix& assign(const CVector& v) throw(cvmexception)
19225  {
19226  _check_ne(CVM_SIZESMISMATCH, this->size(), v.size());
19227  this->_assign(v, v.incr());
19228  return *this;
19229  }
19230 
19256  basic_cmatrix& assign(const TC* pd)
19257  {
19258  this->_assign(pd, 1);
19259  return *this;
19260  }
19261 
19292  basic_cmatrix& assign(tint nRow, tint nCol, const basic_cmatrix& m) throw(cvmexception)
19293  {
19294  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
19295  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
19296  _check_gt(CVM_SIZESMISMATCH_GT, m.msize() + nRow - CVM0, this->msize());
19297  _check_gt(CVM_SIZESMISMATCH_GT, m.nsize() + nCol - CVM0, this->nsize());
19298  this->_assign_shifted(this->_sub_pointer_nocheck(nRow, nCol), m._pd(), m.msize(), m.nsize(), m.ld());
19299  return *this;
19300  }
19301 
19323  basic_cmatrix& set(TC c)
19324  {
19325  this->_set(c);
19326  return *this;
19327  }
19328 
19352  basic_cmatrix& assign_real(const basic_rmatrix<TR>& mRe) throw(cvmexception)
19353  {
19354  _check_ne(CVM_SIZESMISMATCH, this->msize(), mRe.msize());
19355  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mRe.nsize());
19356  __copy_real<TR,TC>(this->get(), this->size(), this->incr(), mRe._pd(), mRe.incr());
19357  return *this;
19358  }
19359 
19383  basic_cmatrix& assign_imag(const basic_rmatrix<TR>& mIm) throw(cvmexception)
19384  {
19385  _check_ne(CVM_SIZESMISMATCH, this->msize(), mIm.msize());
19386  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mIm.nsize());
19387  __copy_imag<TR,TC>(this->get(), this->size(), this->incr(), mIm._pd(), mIm.incr());
19388  return *this;
19389  }
19390 
19412  {
19413  this->_set_real_number(d);
19414  return *this;
19415  }
19416 
19438  {
19439  this->_set_imag_number(d);
19440  return *this;
19441  }
19442 
19485  basic_cmatrix& resize(tint nNewM, tint nNewN) throw(cvmexception)
19486  {
19487  this->_resize2(nNewM, nNewN);
19488  return *this;
19489  }
19490 
19516  bool operator == (const basic_cmatrix& m) const {
19517  return this->msize() == m.msize() && this->nsize() == m.nsize() && this->_mequals(m);
19518  }
19519 
19545  bool operator != (const basic_cmatrix& m) const {
19546  return !operator == (m);
19547  }
19548 
19584  basic_cmatrix& operator << (const basic_cmatrix& m) throw(cvmexception)
19585  {
19586  this->_replace(m);
19587  this->_massign(m);
19588  return *this;
19589  }
19590 
19627  basic_cmatrix operator + (const basic_cmatrix& m) const throw(cvmexception)
19628  {
19629  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
19630  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
19631  basic_cmatrix mSum(*this);
19632  mSum._mincr(m);
19633  return mSum;
19634  }
19635 
19671  basic_cmatrix operator - (const basic_cmatrix& m) const throw(cvmexception)
19672  {
19673  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
19674  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
19675  basic_cmatrix mDiff(*this);
19676  mDiff._mdecr(m);
19677  return mDiff;
19678  }
19679 
19717  basic_cmatrix& sum(const basic_cmatrix& m1, const basic_cmatrix& m2) throw(cvmexception)
19718  {
19719  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
19720  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m1.nsize());
19721  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
19722  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
19723  this->_msum(m1, m2);
19724  return *this;
19725  }
19726 
19764  basic_cmatrix& diff(const basic_cmatrix& m1, const basic_cmatrix& m2) throw(cvmexception)
19765  {
19766  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
19767  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m1.nsize());
19768  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
19769  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
19770  this->_mdiff(m1, m2);
19771  return *this;
19772  }
19773 
19811  basic_cmatrix& operator += (const basic_cmatrix& m) throw(cvmexception)
19812  {
19813  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
19814  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
19815  this->_mincr(m);
19816  return *this;
19817  }
19818 
19856  basic_cmatrix& operator -= (const basic_cmatrix& m) throw(cvmexception)
19857  {
19858  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
19859  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
19860  this->_mdecr(m);
19861  return *this;
19862  }
19863 
19886  {
19887  static const TR mone(-1.);
19888  basic_cmatrix mRes(*this);
19889  mRes._scalr(mone);
19890  return mRes;
19891  }
19892 
19916  basic_cmatrix operator * (TR dMult) const
19917  {
19918  basic_cmatrix mRes(*this);
19919  mRes._scalr(dMult);
19920  return mRes;
19921  }
19922 
19953  basic_cmatrix operator / (TR dDiv) const throw(cvmexception)
19954  {
19955  basic_cmatrix mRes(*this);
19956  mRes._div(dDiv);
19957  return mRes;
19958  }
19959 
19983  basic_cmatrix operator * (TC cMult) const
19984  {
19985  basic_cmatrix mRes(*this);
19986  mRes._scalc(cMult);
19987  return mRes;
19988  }
19989 
20020  basic_cmatrix operator / (TC cDiv) const throw(cvmexception)
20021  {
20022  basic_cmatrix mRes(*this);
20023  mRes._div(cDiv);
20024  return mRes;
20025  }
20026 
20051  {
20052  this->_scalr(dMult);
20053  return *this;
20054  }
20055 
20087  {
20088  this->_div(dDiv);
20089  return *this;
20090  }
20091 
20116  {
20117  this->_scalc(cMult);
20118  return *this;
20119  }
20120 
20152  {
20153  this->_div(cDiv);
20154  return *this;
20155  }
20156 
20182  {
20183  this->_normalize();
20184  return *this;
20185  }
20186 
20222  basic_cmatrix operator !() const throw(cvmexception)
20223  {
20224  basic_cmatrix mRes(this->nsize(), this->msize());
20225  mRes._transp_m(*this);
20226  return mRes;
20227  }
20228 
20264  basic_cmatrix operator ~() const throw(cvmexception)
20265  {
20266  basic_cmatrix mRes(this->nsize(), this->msize());
20267  mRes._transp_m(*this);
20268  __conj<TC>(mRes.get(), mRes.size(), mRes.incr());
20269  return mRes;
20270  }
20271 
20309  basic_cmatrix& transpose(const basic_cmatrix& m) throw(cvmexception)
20310  {
20311  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.nsize());
20312  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
20313  if (this->get() == m.get()) {
20314  basic_cmatrix mTmp(m);
20315  this->_transp_m(mTmp);
20316  } else {
20317  this->_transp_m(m);
20318  }
20319  return *this;
20320  }
20321 
20359  basic_cmatrix& conj(const basic_cmatrix& m) throw(cvmexception)
20360  {
20361  this->transpose(m);
20362  __conj<TC>(this->get(), this->size(), this->incr());
20363  return *this;
20364  }
20365 
20402  basic_cmatrix& transpose() throw(cvmexception)
20403  {
20404  basic_cmatrix mTmp(*this);
20405  this->_resize2(this->nsize(), this->msize());
20406  this->_transp_m(mTmp);
20407  return *this;
20408  }
20409 
20446  basic_cmatrix& conj() throw(cvmexception)
20447  {
20448  this->transpose();
20449  __conj<TC>(this->get(), this->size(), this->incr());
20450  return *this;
20451  }
20452 
20478  CVector operator * (const CVector& v) const throw(cvmexception)
20479  {
20480  _check_ne(CVM_SIZESMISMATCH, this->nsize(), v.size());
20481  CVector vRes(this->msize());
20482  this->_multiply(vRes, v, false);
20483  return vRes;
20484  }
20485 
20510  basic_cmatrix operator * (const basic_cmatrix& m) const throw(cvmexception)
20511  {
20512  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
20513  basic_cmatrix mRes(this->msize(), m.nsize());
20514  mRes.mult(*this, m);
20515  return mRes;
20516  }
20517 
20544  basic_cmatrix& mult(const basic_cmatrix& m1, const basic_cmatrix& m2) throw(cvmexception)
20545  {
20546  this->_mult(m1, m2);
20547  return *this;
20548  }
20549 
20593  basic_cmatrix& rank1update_u(const CVector& vCol, const CVector& vRow) throw(cvmexception)
20594  {
20595  static const TC one(1., 0.);
20596  this->_check_rank1update_u();
20597  _check_ne(CVM_SIZESMISMATCH, this->msize(), vCol.size());
20598  _check_ne(CVM_SIZESMISMATCH, this->nsize(), vRow.size());
20599  this->_vanish();
20600  __geru<TC, basic_cmatrix, CVector>(*this, vCol, vRow, one);
20601  return *this;
20602  }
20603 
20648  basic_cmatrix& rank1update_c(const CVector& vCol, const CVector& vRow) throw(cvmexception)
20649  {
20650  static const TC one(1., 0.);
20651  this->_check_rank1update_c();
20652  _check_ne(CVM_SIZESMISMATCH, this->msize(), vCol.size());
20653  _check_ne(CVM_SIZESMISMATCH, this->nsize(), vRow.size());
20654  this->_vanish();
20655  __gerc<TC, basic_cmatrix, CVector>(*this, vCol, vRow, one);
20656  return *this;
20657  }
20658 
20688  basic_cmatrix& swap_rows(tint n1, tint n2) throw(cvmexception)
20689  {
20690  this->_swap_rows(n1, n2);
20691  return *this;
20692  }
20693 
20721  basic_cmatrix& swap_cols(tint n1, tint n2) throw(cvmexception)
20722  {
20723  this->_swap_cols(n1, n2);
20724  return *this;
20725  }
20726 
20770  basic_cmatrix& solve(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB, TR& dErr) throw(cvmexception) {
20771  return _solve_helper(mA, mB, dErr, 0);
20772  }
20773 
20774 // 6.1: transpose added
20818  basic_cmatrix& solve_tran(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB, TR& dErr) throw(cvmexception) {
20819  return _solve_helper(mA, mB, dErr, 1);
20820  }
20821 
20822 // 6.1: conjugate added
20866  basic_cmatrix& solve_conj(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB, TR& dErr) throw(cvmexception) {
20867  return _solve_helper(mA, mB, dErr, 2);
20868  }
20869 
20908  basic_cmatrix& solve(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB) throw(cvmexception)
20909  {
20910  static TR dErr(0.);
20911  return this->solve(mA, mB, dErr);
20912  }
20913 
20914 // 6.1: transpose added
20955  basic_cmatrix& solve_tran(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB) throw(cvmexception)
20956  {
20957  static TR dErr(0.);
20958  return this->solve_tran(mA, mB, dErr);
20959  }
20960 
20961 // 6.1: conjugate added
21002  basic_cmatrix& solve_conj(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB) throw(cvmexception)
21003  {
21004  static TR dErr(0.);
21005  return this->solve_conj(mA, mB, dErr);
21006  }
21007 
21078  const basic_cmatrix& mB, TR& dErr) throw(cvmexception)
21079  {
21080  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.msize());
21081  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
21082  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
21083  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mLU.msize());
21084  mA._solve(mB, *this, dErr, mLU, pPivots, 0);
21085  return *this;
21086  }
21087 
21155  const basic_cmatrix& mB) throw(cvmexception)
21156  {
21157  static TR dErr(0.);
21158  return this->solve_lu(mA, mLU, pPivots, mB, dErr);
21159  }
21160 
21227  RVector svd() const throw(cvmexception)
21228  {
21229  RVector vRes(_cvm_min<tint>(this->msize(), this->nsize()));
21230  this->_svd(vRes, nullptr, nullptr);
21231  return vRes;
21232  }
21233 
21305  RVector svd(basic_scmatrix<TR,TC>& mU, basic_scmatrix<TR,TC>& mVH) const throw(cvmexception)
21306  {
21307  RVector vRes(_cvm_min<tint>(this->msize(), this->nsize()));
21308  this->_svd(vRes, &mU, &mVH);
21309  return vRes;
21310  }
21311 
21368  basic_cmatrix pinv(TR threshold = basic_cvmMachSp<TR>()) const throw(cvmexception)
21369  {
21370  basic_cmatrix mAx(this->nsize(), this->msize());
21371  this->_pinv(mAx, threshold);
21372  return mAx;
21373  }
21374 
21432  basic_cmatrix& pinv(const basic_cmatrix& mA, TR threshold = basic_cvmMachSp<TR>()) throw(cvmexception)
21433  {
21434  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.nsize());
21435  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mA.msize());
21436  mA._pinv(*this, threshold);
21437  return *this;
21438  }
21439 
21508  basic_cmatrix gels(bool conjugate, const basic_cmatrix& mB, basic_cvector<TR,TC>& vErr) const throw(cvmexception)
21509  {
21510  _check_ne(CVM_SIZESMISMATCH, vErr.size(), mB.nsize());
21511  _check_ne(CVM_SIZESMISMATCH, conjugate ? this->nsize() : this->msize(), mB.msize());
21512  basic_cmatrix mA(*this); // this algorithm overrides A
21513  basic_cmatrix mX;
21514  __gels(conjugate, mA, mB, mX, vErr);
21515  return mX;
21516  }
21517 
21587  basic_cmatrix& gels(bool conjugate, const basic_cmatrix& mA, const basic_cmatrix& mB,
21588  basic_cvector<TR,TC>& vErr) throw(cvmexception)
21589  {
21590  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
21591  _check_ne(CVM_SIZESMISMATCH, mB.nsize(), vErr.size());
21592  _check_ne(CVM_SIZESMISMATCH, this->msize(), conjugate ? mA.msize() : mA.nsize());
21593  _check_ne(CVM_SIZESMISMATCH, mB.msize(), conjugate ? mA.nsize() : mA.msize());
21594  basic_cmatrix mA2(mA); // this algorithm overrides A
21595  __gels(conjugate, mA2, mB, *this, vErr);
21596  return *this;
21597  }
21598 
21664  basic_cvector<TR,TC> gels(bool conjugate, const basic_cvector<TR,TC>& vB, TC& dErr) const throw(cvmexception)
21665  {
21666  _check_ne(CVM_SIZESMISMATCH, conjugate ? this->nsize() : this->msize(), vB.size());
21667  basic_cmatrix mA(*this); // this algorithm overrides A
21668  basic_cmatrix mB(vB, vB.size(), 1);
21669  basic_cmatrix mX;
21670  basic_cvector<TR,TC> vErr(1);
21671  __gels(conjugate, mA, mB, mX, vErr);
21672  dErr = vErr(CVM0);
21673  const TC* pResult = mX;
21674  return basic_cvector<TR,TC>(pResult, mX.msize());
21675  }
21676 
21733  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
21734  {
21735  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
21736  basic_cmatrix mA(*this); // this algorithm overrides A
21737  basic_cmatrix mX;
21738  __gelsy(mA, mB, mX, tol, rank);
21739  return mX;
21740  }
21741 
21800  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
21801  {
21802  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.nsize());
21803  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
21804  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
21805  basic_cmatrix mA2(mA); // this algorithm overrides A
21806  __gelsy(mA2, mB, *this, tol, rank);
21807  return *this;
21808  }
21809 
21866  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
21867  {
21868  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
21869  basic_cmatrix mA(*this); // this algorithm overrides A
21870  basic_cmatrix mB(vB, vB.size(), 1);
21871  basic_cmatrix mX;
21872  __gelsy(mA, mB, mX, tol, rank);
21873  const TC* pResult = mX;
21874  return basic_cvector<TR,TC>(pResult, mX.msize());
21875  }
21876 
21939  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
21940  {
21941  return _gels_sd(true, mB, sv, rank, tol);
21942  }
21943 
22008  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
22009  {
22010  _gels_sd(true, mA, mB, sv, rank, tol);
22011  return *this;
22012  }
22013 
22076  tint& rank, TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
22077  {
22078  return _gels_sd(true, vB, sv, rank, tol);
22079  }
22080 
22143  TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
22144  {
22145  return _gels_sd(false, mB, sv, rank, tol);
22146  }
22147 
22212  tint& rank, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
22213  {
22214  _gels_sd(false, mA, mB, sv, rank, tol);
22215  return *this;
22216  }
22217 
22280  tint& rank, TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
22281  {
22282  return _gels_sd(false, vB, sv, rank, tol);
22283  }
22284 
22316  tint rank(TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
22317  {
22318  tint nRank = 0;
22319  RVector vS(_cvm_min<tint>(this->msize(), this->nsize()));
22320  this->_svd(vS, nullptr, nullptr);
22321  vS.normalize();
22322  for (; nRank < vS.size(); ++nRank) {
22323  if (vS[nRank * this->incr() + CVM0] < tol) break;
22324  }
22325  return nRank;
22326  }
22327 
22328 // QR factorization
22329 // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and R is (n x n)
22377  void qr(basic_cmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mR) const throw(cvmexception) {
22378  this->_qr_rs(mQ, mR);
22379  }
22380 
22381 // Case 2: full mode, A is (m x n) and Q is (m x m) and R is (m x n)
22429  void qr(basic_scmatrix<TR,TC>& mQ, basic_cmatrix<TR,TC>& mR) const throw(cvmexception) {
22430  this->_qr_sr(mQ, mR);
22431  }
22432 
22433 // LQ factorization
22434 // Case 1: "economy" mode, A is (m x n) and L is (m x m) and Q is (m x n)
22481  void lq(basic_scmatrix<TR,TC>& mL, basic_cmatrix<TR,TC>& mQ) const throw(cvmexception) {
22482  this->_lq_sr(mL, mQ);
22483  }
22484 
22485 // Case 2: full mode, A is (m x n) and L is (m x n) and Q is (n x n)
22532  void lq(basic_cmatrix<TR,TC>& mL, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception) {
22533  this->_lq_rs(mL, mQ);
22534  }
22535 
22536 // RQ factorization
22537 // Case 1: "ecomomy" mode, A is (m x n) and R is (m x m) and Q is (m x n)
22578  void rq(basic_scmatrix<TR,TC>& mR, basic_cmatrix<TR,TC>& mQ) const throw(cvmexception) {
22579  this->_rq_sr(mR, mQ);
22580  }
22581 
22582 // Case 2: full mode, A is (m x n) and R is (m x n) and Q is (n x n)
22623  void rq(basic_cmatrix<TR,TC>& mR, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception) {
22624  this->_rq_rs(mR, mQ);
22625  }
22626 
22627 // QL factorization
22628 // Case 1: "ecomomy" mode, A is (m x n) and Q is (m x n) and L is (n x n)
22668  void ql(basic_cmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mL) const throw(cvmexception) {
22669  this->_ql_rs(mQ, mL);
22670  }
22671 
22672 // Case 2: full mode, A is (m x n) and Q is (m x m) and L is (m x n)
22712  void ql(basic_scmatrix<TR,TC>& mQ, basic_cmatrix<TR,TC>& mL) const throw(cvmexception) {
22713  this->_ql_sr(mQ, mL);
22714  }
22715 
22716 // this += alpha * v_col * v_row (unconjugated)
22773  basic_cmatrix& geru(TC alpha, const CVector& vCol, const CVector& vRow) throw(cvmexception)
22774  {
22775  this->_check_geru();
22776  _check_ne(CVM_SIZESMISMATCH, this->msize(), vCol.size());
22777  _check_ne(CVM_SIZESMISMATCH, this->nsize(), vRow.size());
22778  __geru<TC, basic_cmatrix, CVector>(*this, vCol, vRow, alpha);
22779  return *this;
22780  }
22781 
22782 // this += alpha * v_col * v_row (conjugated)
22839  basic_cmatrix& gerc(TC alpha, const CVector& vCol, const CVector& vRow) throw(cvmexception)
22840  {
22841  this->_check_gerc();
22842  _check_ne(CVM_SIZESMISMATCH, this->msize(), vCol.size());
22843  _check_ne(CVM_SIZESMISMATCH, this->nsize(), vRow.size());
22844  __gerc<TC, basic_cmatrix, CVector>(*this, vCol, vRow, alpha);
22845  return *this;
22846  }
22847 
22848 // this = alpha * m1 * m2 + beta * this
22908  basic_cmatrix& gemm(const basic_cmatrix& m1, bool bConj1, const basic_cmatrix& m2,
22909  bool bConj2, TC cAlpha, TC cBeta) throw(cvmexception)
22910  {
22911  this->_check_gemm();
22912  _check_ne(CVM_SIZESMISMATCH, this->msize(), bConj1 ? m1.nsize() : m1.msize());
22913  _check_ne(CVM_SIZESMISMATCH, this->nsize(), bConj2 ? m2.msize() : m2.nsize());
22914  _check_ne(CVM_SIZESMISMATCH, bConj1 ? m1.msize() : m1.nsize(), bConj2 ? m2.nsize() : m2.msize());
22915  this->_gemm(bConj1, m1, bConj2, m2, cAlpha, cBeta);
22916  return *this;
22917  }
22918 
22919 // this = alpha*a*b + beta*this of this = alpha*b*a + beta*this where a is hermitian
22990  basic_cmatrix& hemm(bool bLeft, const basic_schmatrix<TR,TC>& ms, const basic_cmatrix& m,
22991  TC cAlpha, TC cBeta) throw(cvmexception)
22992  {
22993  this->_check_hemm();
22994  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
22995  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.nsize());
22996  _check_ne(CVM_SIZESMISMATCH, bLeft ? this->msize() : this->nsize(), ms.msize());
22997  this->_hemm(bLeft, ms, m, cAlpha, cBeta);
22998  return *this;
22999  }
23000 
23030  basic_cmatrix& vanish()
23031  {
23032  this->_vanish();
23033  return *this;
23034  }
23035 
23059  basic_cmatrix& randomize_real(TR dFrom, TR dTo)
23060  {
23061  this->_randomize_real(dFrom, dTo);
23062  return *this;
23063  }
23064 
23088  basic_cmatrix& randomize_imag(TR dFrom, TR dTo)
23089  {
23090  this->_randomize_imag(dFrom, dTo);
23091  return *this;
23092  }
23093 
23094  // 2-norm (maximum singular value)
23095  TR norm2() const override
23096  {
23097  RVector vS(_cvm_min<tint>(this->msize(), this->nsize()));
23098  this->_svd(vS, nullptr, nullptr);
23099  return vS[CVM0];
23100  }
23101 
23103  void _div(TC d) throw(cvmexception)
23104  {
23105  if (_abs(d) <= basic_cvmMachMin<TR>()) {
23106  throw cvmexception(CVM_DIVISIONBYZERO);
23107  }
23108  static const TC one(1., 0.);
23109  this->_scalc(one / d);
23110  }
23111 
23112  // ?gemm routines perform a matrix-matrix operation with general matrices. The operation is defined as
23113  // c := alpha*op(a)*op(b) + beta*c,
23114  // where: op(x) is one of op(x) = x or op(x) = x' or op(x) = conjg(x'),
23115  void _gemm(bool bTrans1, const basic_cmatrix& m1, bool bTrans2, const basic_cmatrix& m2, TC dAlpha, TC dBeta) throw(cvmexception)
23116  {
23117  basic_cmatrix mTmp1, mTmp2;
23118  const TC* pD1 = m1.get();
23119  const TC* pD2 = m2.get();
23120  if (this->get() == pD1) mTmp1 << m1;
23121  if (this->get() == pD2) mTmp2 << m2;
23122  __gemm<TC, basic_cmatrix>(this->get() == pD1 ? mTmp1 : m1, bTrans1,
23123  this->get() == pD2 ? mTmp2 : m2, bTrans2, dAlpha, *this, dBeta);
23124  }
23125 
23126  // this = alpha*a*b + beta*this or this = alpha*b*a + beta*this where a is hermitian
23127  void _hemm(bool bLeft, const basic_schmatrix<TR,TC>& ms, const basic_cmatrix& m, TC dAlpha, TC dBeta) throw(cvmexception)
23128  {
23129  basic_cmatrix mTmp;
23130  basic_schmatrix<TR,TC> msTmp;
23131  const TC* pD1 = ms.get();
23132  const TC* pD2 = m._pd();
23133  if (this->get() == pD1) msTmp << ms;
23134  if (this->get() == pD2) mTmp << m;
23135  __hemm<TC, basic_schmatrix<TR,TC>, basic_cmatrix>(bLeft, this->get() == pD1 ? msTmp : ms,
23136  this->get() == pD2 ? mTmp : m, dAlpha, *this, dBeta);
23137  }
23138 
23139  // singular values in decreasing order
23140  virtual void _svd(RVector& vRes, basic_scmatrix<TR,TC>* pmU, basic_scmatrix<TR,TC>* pmVH) const throw(cvmexception)
23141  {
23142  if (pmU != nullptr && pmVH != nullptr) {
23143  _check_ne(CVM_SIZESMISMATCH, this->msize(), pmU->msize());
23144  _check_ne(CVM_SIZESMISMATCH, this->nsize(), pmVH->msize());
23145  }
23146  __svd<TR,basic_cmatrix, basic_scmatrix<TR,TC> >(vRes, vRes.size(), vRes.incr(), *this, pmU, pmVH);
23147  }
23148 
23149  virtual void _pinv(basic_cmatrix& mX, TR threshold) const throw(cvmexception) {
23150  __pinv<TR,basic_cmatrix, basic_cmatrix>(mX, *this, threshold);
23151  }
23152 
23153  virtual void _check_submatrix() const {
23154  }
23155 
23156  virtual void _scalc(TC d)
23157  {
23158  if (this->_continuous()) {
23159  __scal<TC, TC>(this->get(), this->size(), this->incr(), d);
23160  } else for (tint i = 0; i < this->nsize(); ++i) {
23161  __scal<TC, TC>(this->get() + this->ld() * i, this->msize(), this->incr(), d);
23162  }
23163  }
23164 
23165 protected:
23166  // protected constructors for inherited stuff
23167  basic_cmatrix(tint nM, tint nN, tint nLD, bool bZeroMemory)
23168  : BaseMatrix(nM, nN, nLD, bZeroMemory)
23169  {
23170  }
23171 
23172  basic_cmatrix(tint size, tint incr, tint msize, tint nsize, tint ld)
23173  : BaseMatrix(size, incr, msize, nsize, ld)
23174  {
23175  }
23176 
23177  // non-const version shares memory
23178  basic_cmatrix(TC* pd, tint nM, tint nN, tint nLD, tint nSize)
23179  : BaseMatrix(pd, nM, nN, nLD, nSize)
23180  {
23181  }
23182 
23183  // const version makes a copy
23184  basic_cmatrix(const TC* pd, tint nM, tint nN, tint nLD, tint nSize)
23185  : BaseMatrix(pd, nM, nN, nLD, nSize)
23186  {
23187  }
23188 
23189  virtual CVector _diag(tint nDiag) throw(cvmexception)
23190  {
23191  tint nShift = 0;
23192  tint nSize = 0;
23193  this->_diag_helper(nDiag, nShift, nSize);
23194  return CVector(this->get() + nShift, nSize, this->ld() + 1);
23195  }
23196 
23197  virtual const CVector _diag(tint nDiag) const throw(cvmexception)
23198  {
23199  tint nShift = 0;
23200  tint nSize = 0;
23201  this->_diag_helper(nDiag, nShift, nSize);
23202  return CVector(this->get() + nShift, nSize, this->ld() + 1);
23203  }
23204 
23205  // compares matrix elements (equal sizes assumed)
23206  bool _mequals(const basic_cmatrix& m) const
23207  {
23208  return ((*this) - m).norminf() <= basic_cvmMachMin<TR>();
23209  }
23210 
23211  // ?gemv routines perform a matrix-vector operation defined as
23212  // vRes = alpha*m*v + beta * vRes or vRes = alpha*v'*m + beta * vRes
23213  // not virtual since __gemv calls all virtual methods inside
23214  void _gemv(bool bLeft, TC dAlpha, const CVector& v, TC dBeta, CVector& vRes) const
23215  {
23216  CVector vTmp;
23217  basic_cmatrix mTmp;
23218  const TC* pDv = v;
23219  if (vRes.get() == pDv) vTmp << v;
23220  if (vRes.get() == this->get()) mTmp << *this;
23221  __gemv<TC, basic_cmatrix, CVector>(bLeft, vRes.get() == this->get() ? mTmp : *this, dAlpha,
23222  vRes.get() == pDv ? vTmp : v, dBeta, vRes);
23223  }
23224 
23225  // 0-based, returns an l-value sharing memory
23226  virtual CVector _row(tint m) {
23227  return CVector(this->get() + m, this->nsize(), this->ld());
23228  }
23229 
23230  // 0-based, returns not an l-value (copy)
23231  virtual const CVector _row(tint m) const {
23232  return CVector(this->get() + m, this->nsize(), this->ld());
23233  }
23234 
23235  // 0-based, returns an l-value sharing memory
23236  virtual CVector _col(tint n) {
23237  return CVector(this->get() + this->ld() * n, this->msize());
23238  }
23239 
23240  // 0-based, returns not an l-value (copy)
23241  virtual const CVector _col(tint n) const {
23242  return CVector(this->get() + this->ld() * n, this->msize());
23243  }
23244 
23245  virtual void _mult(const basic_cmatrix& m1, const basic_cmatrix& m2) throw(cvmexception)
23246  {
23247  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
23248  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
23249  _check_ne(CVM_SIZESMISMATCH, m1.nsize(), m2.msize());
23250  static const TR zero = TR(0.);
23251  static const TR one = TR(1.);
23252  this->_gemm(false, m1, false, m2, one, zero);
23253  }
23254 
23255  virtual void _multiply(CVector& vRes, const CVector& v, bool bLeft) const
23256  {
23257  static const TR zero = TR(0.);
23258  static const TR one = TR(1.);
23259  this->_gemv(bLeft, one, v, zero, vRes);
23260  }
23261 
23262  void _set_real_number(TR d)
23263  {
23264  if (this->_continuous()) {
23265  _set_real<TR,TC>(this->get(), this->size(), this->incr(), d);
23266  } else for (tint i = 0; i < this->nsize(); ++i) {
23267  _set_real<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), d);
23268  }
23269  }
23270 
23271  virtual void _set_imag_number(TR d)
23272  {
23273  if (this->_continuous()) {
23274  _set_imag<TR,TC>(this->get(), this->size(), this->incr(), d);
23275  } else for (tint i = 0; i < this->nsize(); ++i) {
23276  _set_imag<TR,TC>(this->get() + this->ld() * i, this->msize(), this->incr(), d);
23277  }
23278  }
23279 
23280  virtual void _randomize_real(TR dFrom, TR dTo)
23281  {
23282  if (this->_continuous()) {
23283  __randomize_real<TC, TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
23284  } else for (tint i = 0; i < this->nsize(); ++i) {
23285  __randomize_real<TC, TR>(this->get() + this->ld() * i, this->msize(), this->incr(), dFrom, dTo);
23286  }
23287  }
23288 
23289  virtual void _randomize_imag(TR dFrom, TR dTo)
23290  {
23291  if (this->_continuous()) {
23292  __randomize_imag<TC, TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
23293  } else for (tint i = 0; i < this->nsize(); ++i) {
23294  __randomize_imag<TC, TR>(this->get() + this->ld() * i, this->msize(), this->incr(), dFrom, dTo);
23295  }
23296  }
23297 
23298  // QR factorization
23299  // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and R is (n x n)
23300  void _qr_rs(basic_cmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mR) const throw(cvmexception)
23301  {
23302  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
23303  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
23304  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mR.msize());
23305  __qre<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mQ, mR);
23306  }
23307 
23308  // Case 2: full mode, A is (m x n) and Q is (m x m) and R is (m x n)
23309  void _qr_sr(basic_scmatrix<TR,TC>& mQ, basic_cmatrix<TR,TC>& mR) const throw(cvmexception)
23310  {
23311  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
23312  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
23313  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mR.nsize());
23314  __qrf<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mQ, mR);
23315  }
23316 
23317  // RQ factorization
23318  // Case 1: "economy" mode, A is (m x n) and R is (m x m) and Q is (m x n)
23319  void _rq_sr(basic_scmatrix<TR,TC>& mR, basic_cmatrix<TR,TC>& mQ) const throw(cvmexception)
23320  {
23321  _check_gt(CVM_SIZESMISMATCH_GT, this->msize(), this->nsize());
23322  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
23323  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
23324  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
23325  __rqe<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mR, mQ);
23326  }
23327 
23328  // Case 2: full mode, A is (m x n) and R is (m x n) and Q is (n x n)
23329  void _rq_rs(basic_cmatrix<TR,TC>& mR, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception)
23330  {
23331  _check_gt(CVM_SIZESMISMATCH_GT, this->msize(), this->nsize());
23332  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
23333  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.msize());
23334  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mR.nsize());
23335  __rqf<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mR, mQ);
23336  }
23337 
23338  // LQ factorization
23339  // Case 1: "economy" mode, A is (m x n) and L is (m x m) and Q is (m x n)
23340  void _lq_sr(basic_scmatrix<TR,TC>& mL, basic_cmatrix<TR,TC>& mQ) const throw(cvmexception)
23341  {
23342  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
23343  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
23344  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
23345  __lqe<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mL, mQ);
23346  }
23347 
23348  // Case 2: full mode, A is (m x n) and L is (m x n) and Q is (n x n)
23349  void _lq_rs(basic_cmatrix<TR,TC>& mL, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception)
23350  {
23351  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
23352  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mL.nsize());
23353  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
23354  __lqf<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mL, mQ);
23355  }
23356 
23357  // QL factorization
23358  // Case 1: "economy" mode, A is (m x n) and Q is (m x n) and L is (n x n)
23359  void _ql_rs(basic_cmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mL) const throw(cvmexception)
23360  {
23361  _check_lt(CVM_SIZESMISMATCH_LT, this->msize(), this->nsize());
23362  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
23363  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mQ.nsize());
23364  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mL.msize());
23365  __qle<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mQ, mL);
23366  }
23367 
23368  // Case 2: full mode, A is (m x n) and Q is (m x m) and L is (m x n)
23369  void _ql_sr(basic_scmatrix<TR,TC>& mQ, basic_cmatrix<TR,TC>& mL) const throw(cvmexception)
23370  {
23371  _check_lt(CVM_SIZESMISMATCH_LT, this->msize(), this->nsize());
23372  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
23373  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
23374  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mL.nsize());
23375  __qlf<basic_cmatrix, basic_scmatrix<TR,TC> >(*this, mQ, mL);
23376  }
23377 
23378  virtual void _check_geru() { }
23379  virtual void _check_gerc() { }
23380  virtual void _check_rank1update_u() { }
23381  virtual void _check_rank1update_c() { }
23382  virtual void _check_gemm() { }
23383  virtual void _check_hemm() { }
23384 
23385 private:
23386  basic_cmatrix& _solve_helper(const basic_scmatrix<TR,TC>& mA, const basic_cmatrix& mB,
23387  TR& dErr, int transp_mode) throw(cvmexception)
23388  {
23389  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.msize());
23390  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
23391  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
23392  mA._solve(mB, *this, dErr, nullptr, nullptr, transp_mode);
23393  return *this;
23394  }
23395 
23396  // helper for svd and divide&conquer methods
23397  basic_cmatrix _gels_sd(bool svd, const basic_cmatrix& mB, basic_rvector<TR>& sv,
23398  tint& rank, TR tol) const throw(cvmexception)
23399  {
23400  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
23401  _check_ne(CVM_SIZESMISMATCH, _cvm_min<tint>(this->msize(), this->nsize()), sv.size());
23402  basic_cmatrix mA(*this); // this algorithm overrides A
23403  basic_cmatrix mX;
23404  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
23405  if (svd) {
23406  __gelss(mA, mB, mX, tol, sv1, rank);
23407  } else {
23408  __gelsd(mA, mB, mX, tol, sv1, rank);
23409  }
23410  sv = sv1;
23411  return mX;
23412  }
23413 
23414  void _gels_sd(bool svd, const basic_cmatrix& mA, const basic_cmatrix& mB, basic_rvector<TR>& sv,
23415  tint& rank, TR tol) throw(cvmexception)
23416  {
23417  _check_ne(CVM_SIZESMISMATCH, this->msize(), mA.nsize());
23418  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mB.nsize());
23419  _check_ne(CVM_SIZESMISMATCH, mA.msize(), mB.msize());
23420  _check_ne(CVM_SIZESMISMATCH, _cvm_min<tint>(mA.msize(), mA.nsize()), sv.size());
23421  basic_cmatrix mA2(mA); // this algorithm overrides A
23422  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
23423  if (svd) {
23424  __gelss(mA2, mB, *this, tol, sv1, rank);
23425  } else {
23426  __gelsd(mA2, mB, *this, tol, sv1, rank);
23427  }
23428  sv = sv1;
23429  }
23430 
23431  basic_cvector<TR,TC> _gels_sd(bool svd, const basic_cvector<TR,TC>& vB, basic_rvector<TR>& sv,
23432  tint& rank, TR tol) const throw(cvmexception)
23433  {
23434  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
23435  _check_ne(CVM_SIZESMISMATCH, _cvm_min<tint>(this->msize(), this->nsize()), sv.size());
23436  basic_cmatrix mA(*this); // this algorithm overrides A
23437  basic_cmatrix mB(vB, vB.size(), 1);
23438  basic_cmatrix mX;
23439  basic_rvector<TR> sv1(sv.size()); // to ensure that incr=1
23440  if (svd) {
23441  __gelss(mA, mB, mX, tol, sv1, rank);
23442  } else {
23443  __gelsd(mA, mB, mX, tol, sv1, rank);
23444  }
23445  sv = sv1;
23446  const TC* pResult = mX;
23447  return basic_cvector<TR,TC>(pResult, mX.msize());
23448  }
23450 };
23451 
23452 
23459 template<typename TR, typename TC>
23460 class basic_scmatrix : public basic_cmatrix<TR,TC>, public SqMatrix<TR,TC>
23461 {
23462  typedef basic_cvector<TR,TC> CVector;
23463  typedef basic_array<TR,TC> BaseArray;
23464  typedef Matrix<TR,TC> BaseMatrix;
23465  typedef SqMatrix<TR,TC> BaseSqMatrix;
23467 
23468 public:
23494  {
23495  }
23496 
23523  explicit basic_scmatrix(tint nDim)
23524  : BaseCMatrix(nDim, nDim)
23525  {
23526  }
23527 
23559  basic_scmatrix(TC* pd, tint nDim)
23560  : BaseCMatrix(pd, nDim, nDim)
23561  {
23562  }
23563 
23596  basic_scmatrix(const TC* pd, tint nDim)
23597  : BaseCMatrix(pd, nDim, nDim)
23598  {
23599  }
23600 
23626  : BaseCMatrix(m.msize(), m.nsize(), m.msize(), false), BaseSqMatrix()
23627  {
23628  this->_massign(m);
23629  }
23630 
23649  : BaseCMatrix(std::move(m))
23650  {
23651  }
23652 
23684  : BaseCMatrix(m.msize(), m.nsize(), m.msize(), false)
23685  {
23686  _check_ne(CVM_SIZESMISMATCH, this->msize(), this->nsize());
23687  this->_massign(m);
23688  }
23689 
23713  explicit basic_scmatrix(const CVector& v)
23714  : BaseCMatrix(v.size(), v.size(), v.size(), true)
23715  {
23716  __copy<TC>(this->msize(), v, v.incr(), this->get(), this->msize() + 1);
23717  }
23718 
23746  explicit basic_scmatrix(const basic_srmatrix<TR>& m, bool bRealPart = true)
23747  : BaseCMatrix(m.msize(), m.msize(), m.msize(), true)
23748  {
23749  if (bRealPart) {
23750  __copy2<TR,TC>(this->get(), this->size(), this->incr(), m._pd(), nullptr);
23751  }
23752  else {
23753  __copy2<TR,TC>(this->get(), this->size(), this->incr(), nullptr, m._pd());
23754  }
23755  }
23756 
23793  basic_scmatrix(const TR* pRe, const TR* pIm, tint nDim)
23794  : BaseCMatrix(pRe, pIm, nDim, nDim)
23795  {
23796  }
23797 
23824  : BaseCMatrix(mRe.msize(), mRe.nsize(), mRe.msize(), false)
23825  {
23826  _check_ne(CVM_SIZESMISMATCH, mRe.msize(), mIm.msize());
23827  _check_ne(CVM_SIZESMISMATCH, mRe.nsize(), mIm.nsize());
23828  __copy2<TR,TC>(this->get(), this->size(), this->incr(), mRe, mIm, mRe.incr(), mIm.incr());
23829  }
23830 
23859  basic_scmatrix(BaseCMatrix& m, tint nRow, tint nCol, tint nDim)
23860  : BaseCMatrix(m, nRow, nCol, nDim, nDim)
23861  {
23862  m._check_submatrix();
23863  }
23864 
23865  type_proxy<TC, TR> operator () (tint nRow, tint nCol) throw(cvmexception)
23866  {
23867  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
23868  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
23869  return this->_ij_proxy_val(nRow - CVM0, nCol - CVM0);
23870  }
23871 
23872  TC operator () (tint nRow, tint nCol) const throw(cvmexception)
23873  {
23874  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
23875  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
23876  return this->_ij_val(nRow - CVM0, nCol - CVM0);
23877  }
23878 
23879  // returns column which is l-value
23880  CVector operator () (tint nCol) throw(cvmexception)
23881  {
23882  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
23883  return this->_col(nCol - CVM0);
23884  }
23885 
23886  // returns column which is NOT l-value
23887  const CVector operator () (tint nCol) const throw(cvmexception)
23888  {
23889  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
23890  return this->_col(nCol - CVM0);
23891  }
23892 
23893  // returns row which is l-value
23894  CVector operator [] (tint nRow) throw(cvmexception)
23895  {
23896  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
23897  return this->_row(nRow - CVM0);
23898  }
23899 
23900  // returns row which is NOT l-value
23901  const CVector operator [] (tint nRow) const throw(cvmexception)
23902  {
23903  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
23904  return this->_row(nRow - CVM0);
23905  }
23906 
23907  // real part
23908  const basic_srmatrix<TR> real() const
23909  {
23910  basic_srmatrix<TR> mRet(this->msize());
23911  __copy<TR>(this->size(), __get_real_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
23912  return mRet;
23913  }
23914 
23915  // imaginary part
23916  const basic_srmatrix<TR> imag() const
23917  {
23918  basic_srmatrix<TR> mRet(this->msize());
23919  __copy<TR>(this->size(), __get_imag_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
23920  return mRet;
23921  }
23922 
23952  basic_scmatrix& operator = (const basic_scmatrix& m) throw(cvmexception)
23953  {
23954  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
23955  this->_massign(m);
23956  return *this;
23957  }
23958 
23972  basic_scmatrix& operator = (basic_scmatrix&& m) throw(cvmexception)
23973  {
23974  // size check is in BaseCMatrix
23975  BaseCMatrix::operator = (std::move(m));
23976  return *this;
23977  }
23978 
23979  // assigns vector
23980  basic_scmatrix& assign(const CVector& v) throw(cvmexception)
23981  {
23982  _check_gt(CVM_SIZESMISMATCH_GT, this->size(), v.size());
23983  this->_assign(v, v.incr());
23984  return *this;
23985  }
23986 
23987  // assigns external array (nIncr = 1)
23988  basic_scmatrix& assign(const TC* pd)
23989  {
23990  this->_assign(pd, 1);
23991  return *this;
23992  }
23993 
24025  basic_scmatrix& assign(tint nRow, tint nCol, const BaseCMatrix& m) throw(cvmexception)
24026  {
24027  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
24028  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
24029  _check_gt(CVM_SIZESMISMATCH_GT, m.msize() + nRow - CVM0, this->msize());
24030  _check_gt(CVM_SIZESMISMATCH_GT, m.nsize() + nCol - CVM0, this->nsize());
24031  this->_assign_shifted(this->_sub_pointer_nocheck(nRow, nCol), m._pd(), m.msize(), m.nsize(), m.ld());
24032  return *this;
24033  }
24034 
24035  // fills the content
24036  basic_scmatrix& set(TC c)
24037  {
24038  this->_set(c);
24039  return *this;
24040  }
24041 
24066  basic_scmatrix& assign_real(const basic_srmatrix<TR>& mRe) throw(cvmexception)
24067  {
24068  _check_ne(CVM_SIZESMISMATCH, this->msize(), mRe.msize());
24069  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mRe.nsize());
24070  __copy_real<TR,TC>(this->get(), this->size(), this->incr(), mRe._pd(), mRe.incr());
24071  return *this;
24072  }
24073 
24098  basic_scmatrix& assign_imag(const basic_srmatrix<TR>& mIm) throw(cvmexception)
24099  {
24100  _check_ne(CVM_SIZESMISMATCH, this->msize(), mIm.msize());
24101  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mIm.nsize());
24102  __copy_imag<TR,TC>(this->get(), this->size(), this->incr(), mIm._pd(), mIm.incr());
24103  return *this;
24104  }
24105 
24106  // fills real part
24107  basic_scmatrix& set_real(TR d)
24108  {
24109  this->_set_real_number(d);
24110  return *this;
24111  }
24112 
24113  // fills imaginary part
24114  basic_scmatrix& set_imag(TR d)
24115  {
24116  this->_set_imag_number(d);
24117  return *this;
24118  }
24119 
24155  basic_scmatrix& resize(tint nNewDim) throw(cvmexception)
24156  {
24157  this->_resize2(nNewDim, nNewDim);
24158  return *this;
24159  }
24160 
24199  basic_scmatrix& operator << (const basic_scmatrix& m) throw(cvmexception)
24200  {
24201  this->_replace(m);
24202  this->_massign(m);
24203  return *this;
24204  }
24205 
24240  basic_scmatrix operator + (const basic_scmatrix& m) const throw(cvmexception)
24241  {
24242  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
24243  basic_scmatrix mSum(*this);
24244  mSum._mincr(m);
24245  return mSum;
24246  }
24247 
24281  basic_scmatrix operator - (const basic_scmatrix& m) const throw(cvmexception)
24282  {
24283  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
24284  basic_scmatrix mDiff(*this);
24285  mDiff._mdecr(m);
24286  return mDiff;
24287  }
24288 
24327  basic_scmatrix& sum(const basic_scmatrix& m1, const basic_scmatrix& m2) throw(cvmexception)
24328  {
24329  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
24330  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
24331  this->_msum(m1, m2);
24332  return *this;
24333  }
24334 
24373  basic_scmatrix& diff(const basic_scmatrix& m1, const basic_scmatrix& m2) throw(cvmexception)
24374  {
24375  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
24376  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
24377  this->_mdiff(m1, m2);
24378  return *this;
24379  }
24380 
24422  basic_scmatrix& operator += (const basic_scmatrix& m) throw(cvmexception)
24423  {
24424  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
24425  this->_mincr(m);
24426  return *this;
24427  }
24428 
24470  basic_scmatrix& operator -= (const basic_scmatrix& m) throw(cvmexception)
24471  {
24472  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
24473  this->_mdecr(m);
24474  return *this;
24475  }
24476 
24498  {
24499  static const TR mone(-1.);
24500  basic_scmatrix mRes(*this);
24501  mRes._scalr(mone);
24502  return mRes;
24503  }
24504 
24530  basic_scmatrix& operator ++ ()
24531  {
24532  this->_plus_plus();
24533  return *this;
24534  }
24535 
24561  basic_scmatrix operator ++ (int)
24562  {
24563  this->_plus_plus();
24564  return *this;
24565  }
24566 
24592  basic_scmatrix& operator -- ()
24593  {
24594  this->_minus_minus();
24595  return *this;
24596  }
24597 
24623  basic_scmatrix operator -- (int)
24624  {
24625  this->_minus_minus();
24626  return *this;
24627  }
24628 
24653  basic_scmatrix operator * (TR dMult) const
24654  {
24655  basic_scmatrix mRes(*this);
24656  mRes._scalr(dMult);
24657  return mRes;
24658  }
24659 
24686  basic_scmatrix operator / (TR dDiv) const throw(cvmexception)
24687  {
24688  basic_scmatrix mRes(*this);
24689  mRes._div(dDiv);
24690  return mRes;
24691  }
24692 
24717  basic_scmatrix operator * (TC cMult) const
24718  {
24719  basic_scmatrix mRes(*this);
24720  mRes._scalc(cMult);
24721  return mRes;
24722  }
24723 
24750  basic_scmatrix operator / (TC cDiv) const throw(cvmexception)
24751  {
24752  basic_scmatrix mRes(*this);
24753  mRes._div(cDiv);
24754  return mRes;
24755  }
24756 
24781  basic_scmatrix& operator *= (TR dMult)
24782  {
24783  this->_scalr(dMult);
24784  return *this;
24785  }
24786 
24813  basic_scmatrix& operator /= (TR dDiv)
24814  {
24815  this->_div(dDiv);
24816  return *this;
24817  }
24818 
24843  basic_scmatrix& operator *= (TC cMult)
24844  {
24845  this->_scalc(cMult);
24846  return *this;
24847  }
24848 
24875  basic_scmatrix& operator /= (TC cDiv)
24876  {
24877  this->_div(cDiv);
24878  return *this;
24879  }
24880 
24881  basic_scmatrix& normalize()
24882  {
24883  this->_normalize();
24884  return *this;
24885  }
24886 
24887 // 6.1: transposed (not conjugated) matrix
24923  basic_scmatrix operator !() const throw(cvmexception)
24924  {
24925  basic_scmatrix mRes(*this);
24926  return mRes.transpose();
24927  }
24928 
24966  basic_scmatrix operator ~() const throw(cvmexception)
24967  {
24968  basic_scmatrix mRes(*this);
24969  return mRes.conj();
24970  }
24971 
24972 // 6.1: this = transposed (not conjugated) (m)
25010  basic_scmatrix& transpose(const basic_scmatrix& m) throw(cvmexception)
25011  {
25012  (*this) = m;
25013  return this->transpose();
25014  }
25015 
25055  basic_scmatrix& conj(const basic_scmatrix& m) throw(cvmexception)
25056  {
25057  (*this) = m;
25058  return this->conj();
25059  }
25060 
25061 // 6.1: this = transposed (not conjugate) (this)
25098  basic_scmatrix& transpose() throw(cvmexception)
25099  {
25100  this->_transp();
25101  return *this;
25102  }
25103 
25142  basic_scmatrix& conj() throw(cvmexception)
25143  {
25144  this->_conj();
25145  return *this;
25146  }
25147 
25148  CVector operator * (const CVector& v) const throw(cvmexception) {
25149  return this->BaseCMatrix::operator * (v);
25150  }
25151 
25152 // special exclusion since matrix product is not commutative
25183  BaseCMatrix operator * (const BaseCMatrix& m) const throw(cvmexception) {
25184  return this->BaseCMatrix::operator * (m);
25185  }
25186 
25216  basic_scmatrix operator * (const basic_scmatrix& m) const throw(cvmexception)
25217  {
25218  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
25219  basic_scmatrix mRes(this->msize());
25220  mRes.mult(*this, m);
25221  return mRes;
25222  }
25223 
25258  basic_scmatrix& operator *= (const basic_scmatrix& m) throw(cvmexception)
25259  {
25260  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
25261  const basic_scmatrix mTmp(*this);
25262  this->mult(mTmp, m);
25263  return *this;
25264  }
25265 
25266  basic_scmatrix& swap_rows(tint n1, tint n2) throw(cvmexception)
25267  {
25268  this->_swap_rows(n1, n2);
25269  return *this;
25270  }
25271 
25272  basic_scmatrix& swap_cols(tint n1, tint n2) throw(cvmexception)
25273  {
25274  this->_swap_cols(n1, n2);
25275  return *this;
25276  }
25277 
25278 // linear solvers
25339  CVector solve(const CVector& vB, TR& dErr) const throw(cvmexception) {
25340  return _solve_helper(vB, dErr, 0);
25341  }
25342 
25343 // 6.1: transpose added
25408  CVector solve_tran(const CVector& vB, TR& dErr) const throw(cvmexception) {
25409  return _solve_helper(vB, dErr, 1);
25410  }
25411 
25412 // 6.1: conjugate added
25477  CVector solve_conj(const CVector& vB, TR& dErr) const throw(cvmexception) {
25478  return _solve_helper(vB, dErr, 2);
25479  }
25480 
25536  CVector solve(const CVector& vB) const throw(cvmexception)
25537  {
25538  static TR dErr(0.);
25539  return this->solve(vB, dErr);
25540  }
25541 
25542 // 6.1: transpose added
25603  CVector solve_tran(const CVector& vB) const throw(cvmexception)
25604  {
25605  static TR dErr(0.);
25606  return this->solve_tran(vB, dErr);
25607  }
25608 
25609 // 6.1: conjugate added
25670  CVector solve_conj(const CVector& vB) const throw(cvmexception)
25671  {
25672  static TR dErr(0.);
25673  return this->solve_conj(vB, dErr);
25674  }
25675 
25735  BaseCMatrix solve(const BaseCMatrix& mB, TR& dErr) const throw(cvmexception) {
25736  return _solve_helper(mB, dErr, 0);
25737  }
25738 
25739 // 6.1: transpose added
25804  BaseCMatrix solve_tran(const BaseCMatrix& mB, TR& dErr) const throw(cvmexception) {
25805  return _solve_helper(mB, dErr, 1);
25806  }
25807 
25808 // 6.1: conjugate added
25873  BaseCMatrix solve_conj(const BaseCMatrix& mB, TR& dErr) const throw(cvmexception) {
25874  return _solve_helper(mB, dErr, 2);
25875  }
25876 
25932  BaseCMatrix solve(const BaseCMatrix& mB) const throw(cvmexception)
25933  {
25934  static TR dErr(0.);
25935  return this->solve(mB, dErr);
25936  }
25937 
25938 // 6.1: transpose added
26000  BaseCMatrix solve_tran(const BaseCMatrix& mB) const throw(cvmexception)
26001  {
26002  static TR dErr(0.);
26003  return this->solve_tran(mB, dErr);
26004  }
26005 
26006 // 6.1: conjugate added
26068  BaseCMatrix solve_conj(const BaseCMatrix& mB) const throw(cvmexception)
26069  {
26070  static TR dErr(0.);
26071  return this->solve_conj(mB, dErr);
26072  }
26073 
26074 // 6.1: reversed MATLAB-style operator B/A returning solution of X*A=B equation
26108  CVector operator % (const CVector& vB) const throw(cvmexception) {
26109  return vB / (*this);
26110  }
26111 
26112 // 6.1: reversed vector operator % returns solution of A*X=B equation
26146  CVector operator / (const CVector& vB) const throw(cvmexception) {
26147  return vB % (*this);
26148  }
26149 
26234  CVector solve_lu(const basic_scmatrix& mLU, const tint* pPivots,
26235  const CVector& vB, TR& dErr) const throw(cvmexception)
26236  {
26237  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
26238  _check_ne(CVM_SIZESMISMATCH, this->msize(), mLU.msize());
26239  CVector vX(this->msize());
26240  this->_solve(vB, vX, dErr, mLU, pPivots, 0);
26241  return vX;
26242  }
26243 
26326  CVector solve_lu(const basic_scmatrix& mLU, const tint* pPivots, const CVector& vB) const throw(cvmexception)
26327  {
26328  static TR dErr(0.);
26329  return this->solve_lu(mLU, pPivots, vB, dErr);
26330  }
26331 
26415  BaseCMatrix solve_lu(const basic_scmatrix& mLU, const tint* pPivots,
26416  const BaseCMatrix& mB, TR& dErr) const throw(cvmexception)
26417  {
26418  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
26419  _check_ne(CVM_SIZESMISMATCH, this->msize(), mLU.msize());
26420  BaseCMatrix mX(mB.msize(), mB.nsize());
26421  this->_solve(mB, mX, dErr, mLU, pPivots, 0);
26422  return mX;
26423  }
26424 
26506  BaseCMatrix solve_lu(const basic_scmatrix& mLU, const tint* pPivots, const BaseCMatrix& mB) const throw(cvmexception)
26507  {
26508  static TR dErr(0.);
26509  return this->solve_lu(mLU, pPivots, mB, dErr);
26510  }
26511 
26541  TC det() const throw(cvmexception) {
26542  return this->_det();
26543  }
26544 
26622  basic_scmatrix& low_up(const basic_scmatrix& m, tint* nPivots) throw(cvmexception)
26623  {
26624  (*this) = m;
26625  this->_low_up(nPivots);
26626  return *this;
26627  }
26628 
26704  basic_scmatrix low_up(tint* nPivots) const throw(cvmexception)
26705  {
26706  basic_scmatrix mRes(*this);
26707  mRes._low_up(nPivots);
26708  return mRes;
26709  }
26710 
26753  TR cond() const throw(cvmexception)
26754  {
26755  TR dCondNum(0.);
26756  __cond_num<TR,basic_scmatrix>(*this, dCondNum); // universal method, no need to virtualize
26757  return dCondNum;
26758  }
26759 
26802  basic_scmatrix& inv(const basic_scmatrix& m) throw(cvmexception)
26803  {
26804  __inv<basic_scmatrix>(*this, m);
26805  return *this;
26806  }
26807 
26849  basic_scmatrix inv() const throw(cvmexception)
26850  {
26851  basic_scmatrix mRes(this->msize());
26852  __inv<basic_scmatrix>(mRes, *this);
26853  return mRes;
26854  }
26855 
26927  basic_scmatrix& exp(const basic_scmatrix& m, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
26928  {
26929  __exp<basic_scmatrix, TR>(*this, m, tol);
26930  return *this;
26931  }
26932 
27002  basic_scmatrix exp(TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
27003  {
27004  basic_scmatrix mRes(this->msize());
27005  __exp<basic_scmatrix, TR>(mRes, *this, tol);
27006  return mRes;
27007  }
27008 
27009 // this = v(1)*I + v(2)*m + v(3)*m^2 + ... + v(N)*m^(N-1)
27088  basic_scmatrix& polynom(const basic_scmatrix& m, const CVector& v) throw(cvmexception)
27089  {
27090  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
27091  CVector v1;
27092  if (v.incr() > 1) v1 << v; // to make sure incr = 1
27093  __polynom<TC, CVector>(this->get(), this->ld(), this->msize(), m._pd(), m._ldm(), v.incr() > 1 ? v1 : v);
27094  return *this;
27095  }
27096 
27097 // returns v(1)*I + v(2)*this + v(3)*this^2 + ... + v(N)*this^(N-1)
27175  basic_scmatrix polynom(const CVector& v) const
27176  {
27177  basic_scmatrix mRes(this->msize());
27178  CVector v1;
27179  if (v.incr() > 1) v1 << v; // to make sure incr = 1
27180  __polynom<TC, CVector>(mRes.get(), mRes.ld(), this->msize(), this->get(), this->ld(), v.incr() > 1 ? v1 : v);
27181  return mRes;
27182  }
27183 
27242  CVector eig(basic_scmatrix& mEigVect, bool bRightVect = true) const throw(cvmexception)
27243  {
27244  CVector vEig(this->msize());
27245  this->_eig(vEig, &mEigVect, bRightVect);
27246  return vEig;
27247  }
27248 
27286  CVector eig() const throw(cvmexception)
27287  {
27288  CVector vEig(this->msize());
27289  this->_eig(vEig, nullptr, false);
27290  return vEig;
27291  }
27292 
27338  basic_scmatrix& cholesky(const basic_schmatrix<TR,TC>& m) throw(cvmexception)
27339  {
27340  this->_check_cholesky(); // doesn't work for band matrices
27341  *this = m;
27342  tint nOutInfo = __cholesky<basic_scmatrix>(*this);
27343  _check_negative(CVM_WRONGMKLARG, nOutInfo);
27344  _check_positive(CVM_NOTPOSITIVEDEFINITE, nOutInfo);
27345  this->_clean_low_triangle();
27346  return *this;
27347  }
27348 
27378  basic_scmatrix& bunch_kaufman(const basic_schmatrix<TR,TC>& m, tint* nPivots) throw(cvmexception)
27379  {
27380  this->_check_bunch_kaufman(); // doesn't work for band matrices
27381  *this = m;
27382  __bunch_kaufman<basic_scmatrix>(*this, nPivots);
27383  return *this;
27384  }
27385 
27414  void qr(basic_scmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mR) const throw(cvmexception) {
27415  this->_qr_ss(mQ, mR);
27416  }
27417 
27446  void lq(basic_scmatrix<TR,TC>& mL, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception) {
27447  this->_lq_ss(mL, mQ);
27448  }
27449 
27478  void ql(basic_scmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mL) const throw(cvmexception) {
27479  this->_ql_ss(mQ, mL);
27480  }
27481 
27510  void rq(basic_scmatrix<TR,TC>& mR, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception) {
27511  this->_rq_ss(mR, mQ);
27512  }
27513 
27539  basic_scmatrix& identity()
27540  {
27541  this->_vanish();
27542  this->_plus_plus();
27543  return *this;
27544  }
27545 
27573  basic_scmatrix& vanish()
27574  {
27575  this->_vanish();
27576  return *this;
27577  }
27578 
27579  basic_scmatrix& randomize_real(TR dFrom, TR dTo)
27580  {
27581  this->_randomize_real(dFrom, dTo);
27582  return *this;
27583  }
27584 
27585  basic_scmatrix& randomize_imag(TR dFrom, TR dTo)
27586  {
27587  this->_randomize_imag(dFrom, dTo);
27588  return *this;
27589  }
27590 
27592  virtual void _eig(CVector& vEig, basic_scmatrix<TR,TC>* mEigVect, bool bRightVect) const throw(cvmexception)
27593  {
27594  __eig<CVector, basic_scmatrix, basic_scmatrix>(vEig, *this, mEigVect, bRightVect);
27595  }
27596 
27597  virtual void _solve(const CVector& vB, CVector& vX,
27598  TR& dErr, const TC* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception)
27599  {
27600  vX = vB;
27601  CVector vB1;
27602  CVector vX1;
27603  if (vB.incr() > 1) vB1 << vB; // to make sure incr = 1
27604  if (vX.incr() > 1) vX1 << vX;
27605  __solve<TR,TC, basic_scmatrix>(*this, 1, vB.incr() > 1 ? vB1 : vB, vB.size(), vX.incr() > 1 ? vX1 : vX, vX.size(),
27606  dErr, pLU, pPivots, transp_mode);
27607  if (vX.incr() > 1) vX = vX1;
27608  }
27609 
27610  virtual void _solve(const BaseCMatrix& mB, BaseCMatrix& mX,
27611  TR& dErr, const TC* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception)
27612  {
27613  mX = mB;
27614  __solve<TR,TC, basic_scmatrix>(*this, mB.nsize(), mB, mB.ld(), mX, mX.ld(), dErr, pLU, pPivots, transp_mode);
27615  }
27616 
27617  virtual const TC* _pv() const override {return this->get(); }
27618  virtual TC* _pv() override {return this->get(); }
27619 
27620 protected:
27621  // protected constructors for inherited stuff
27622  basic_scmatrix(tint nDim, tint nLD, bool bZeroMemory)
27623  : BaseCMatrix(nDim, nDim, nLD, bZeroMemory)
27624  {
27625  }
27626 
27627  basic_scmatrix(tint size, tint incr, tint msize, tint nsize, tint ld)
27628  : BaseCMatrix(size, incr, msize, nsize, ld)
27629  {
27630  }
27631 
27632  // non-const version shares memory
27633  basic_scmatrix(TC* pd, tint nDim, tint nLD, tint nSize)
27634  : BaseCMatrix(pd, nDim, nDim, nLD, nSize)
27635  {
27636  }
27637 
27638  // const version makes a copy
27639  basic_scmatrix(const TC* pd, tint nDim, tint nLD, tint nSize)
27640  : BaseCMatrix(pd, nDim, nDim, nLD, nSize)
27641  {
27642  }
27643 
27644  tint _size() const override {return this->size();}
27645  tint _msize() const override {return this->msize();}
27646  tint _nsize() const override {return this->nsize();}
27647  tint _ld() const override {return this->ld();}
27648 
27649  // returns diagonal which IS l-value (shares memory)
27650  // 0 - main, negative - low, positive - up
27651  CVector _diag(tint nDiag) throw(cvmexception) override
27652  {
27653  const tint nD = _abs(nDiag);
27654  _check_ge(CVM_INDEX_GE, nD, this->msize());
27655  return CVector(this->get() + (nDiag > 0 ? nDiag * this->ld() : nD), this->msize() - nD, this->ld() + 1);
27656  }
27657 
27658  // returns diagonal which IS NOT l-value (creates a copy)
27659  // 0 - main, negative - low, positive - up
27660  const CVector _diag(tint nDiag) const throw(cvmexception) override
27661  {
27662  const tint nD = _abs(nDiag);
27663  _check_ge(CVM_INDEX_GE, nD, this->msize());
27664  return CVector(this->get() + (nDiag > 0 ? nDiag * this->ld() : nD), this->msize() - nD, this->ld() + 1);
27665  }
27666 
27667  // returns main diagonal of low_up factorization
27668  virtual CVector _low_up_diag(basic_array<tint,tint>& naPivots) const throw(cvmexception)
27669  {
27670  // let temp matrix be const to get a copy of its main diagonal
27671  const basic_scmatrix lu = this->low_up(naPivots);
27672  return lu.diag(0);
27673  }
27674 
27675  virtual void _transp() {
27676  this->_sq_transp();
27677  }
27678 
27679  // 6.1: it's reused in scb, overridden in sch
27680  virtual void _conj()
27681  {
27682  this->_transp();
27683  __conj<TC>(this->get(), this->size(), this->incr());
27684  }
27685 
27686  virtual void _plus_plus() {
27687  this->_sq_plus_plus();
27688  }
27689 
27690  virtual void _minus_minus() {
27691  this->_sq_minus_minus();
27692  }
27693 
27694  virtual TC _det() const throw(cvmexception)
27695  {
27696  TC cDet(0.);
27697  switch (this->msize()) {
27698  case 0:
27699  break;
27700  case 1:
27701  cDet = this->_ij_val(0, 0);
27702  break;
27703  case 2:
27704  cDet = this->_ij_val(0, 0) * this->_ij_val(1, 1) -
27705  this->_ij_val(1, 0) * this->_ij_val(0, 1);
27706  break;
27707  default:
27708  try {
27709  static const TC one(1., 0.);
27710  basic_array<tint,tint> naPivots(this->msize());
27711  CVector vUpDiag = this->_low_up_diag(naPivots);
27712 
27713  cDet = one;
27714  for (tint i = CVM0; i <= this->msize() - (1 - CVM0); ++i) {
27715  cDet *= vUpDiag[i];
27716  if (i + (1 - CVM0) != naPivots[i]) {
27717  cDet = -cDet;
27718  }
27719  }
27720  }
27721  catch (const cvmexception& e) {
27722  if (e.cause() != CVM_SINGULARMATRIX) throw e;
27723  }
27724  break;
27725  }
27726  return cDet;
27727  }
27728 
27729  virtual void _low_up(tint* nPivots) throw(cvmexception) {
27730  __low_up<basic_scmatrix>(*this, nPivots);
27731  }
27732 
27733  // QR - "economy" mode
27734  void _qr_ss(basic_scmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mR) const throw(cvmexception)
27735  {
27736  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
27737  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
27738  __qre<basic_cmatrix<TR,TC>, basic_scmatrix<TR,TC> >(*this, mQ, mR);
27739  }
27740 
27741  // RQ - "economy" mode
27742  void _rq_ss(basic_scmatrix<TR,TC>& mR, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception)
27743  {
27744  _check_ne(CVM_SIZESMISMATCH, this->msize(), mR.msize());
27745  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
27746  __rqe<basic_cmatrix<TR,TC>, basic_scmatrix<TR,TC> >(*this, mR, mQ);
27747  }
27748 
27749  // LQ - "economy" mode
27750  void _lq_ss(basic_scmatrix<TR,TC>& mL, basic_scmatrix<TR,TC>& mQ) const throw(cvmexception)
27751  {
27752  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
27753  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
27754  __lqe<basic_cmatrix<TR,TC>, basic_scmatrix<TR,TC> >(*this, mL, mQ);
27755  }
27756 
27757  // QL - "economy" mode
27758  void _ql_ss(basic_scmatrix<TR,TC>& mQ, basic_scmatrix<TR,TC>& mL) const throw(cvmexception)
27759  {
27760  _check_ne(CVM_SIZESMISMATCH, this->msize(), mQ.msize());
27761  _check_ne(CVM_SIZESMISMATCH, this->msize(), mL.msize());
27762  __qle<basic_cmatrix<TR,TC>, basic_scmatrix<TR,TC> >(*this, mQ, mL);
27763  }
27764 
27765  virtual void _check_cholesky() { }
27766  virtual void _check_bunch_kaufman() { }
27767 
27768 private:
27769  CVector _solve_helper(const CVector& vB, TR& dErr, int transp_mode) const throw(cvmexception)
27770  {
27771  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
27772  CVector vX(this->msize());
27773  this->_solve(vB, vX, dErr, nullptr, nullptr, transp_mode);
27774  return vX;
27775  }
27776 
27777  BaseCMatrix _solve_helper(const BaseCMatrix& mB, TR& dErr, int transp_mode) const throw(cvmexception)
27778  {
27779  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
27780  BaseCMatrix mX(mB.msize(), mB.nsize());
27781  this->_solve(mB, mX, dErr, nullptr, nullptr, transp_mode);
27782  return mX;
27783  }
27785 };
27786 
27787 
27810 template<typename TR, typename TC>
27812 {
27813 protected:
27816 
27819  : mkl(0),
27820  mku(0)
27821  {
27822  }
27823 
27826  : mkl(nKL),
27827  mku(nKU)
27828  {
27829  }
27830 
27832  virtual ~BandMatrix()
27833  {
27834  }
27835 
27837  virtual tint _size() const = 0;
27838  virtual tint _msize() const = 0;
27839  virtual tint _nsize() const = 0;
27840  virtual tint _ld() const = 0;
27841  virtual void _set_p(TC* pf) = 0;
27842  virtual void _set(TC* pf, tint nSize, tint nM, tint nN, tint nIncr, tint nLD) = 0;
27843 
27844  // it's the same as get, but let's keep get not virtual for performance sake
27845  virtual const TC* _pb() const = 0;
27846  virtual TC* _pb() = 0;
27847 
27848 #ifdef CVM_USE_POOL_MANAGER
27849  void _bresize(tint nNewM) throw(cvmexception)
27850 #else
27851  void _bresize(std::shared_ptr<TC>& mp, tint nNewM)throw (cvmexception)
27852 #endif
27853  {
27854  const tint mm = this->_msize();
27855  const tint nSize = this->_size();
27856  if (nNewM != mm) {
27857  _check_lt(CVM_WRONGSIZE_LT, nNewM, TINT_ZERO);
27858  const tint nNewSize = nNewM * (1 + this->lsize() + this->usize());
27859  TC* pd = cvmMalloc<TC>(nNewSize);
27860  if (nNewSize > nSize) cvmZeroMemory<TC>(pd, nNewSize);
27861  const tint nMinSize = _cvm_min<tint>(nSize, nNewSize);
27862  if (nMinSize > 0) {
27863  __copy<TC>(nMinSize, this->_pb(), 1, pd, 1);
27864  CVM_ASSERT(pd, nNewSize * sizeof(TC))
27865  }
27866 #ifdef CVM_USE_POOL_MANAGER
27867  TC* pB = this->_pb();
27868  cvmFree<TC>(pB);
27869  this->_set(pd, nNewSize, nNewM, nNewM, 1, nNewSize > 0 ? 1 + this->lsize() + this->usize() : 0);
27870 #else
27871  mp.reset(pd, ArrayDeleter<TC>());
27872  this->_set(nullptr, nNewSize, nNewM, nNewM, 1, nNewSize > 0 ? 1 + this->lsize() + this->usize() : 0);
27873 #endif
27874  }
27875  }
27876 
27877  void _check_dimensions() const throw(cvmexception)
27878  {
27879  _check_lt(CVM_WRONGSIZE_LT, this->lsize(), TINT_ZERO);
27880  _check_lt(CVM_WRONGSIZE_LT, this->usize(), TINT_ZERO);
27881  }
27882 
27883  void _check_dimensions(const BandMatrix& m) const throw(cvmexception) {
27884  _check_ne(CVM_SIZESMISMATCH, this->_msize(), m._msize());
27885  _check_ne(CVM_SIZESMISMATCH, this->lsize(), m.lsize());
27886  _check_ne(CVM_SIZESMISMATCH, this->usize(), m.usize());
27887  }
27888 
27889  bool _bcontinuous() const {
27890  return this->_msize() == 0 || this->_ld() == 1 + this->lsize() + this->usize();
27891  }
27892 
27893  // m is a band matrix here
27894  void _mbassign(const Matrix<TR,TC>& m)
27895  {
27896  TC* pd = _pb();
27897  if (pd != m.get()) {
27898  __copy<TC>(this->_size(), m, m.incr(), pd, 1);
27899  }
27900  }
27901 
27902  // fills the content, doesn't touch head and tail
27903  void _b_for_each(TC d, bool bRandom, bool bReal, TR dFrom, TR dTo)
27904  {
27905  tint i, jc, ju, jl;
27906  const tint nCol = 1 + this->lsize() + this->usize();
27907  TC* pB = _pb();
27908  const tint mn = this->_nsize();
27909  for (tint j = 0; j < mn; ++j) {
27910  jc = j * nCol;
27911  ju = this->usize() - j;
27912  jl = ju + mn;
27913  for (i = 0; i < nCol; ++i) {
27914  if (i >= ju && i < jl) {
27915  CVM_ASSERT(pB, (jc + i + 1) * sizeof(TC))
27916  if (bRandom) {
27917  TR* pd = bReal ? __get_real_p<TR>(pB + (jc + i)) : __get_imag_p<TR>(pB + (jc + i));
27918  *pd = Randomizer<TR>::get(dFrom, dTo);
27919  } else {
27920  pB[jc + i] = d;
27921  }
27922  }
27923  }
27924  }
27925  }
27926 
27927  // fills the content, doesn't touch head and tail
27928  void _bset(TC d)
27929  {
27930  static const TR zero = TR(0.);
27931  this->_b_for_each(d, false, false, zero, zero);
27932  }
27933 
27934  // fills the content, doesn't touch head and tail
27935  void _b_randomize(bool bReal, TR dFrom, TR dTo)
27936  {
27937  static const TC zero(0.);
27938  this->_b_for_each(zero, true, bReal, dFrom, dTo);
27939  }
27940 
27941  // 1-norm
27942  TR _bnorm1() const
27943  {
27944  tint i, j;
27945  tint nLen = 0;
27946  tint nShift = 0;
27947  TR rNorm = TR(0.);
27948  TR rSum;
27949  const tint mn = this->_nsize();
27950  basic_array<TR,TC> rv(this->_msize());
27951 
27952  for (j = 0; j < mn; ++j) {
27953  rSum = TR(0.);
27954  this->_get_col(j, rv, 1, &nLen, &nShift);
27955 
27956  nLen += nShift;
27957  for (i = nShift + 1; i <= nLen; ++i) {
27958  rSum += _abs(rv[i - (1 - CVM0)]);
27959  }
27960 
27961  if (rSum > rNorm) {
27962  rNorm = rSum;
27963  }
27964  }
27965  return rNorm;
27966  }
27967 
27968  // infinity-norm
27969  TR _bnorminf() const
27970  {
27971  tint i, j;
27972  tint nLen = 0;
27973  tint nShift = 0;
27974  TR rNorm = TR(0.);
27975  TR rSum;
27976  const tint mm = this->_msize();
27977  basic_array<TR,TC> rv(this->_nsize());
27978 
27979  for (i = 0; i < mm; ++i) {
27980  rSum = TR(0.);
27981  this->_get_row(i, rv, 1, &nLen, &nShift);
27982 
27983  nLen += nShift;
27984  for (j = nShift + 1; j <= nLen; ++j) {
27985  rSum += _abs(rv[j - (1 - CVM0)]);
27986  }
27987 
27988  if (rSum > rNorm) {
27989  rNorm = rSum;
27990  }
27991  }
27992  return rNorm;
27993  }
27994 
27995  void _bvanish() {
27996  this->_bset(TC(0.));
27997  }
27998 
27999  // zero based
28000  type_proxy<TC, TR> _b_ij_proxy_val(tint i, tint j)
28001  {
28002  static const TC zero = TC(0.);
28003  TC* pd = _pb();
28004  const tint nA = j - this->usize();
28005  CVM_ASSERT(pd, (i + j * (1 + this->lsize() + this->usize()) - nA + 1) * sizeof(TC))
28006  return(nA < 0 || i >= nA) && i <= this->lsize() + j ? type_proxy<TC, TR>(pd[i + j * (1 + this->lsize() + this->usize()) - nA], false) :
28007  type_proxy<TC, TR>(zero, true);
28008  }
28009 
28010  // zero based
28011  TC _b_ij_val(tint i, tint j) const
28012  {
28013  static const TC zero = TC(0.);
28014  const TC* pd = _pb();
28015  const tint nA = j - this->usize();
28016  CVM_ASSERT(pd, (i + j * (1 + this->lsize() + this->usize()) - nA + 1) * sizeof(TC))
28017  return(nA < 0 || i >= nA) && i <= this->lsize() + j ? pd[i + j * (1 + this->lsize() + this->usize()) - nA] : zero;
28018  }
28019 
28020  void _get_col(tint i, TC* pCol, tint nIncr, tint* pnLen = nullptr, tint* pnShift = nullptr) const
28021  {
28022  const TC* pd = _pb();
28023  const tint mm = this->_msize();
28024  const tint mn = this->_nsize();
28025  const tint nCol = 1 + this->lsize() + this->usize();
28026  tint nS = nCol;
28027  tint nShiftSrc = 0;
28028  tint nShiftDest = 0;
28029 
28030  if (i > this->usize()) {
28031  nShiftDest = i - this->usize();
28032  } else {
28033  nShiftSrc = this->usize() - i;
28034  nS -= nShiftSrc;
28035  }
28036 
28037  if (mm - i <= this->lsize()) {
28038  nS -= this->lsize() + 1 - (mn - i);
28039  }
28040 
28041  __copy<TC>(nS,
28042  pd + i * nCol + nShiftSrc,
28043  1,
28044  pCol + nShiftDest,
28045  nIncr);
28046 
28047  if (pnLen) *pnLen = nS;
28048  if (pnShift) *pnShift = nShiftDest;
28049  }
28050 
28051  void _get_row(tint i, TC* pCol, tint nIncr, tint* pnLen = nullptr, tint* pnShift = nullptr) const
28052  {
28053  const TC* pd = _pb();
28054  const tint mm = this->_msize();
28055  const tint mn = this->_nsize();
28056  const tint nCol = this->lsize() + this->usize();
28057  tint nS = mn;
28058  tint nShiftSrc = i + this->usize();
28059  tint nShiftDest = 0;
28060 
28061  if (i > this->lsize()) {
28062  nShiftDest = i - this->lsize();
28063  nShiftSrc += nShiftDest * nCol;
28064  nS -= nShiftDest;
28065  }
28066  if (mn - i > this->usize()) {
28067  nS -= (mm - i) - this->usize() - 1;
28068  }
28069 
28070  __copy<TC>(nS,
28071  pd + nShiftSrc,
28072  nCol,
28073  pCol + nShiftDest,
28074  nIncr);
28075 
28076  if (pnLen) *pnLen = nS;
28077  if (pnShift) *pnShift = nShiftDest;
28078  }
28079 
28080 // matrix replacement, no assignment
28081 #ifdef CVM_USE_POOL_MANAGER
28082  void _btransp() throw(cvmexception)
28083 #else
28084  void _btransp(std::shared_ptr<TC>& mp)throw (cvmexception)
28085 #endif
28086  {
28087  TC* mpd = _pb();
28088  const tint mn = this->_nsize();
28089  if (this->lsize() > 0 || this->usize() > 0) {
28090  const tint nLU = this->lsize() + this->usize();
28091  const tint nCol = 1 + nLU;
28092  const tint nEls = nCol * mn;
28093  tint nS, nShiftSrc;
28094  TC* pL;
28095  TC* pR;
28096  TC* pd = cvmMalloc<TC>(nEls);
28097  cvmZeroMemory(pd, nEls);
28098 
28099  for (tint i = 0; i < mn; ++i) {
28100  nS = nCol;
28101  nShiftSrc = 0;
28102 
28103  if (i < this->usize()) {
28104  nShiftSrc = this->usize() - i;
28105  nS -= nShiftSrc;
28106  }
28107  if (mn - i <= this->lsize()) {
28108  nS -= this->lsize() + 1 - (mn - i);
28109  }
28110 
28111  pL = mpd + i * nCol + nShiftSrc;
28112  pR = pd + (i > this->usize() ? (i - this->usize() + 1) * nCol - 1 : this->lsize() + i);
28113 
28114  __copy<TC>(nS, pL, 1, pR, nLU);
28115  }
28116  std::swap(mkl, mku);
28117 #ifdef CVM_USE_POOL_MANAGER
28118  cvmFree<TC>(mpd);
28119  this->_set_p(pd);
28120 #else
28121  mp.reset(pd, ArrayDeleter<TC>());
28122  this->_set_p(nullptr);
28123 #endif
28124  }
28125  }
28126 
28127  void _b_plus_plus()
28128  {
28129  TC* pd = _pb();
28130  static const TC one(1.);
28131  const tint mn = this->_nsize();
28132  const tint nNext = 1 + this->lsize() + this->usize();
28133  const tint nSize = nNext * mn;
28134  CVM_ASSERT(pd, nSize * sizeof(TC))
28135  for (tint i = this->usize(); i < nSize; i += nNext) {
28136  pd[i] += one;
28137  }
28138  }
28139 
28140  void _b_minus_minus()
28141  {
28142  TC* pd = _pb();
28143  static const TC one(1.);
28144  const tint mn = this->_nsize();
28145  const tint nNext = 1 + this->lsize() + this->usize();
28146  const tint nSize = nNext * mn;
28147  CVM_ASSERT(pd, nSize * sizeof(TC))
28148  for (tint i = this->usize(); i < nSize; i += nNext) {
28149  pd[i] -= one;
28150  }
28151  }
28152 
28153  // matrix replacement, no assignment
28154 #ifdef CVM_USE_POOL_MANAGER
28155  void _b_replace(const BandMatrix& m) throw(cvmexception)
28156 #else
28157  void _b_replace(std::shared_ptr<TC>& mp, const BandMatrix& m) throw(cvmexception)
28158 #endif
28159  {
28160 #ifdef CVM_USE_POOL_MANAGER
28161  TC* pB = _pb();
28162  cvmFree<TC>(pB);
28163 #endif
28164  tint nSize = m._size();
28165  TC* pd = cvmMalloc<TC>(nSize);
28166  CVM_ASSERT(pd, (nSize * sizeof(TC)))
28167  mkl = m.lsize();
28168  mku = m.usize();
28169 #ifdef CVM_USE_POOL_MANAGER
28170  this->_set(pd, nSize, m._msize(), m._nsize(), 1, m._ld());
28171 #else
28172  mp.reset(pd, ArrayDeleter<TC>());
28173  this->_set(nullptr, nSize, m._msize(), m._nsize(), 1, m._ld());
28174 #endif
28175  }
28176 
28177 #ifdef CVM_USE_POOL_MANAGER
28178  void _resize_lu(tint nNewKL, tint nNewKU) throw(cvmexception)
28179 #else
28180  void _resize_lu(std::shared_ptr<TC>& mp, tint nNewKL, tint nNewKU) throw(cvmexception)
28181 #endif
28182  {
28183  if (nNewKL != this->lsize() || nNewKU != this->usize()) {
28184  if (this->lsize() < 0) throw cvmexception(CVM_WRONGSIZE, this->lsize());
28185  if (this->usize() < 0) throw cvmexception(CVM_WRONGSIZE, this->usize());
28186  TC* pB = _pb();
28187  const tint mm = this->_msize();
28188  const tint mn = this->_nsize();
28189  const tint nOldLD = 1 + this->lsize() + this->usize();
28190  const tint nNewLD = 1 + nNewKL + nNewKU;
28191  const tint nMinKL = _cvm_min<tint>(this->lsize(), nNewKL);
28192  const tint nMinKU = _cvm_min<tint>(this->usize(), nNewKU);
28193  const tint nNewSize = mn * (1 + nNewKL + nNewKU);
28194  TC* pd = cvmMalloc<TC>(nNewSize);
28195  CVM_ASSERT(pd, nNewSize * sizeof(TC))
28196  cvmZeroMemory<TC>(pd, nNewSize);
28197  for (tint i = -nMinKU; i <= nMinKL; ++i) {
28198  __copy<TC>(mn, pB + (this->usize() + i), nOldLD, pd + (nNewKU + i), nNewLD);
28199  }
28200  mkl = nNewKL;
28201  mku = nNewKU;
28202 #ifdef CVM_USE_POOL_MANAGER
28203  cvmFree<TC>(pB);
28204  this->_set(pd, nNewSize, mm, mn, 1, nNewLD);
28205 #else
28206  mp.reset(pd, ArrayDeleter<TC>());
28207  this->_set(nullptr, nNewSize, mm, mn, 1, nNewLD);
28208 #endif
28209  }
28210  }
28212 
28213 public:
28237  tint lsize() const {
28238  return mkl;
28239  }
28240 
28264  tint usize() const {
28265  return mku;
28266  }
28267 
28269  const tint* _pl() const {
28270  return&mkl;
28271  }
28272 
28273  const tint* _pu() const {
28274  return&mku;
28275  }
28277 };
28278 
28279 
28308 template<typename TR>
28309 class basic_srbmatrix : public basic_srmatrix<TR>, public BandMatrix<TR,TR>
28310 {
28311  typedef std::complex<TR> TC;
28312  typedef basic_rvector<TR> RVector;
28313  typedef basic_cvector<TR,TC> CVector;
28314  typedef basic_array<TR,TR> BaseArray;
28315  typedef Matrix<TR,TR> BaseMatrix;
28316  typedef basic_rmatrix<TR> BaseRMatrix;
28319 
28320  friend class basic_scbmatrix<TR,TC>; // basic_scbmatrix constructor
28321 
28322 protected:
28323  mutable BaseSRMatrix mSM;
28324 
28325 public:
28350  : mSM()
28351  {
28352  }
28353 
28379  explicit basic_srbmatrix(tint nDim)
28380  : BaseSRMatrix(nDim, 1, true),
28381  BaseBandMatrix(0, 0)
28382  {
28383  }
28384 
28415  basic_srbmatrix(tint nDim, tint nKL, tint nKU)
28416  : BaseSRMatrix(nDim, 1 + nKL + nKU, true),
28417  BaseBandMatrix(nKL, nKU), mSM()
28418  {
28419  this->_check_dimensions();
28420  }
28421 
28464  basic_srbmatrix(TR* pd, tint nDim, tint nKL, tint nKU)
28465  : BaseSRMatrix(pd, nDim, 1 + nKL + nKU, nDim * (1 + nKL + nKU)),
28466  BaseBandMatrix(nKL, nKU), mSM()
28467  {
28468  this->_check_dimensions();
28469  }
28470 
28513  basic_srbmatrix(const TR* pd, tint nDim, tint nKL, tint nKU)
28514  : BaseSRMatrix(pd, nDim, 1 + nKL + nKU, nDim * (1 + nKL + nKU)),
28515  BaseBandMatrix(nKL, nKU), mSM()
28516  {
28517  this->_check_dimensions();
28518  }
28519 
28549  : BaseSRMatrix(m.msize(), 1 + m.lsize() + m.usize(), false),
28550  BaseBandMatrix(m.lsize(), m.usize()), mSM()
28551  {
28552  this->_massign(m);
28553  }
28554 
28573  : BaseSRMatrix(m.size(), m.incr(), m.msize(), m.nsize(), m.ld()),
28574  BaseBandMatrix(m.lsize(), m.usize()), mSM()
28575  {
28576  this->_mmove(std::move(m));
28577  }
28578 
28611  basic_srbmatrix(const BaseRMatrix& m, tint nKL, tint nKU)
28612  : BaseSRMatrix(m.msize(), 1 + nKL + nKU, false), BaseBandMatrix(nKL, nKU), mSM()
28613  {
28614  _check_ne(CVM_SIZESMISMATCH, this->msize(), this->nsize());
28615  this->_check_dimensions();
28616  _copy_b_matrix<TR,TR, BaseRMatrix, basic_srbmatrix>(const_cast<BaseRMatrix&>(m), *this, true);
28617  }
28618 
28643  explicit basic_srbmatrix(const RVector& v)
28644  : BaseSRMatrix(v.size(), 1, false),
28645  BaseBandMatrix(0, 0)
28646  {
28647  __copy<TR>(this->msize(), v, v.incr(), this->get(), 1);
28648  }
28649 
28650  type_proxy<TR,TR> operator () (tint nRow, tint nCol) throw(cvmexception)
28651  {
28652  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
28653  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
28654  return this->_ij_proxy_val(nRow - CVM0, nCol - CVM0);
28655  }
28656 
28657  TR operator () (tint nRow, tint nCol) const throw(cvmexception)
28658  {
28659  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
28660  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
28661  return this->_ij_val(nRow - CVM0, nCol - CVM0);
28662  }
28663 
28664  // returns column which CAN NOT be l-value
28665  const RVector operator () (tint nCol) const throw(cvmexception)
28666  {
28667  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
28668  return this->_col(nCol - CVM0);
28669  }
28670 
28671  // returns row which CAN NOT be l-value
28672  const RVector operator [] (tint nRow) const throw(cvmexception)
28673  {
28674  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
28675  return this->_row(nRow - CVM0);
28676  }
28677 
28710  basic_srbmatrix& operator = (const basic_srbmatrix& m) throw(cvmexception)
28711  {
28712  this->_check_dimensions(m);
28713  this->_massign(m);
28714  return *this;
28715  }
28716 
28730  basic_srbmatrix& operator = (basic_srbmatrix&& m) throw(cvmexception)
28731  {
28732  this->_check_dimensions(m);
28733  BaseSRMatrix::operator = (std::move(m));
28734  return *this;
28735  }
28736 
28737  // assigns vector
28738  basic_srbmatrix& assign(const RVector& v) throw(cvmexception)
28739  {
28740  _check_gt(CVM_SIZESMISMATCH_GT, this->size(), v.size());
28741  this->_assign(v, v.incr());
28742  return *this;
28743  }
28744 
28745  // assigns external array (nIncr = 1)
28746  basic_srbmatrix& assign(const TR* pd)
28747  {
28748  this->_assign(pd, 1);
28749  return *this;
28750  }
28751 
28752  // fills the content
28753  basic_srbmatrix& set(TR d)
28754  {
28755  this->_set(d);
28756  return *this;
28757  }
28758 
28759  basic_srbmatrix& resize(tint nNewDim) throw(cvmexception)
28760  {
28761  this->_resize2(nNewDim, nNewDim);
28762  return *this;
28763  }
28764 
28803  basic_srbmatrix& resize_lu(tint nNewKL, tint nNewKU) throw(cvmexception)
28804  {
28805 #ifdef CVM_USE_POOL_MANAGER
28806  this->_resize_lu(nNewKL, nNewKU);
28807 #else
28808  this->_resize_lu(this->mp, nNewKL, nNewKU);
28809 #endif
28810  return *this;
28811  }
28812 
28843  bool operator == (const basic_srbmatrix& m) const
28844  {
28845  return this->msize() == m.msize() && this->nsize() == m.nsize() &&
28846  this->lsize() == m.lsize() && this->usize() == m.usize() &&
28847  this->_mequals(m);
28848  }
28849 
28880  bool operator != (const basic_srbmatrix& m) const {
28881  return !(this->operator == (m));
28882  }
28883 
28922  basic_srbmatrix& operator << (const basic_srbmatrix& m) throw(cvmexception)
28923  {
28924  this->_check_ld(); // submatrix replacement is obviously not possible
28925 #ifdef CVM_USE_POOL_MANAGER
28926  this->_b_replace(m);
28927 #else
28928  this->_b_replace(this->mp, m);
28929 #endif
28930  this->_massign(m);
28931  return *this;
28932  }
28933 
28973  basic_srbmatrix operator + (const basic_srbmatrix& m) const throw(cvmexception)
28974  {
28975  this->_check_dimensions(m);
28976  basic_srbmatrix mSum(*this);
28977  mSum._mincr(m);
28978  return mSum;
28979  }
28980 
29020  basic_srbmatrix operator - (const basic_srbmatrix& m) const throw(cvmexception)
29021  {
29022  this->_check_dimensions(m);
29023  basic_srbmatrix mDiff(*this);
29024  mDiff._mdecr(m);
29025  return mDiff;
29026  }
29027 
29074  basic_srbmatrix& sum(const basic_srbmatrix& m1, const basic_srbmatrix& m2) throw(cvmexception)
29075  {
29076  this->_check_dimensions(m1);
29077  this->_check_dimensions(m2);
29078  this->_msum(m1, m2);
29079  return *this;
29080  }
29081 
29128  basic_srbmatrix& diff(const basic_srbmatrix& m1, const basic_srbmatrix& m2) throw(cvmexception)
29129  {
29130  this->_check_dimensions(m1);
29131  this->_check_dimensions(m2);
29132  this->_mdiff(m1, m2);
29133  return *this;
29134  }
29135 
29179  basic_srbmatrix& operator += (const basic_srbmatrix& m) throw(cvmexception)
29180  {
29181  this->_check_dimensions(m);
29182  this->_mincr(m);
29183  return *this;
29184  }
29185 
29229  basic_srbmatrix& operator -= (const basic_srbmatrix& m) throw(cvmexception)
29230  {
29231  this->_check_dimensions(m);
29232  this->_mdecr(m);
29233  return *this;
29234  }
29235 
29263  {
29264  static const TR mone(-1.);
29265  basic_srbmatrix mRes(*this);
29266  mRes._scalr(mone);
29267  return mRes;
29268  }
29269 
29298  {
29299  this->_plus_plus();
29300  return *this;
29301  }
29302 
29331  {
29332  this->_plus_plus();
29333  return *this;
29334  }
29335 
29364  {
29365  this->_minus_minus();
29366  return *this;
29367  }
29368 
29397  {
29398  this->_minus_minus();
29399  return *this;
29400  }
29401 
29403  {
29404  basic_srbmatrix mRes(*this);
29405  mRes._scalr(dMult);
29406  return mRes;
29407  }
29408 
29409  basic_srbmatrix operator / (TR dDiv) const throw(cvmexception)
29410  {
29411  basic_srbmatrix mRes(*this);
29412  mRes._div(dDiv);
29413  return mRes;
29414  }
29415 
29417  {
29418  this->_scalr(dMult);
29419  return *this;
29420  }
29421 
29422  basic_srbmatrix& operator /= (TR dDiv) throw(cvmexception)
29423  {
29424  this->_div(dDiv);
29425  return *this;
29426  }
29427 
29429  {
29430  this->_normalize();
29431  return *this;
29432  }
29433 
29434  // transposed Matrix
29435  basic_srbmatrix operator ~() const throw(cvmexception)
29436  {
29437  basic_srbmatrix mRes(*this);
29438  return mRes.transpose();
29439  }
29440 
29478  basic_srbmatrix& transpose(const basic_srbmatrix& m) throw(cvmexception)
29479  {
29480  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
29481  _check_ne(CVM_SIZESMISMATCH, this->lsize(), m.usize());
29482  _check_ne(CVM_SIZESMISMATCH, this->usize(), m.lsize());
29483  *this << ~m;
29484  return *this;
29485  }
29486 
29487  basic_srbmatrix& transpose() throw(cvmexception)
29488  {
29489  this->_transp();
29490  return *this;
29491  }
29492 
29493  RVector operator * (const RVector& v) const throw(cvmexception)
29494  {
29495  _check_ne(CVM_SIZESMISMATCH, this->nsize(), v.size());
29496  RVector vRes(this->msize());
29497  this->_multiply(vRes, v, false);
29498  return vRes;
29499  }
29500 
29501  // special exclusion since matrix product is not commutative
29502  BaseRMatrix operator * (const BaseRMatrix& m) const throw(cvmexception)
29503  {
29504  _bake_SM();
29505  return mSM * m;
29506  }
29507 
29539  BaseSRMatrix operator * (const BaseSRMatrix& m) const throw(cvmexception)
29540  {
29541  _bake_SM();
29542  return mSM * m;
29543  }
29544 
29579  basic_srbmatrix operator * (const basic_srbmatrix& m) const throw(cvmexception)
29580  {
29581  _bake_SM();
29582  m._bake_SM();
29583  return basic_srbmatrix(mSM * m.mSM,
29584  _cvm_min<tint>(this->msize() - 1, this->lsize() + m.lsize()),
29585  _cvm_min<tint>(this->msize() - 1, this->usize() + m.usize()));
29586  }
29587 
29588  // 6.1: reversed vector operator % returns solution of A*X=B equation
29589  // overridden to mask out operator / (TR)
29590  RVector operator / (const RVector& v) const throw(cvmexception) {
29591  return v % (*this);
29592  }
29593 
29686  basic_srbmatrix& low_up(const basic_srbmatrix& m, tint* nPivots) throw(cvmexception)
29687  {
29688  (*this) = m;
29689  this->_low_up(nPivots);
29690  return *this;
29691  }
29692 
29693  basic_srbmatrix low_up(tint* nPivots) const throw(cvmexception)
29694  {
29695  basic_srbmatrix mRes(*this);
29696  mRes._low_up(nPivots);
29697  return mRes;
29698  }
29699 
29701  {
29702  this->_vanish();
29703  this->_plus_plus();
29704  return *this;
29705  }
29706 
29708  {
29709  this->_vanish();
29710  return *this;
29711  }
29712 
29713  basic_srbmatrix& randomize(TR dFrom, TR dTo)
29714  {
29715  this->_b_randomize(true, dFrom, dTo);
29716  return *this;
29717  }
29718 
29719  // Euclid norm - band matrices require special care because of tails
29720  TR norm() const override
29721  {
29722  TR dNorm = TR(0.), d;
29723  tint i;
29724 
29725  for (i = 0; i <= this->lsize(); ++i) {
29726  // non-const version shares mamory, it's faster
29727  d = const_cast<basic_srbmatrix*>(this)->diag(-i).norm();
29728  dNorm += d * d;
29729  }
29730  for (i = 1; i <= this->usize(); ++i) {
29731  // non-const version shares mamory, it's faster
29732  d = const_cast<basic_srbmatrix*>(this)->diag(i).norm();
29733  dNorm += d * d;
29734  }
29735 
29736  return _sqrt(dNorm);
29737  }
29738 
29739  TR norm1() const override
29740  {
29741  return this->_bnorm1();
29742  }
29743 
29744  TR norminf() const override
29745  {
29746  return this->_bnorminf();
29747  }
29748 
29749  // ATTENTION!!! This is not a good idea to use the following function. It's provided for
29750  // overriding of basic_rmatrix<TR>::mult only
29751  // this = m1 * m2
29752  basic_srbmatrix& mult(const BaseRMatrix& m1, const BaseRMatrix& m2) throw(cvmexception)
29753  {
29754  this->_mult(m1, m2);
29755  return *this;
29756  }
29757 
29759  // redefinition of basic_array's function
29760  TR* _pd() override
29761  {
29762 #ifdef CVM_DEBUG
29763  // it's abnormal to call this function, this is pointer to copy, not to an object.
29764  // only const version is allowed
29765  assert(false);
29766 #endif
29767  _bake_SM();
29768  return mSM._pd();
29769  }
29770 
29771  // redefinition of basic_array's function
29772  const TR* _pd() const override
29773  {
29774  _bake_SM();
29775  return mSM._pd();
29776  }
29777 
29778  // singular values in decreasing order
29779  void _svd(RVector& vRes, BaseSRMatrix* pmU, BaseSRMatrix* pmVH) const throw(cvmexception) override
29780  {
29781  if (pmU != nullptr && pmVH != nullptr) {
29782  _check_ne(CVM_SIZESMISMATCH, this->msize(), pmU->msize());
29783  _check_ne(CVM_SIZESMISMATCH, this->nsize(), pmVH->msize());
29784  }
29785  __svd<TR,basic_srbmatrix, BaseSRMatrix>(vRes, vRes.size(), vRes.incr(), *this, pmU, pmVH);
29786  }
29787 
29788  void _pinv(BaseRMatrix& mX, TR threshold) const throw(cvmexception) override {
29789  __pinv<TR,basic_srbmatrix, BaseRMatrix>(mX, *this, threshold);
29790  }
29791 
29792  void _eig(CVector& vEig, basic_scmatrix<TR,TC>* mEigVect, bool bRightVect) const throw(cvmexception) override
29793  {
29794  _bake_SM();
29795  mSM._eig(vEig, mEigVect, bRightVect);
29796  }
29797 
29798  void _solve(const RVector& vB, RVector& vX,
29799  TR& dErr, const TR* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
29800  {
29801  vX = vB;
29802  RVector vB1;
29803  RVector vX1;
29804  if (vB.incr() > 1) vB1 << vB; // to make sure incr = 1
29805  if (vX.incr() > 1) vX1 << vX;
29806  __solve<TR,TR, basic_srbmatrix>(*this, 1, vB.incr() > 1 ? vB1 : vB, vB.size(),
29807  vX.incr() > 1 ? vX1 : vX, vX.size(), dErr, pLU, pPivots, transp_mode);
29808  if (vX.incr() > 1) vX = vX1;
29809  }
29810 
29811  void _solve(const BaseRMatrix& mB, BaseRMatrix& mX, TR& dErr,
29812  const TR* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
29813  {
29814  mX = mB;
29815  __solve<TR,TR, basic_srbmatrix>(*this, mB.nsize(), mB, mB.ld(), mX, mX.ld(), dErr, pLU, pPivots, transp_mode);
29816  }
29817 
29818  // ?gbmv routines perform a matrix-vector operation defined as
29819  // vRes = alpha*m*v + beta * vRes or vRes = alpha*v'*m + beta * vRes
29820  // not virtual since __gbmv calls all virtual methods inside
29821  void _gbmv(bool bLeft, TR dAlpha, const RVector& v, TR dBeta, RVector& vRes) const
29822  {
29823  RVector vTmp;
29824  basic_srbmatrix mTmp;
29825  const TR* pDv = v;
29826  if (vRes.get() == pDv) vTmp << v;
29827  if (vRes.get() == this->get()) mTmp << *this;
29828  __gbmv<TR,basic_srbmatrix, RVector>(bLeft, vRes.get() == this->get() ? mTmp : *this, dAlpha,
29829  vRes.get() == pDv ? vTmp : v, dBeta, vRes);
29830  }
29831 
29832  void _check_submatrix() const throw(cvmexception) override {
29833  throw cvmexception(CVM_SUBMATRIXNOTAVAILABLE, "srbmatrix");
29834  }
29835 
29836  const TR* _pb() const override {
29837  return this->get();
29838  }
29839 
29840  TR* _pb() override {
29841  return this->get();
29842  }
29843 
29844 protected:
29845  void _bake_SM() const
29846  {
29847  mSM.resize(this->msize());
29848  mSM.vanish();
29849  _copy_b_matrix<TR,TR, BaseSRMatrix, basic_srbmatrix>(mSM, *const_cast<basic_srbmatrix*>(this), false);
29850  }
29851 
29852  tint _size() const override {return this->size(); }
29853  tint _msize() const override {return this->msize(); }
29854  tint _nsize() const override {return this->nsize(); }
29855  tint _ld() const override {return this->ld(); }
29856 
29857  void _set_p(TR* pf) override
29858  {
29859 #ifdef CVM_USE_POOL_MANAGER
29860  this->mpd = pf;
29861 #else
29862  this->mpf = pf;
29863 #endif
29864  }
29865 
29866  void _set(TR* pf, tint nSize, tint nM, tint nN, tint nIncr, tint nLD) override
29867  {
29868 #ifdef CVM_USE_POOL_MANAGER
29869  this->mpd = pf;
29870 #else
29871  this->mpf = pf;
29872 #endif
29873  this->msz = nSize;
29874  this->mm = nM;
29875  this->mn = nN;
29876  this->mincr = nIncr;
29877  this->mld = nLD;
29878  }
29879 
29880  // for _msum _mdiff etc.
29881  const TR* _pp(const BaseMatrix& m) const override {
29882  return m.get();
29883  }
29884 
29885  tint _ldm() const override {
29886  return this->mm;
29887  }
29888 
29889  const tint* _pldm() const override {
29890  return &this->mm;
29891  }
29892 
29893  // 0-based, returns an l-value sharing memory
29894  RVector _row(tint m) override
29895  {
29896  RVector vRet(this->msize());
29897  this->_get_row(m, vRet, vRet.incr());
29898  return vRet;
29899  }
29900 
29901  // 0-based, returns not an l-value (copy)
29902  // looks like cut-n-paste, but it's not
29903  const RVector _row(tint m) const override
29904  {
29905  RVector vRet(this->msize());
29906  this->_get_row(m, vRet, vRet.incr());
29907  return vRet;
29908  }
29909 
29910  // 0-based, returns an l-value sharing memory
29911  RVector _col(tint n) override
29912  {
29913  RVector vRet(this->msize());
29914  this->_get_col(n, vRet, vRet.incr());
29915  return vRet;
29916  }
29917 
29918  // 0-based, returns not an l-value (copy)
29919  // looks like cut-n-paste, but it's not
29920  const RVector _col(tint n) const override
29921  {
29922  RVector vRet(this->msize());
29923  this->_get_col(n, vRet, vRet.incr());
29924  return vRet;
29925  }
29926 
29927  RVector _diag(tint nDiag) throw(cvmexception) override
29928  {
29929  const tint nD = _abs(nDiag);
29930  if (nDiag < 0) {
29931  _check_gt(CVM_INDEX_GT, nD, this->lsize());
29932  }
29933  else {
29934  _check_gt(CVM_INDEX_GT, nDiag, this->usize());
29935  }
29936  const tint nLU = this->lsize() + this->usize();
29937  return RVector(this->get() + this->usize() + (nDiag < 0 ? nD : nD * nLU), this->msize() - nD, nLU + 1);
29938  }
29939 
29940  const RVector _diag(tint nDiag) const throw(cvmexception) override
29941  {
29942  const tint nD = _abs(nDiag);
29943  if (nDiag < 0) {
29944  _check_gt(CVM_INDEX_GT, nD, this->lsize());
29945  }
29946  else {
29947  _check_gt(CVM_INDEX_GT, nDiag, this->usize());
29948  }
29949  const tint nLU = this->lsize() + this->usize();
29950  return RVector(this->get() + this->usize() + (nDiag < 0 ? nD : nD * nLU), this->msize() - nD, nLU + 1);
29951  }
29952 
29953  void _swap_rows(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_rows", "srbmatrix");}
29954  void _swap_cols(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_cols", "srbmatrix");}
29955  void _check_ger() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "ger", "srbmatrix");}
29956  void _check_rank1update() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "rank1update", "srbmatrix");}
29957  void _check_gemm() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "gemm", "srbmatrix");}
29958  void _check_symm() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "symm", "srbmatrix");}
29959  void _check_cholesky() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "cholesky", "srbmatrix");}
29960  void _check_bunch_kaufman() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "bunch_kaufman", "srbmatrix");}
29961 
29962  void _resize2(tint nNewM, tint) throw(cvmexception) override
29963  {
29964 #ifdef CVM_USE_POOL_MANAGER
29965  this->_bresize(nNewM);
29966 #else
29967  this->_bresize(this->mp, nNewM);
29968 #endif
29969  }
29970 
29971  bool _continuous() const override {
29972  return this->_bcontinuous();
29973  }
29974 
29975  void _massign(const BaseMatrix& m) override {
29976  this->_mbassign(m);
29977  }
29978 
29979  void _set(TR d) override {
29980  this->_bset(d);
29981  }
29982 
29983  void _vanish() override {
29984  this->_bvanish();
29985  }
29986 
29987  // zero based
29988  type_proxy<TR,TR> _ij_proxy_val(tint i, tint j) override {
29989  return this->_b_ij_proxy_val(i, j);
29990  }
29991 
29992  // zero based
29993  TR _ij_val(tint i, tint j) const override {
29994  return this->_b_ij_val(i, j);
29995  }
29996 
29997  void _transp() throw(cvmexception) override
29998  {
29999 #ifdef CVM_USE_POOL_MANAGER
30000  this->_btransp();
30001 #else
30002  this->_btransp(this->mp);
30003 #endif
30004  }
30005 
30006  void _plus_plus() override {
30007  this->_b_plus_plus();
30008  }
30009 
30010  void _minus_minus() override {
30011  this->_b_minus_minus();
30012  }
30013 
30014  tint _indofmax() const override
30015  {
30016  this->_check_ld();
30017  _bake_SM();
30018  return mSM.indofmax();
30019  }
30020 
30021  tint _indofmin() const override
30022  {
30023  this->_check_ld();
30024  _bake_SM();
30025  return mSM.indofmin();
30026  }
30027 
30028  // returns main diagonal of low_up factorization
30029  RVector _low_up_diag(basic_array<tint,tint>& naPivots) const throw(cvmexception) override
30030  {
30031  // let temp matrix be const to get a copy of its main diagonal
30032  const basic_srbmatrix lu = this->low_up(naPivots);
30033  return lu.diag(0);
30034  }
30035 
30036  void _scalr(TR d) override {
30037  __scal<TR,TR>(this->get(), this->size(), this->incr(), d); // zero tails are supposed here
30038  }
30039 
30040  void _mult(const BaseRMatrix& m1, const BaseRMatrix& m2) throw(cvmexception) override
30041  {
30042  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
30043  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
30044  _check_ne(CVM_SIZESMISMATCH, m1.nsize(), m2.msize());
30045  BaseSRMatrix mR(this->msize());
30046  mR.mult(m1, m2);
30047 #ifdef CVM_USE_POOL_MANAGER
30048  this->_resize_lu(this->msize() - 1, this->msize() - 1);
30049 #else
30050  this->_resize_lu(this->mp, this->msize() - 1, this->msize() - 1);
30051 #endif
30052  _copy_b_matrix<TR,TR, BaseSRMatrix, basic_srbmatrix>(const_cast<BaseSRMatrix&>(mR), *this, true);
30053  }
30054 
30055  void _multiply(RVector& vRes, const RVector& v, bool bLeft) const override
30056  {
30057  static const TR zero(0.);
30058  static const TR one(1.);
30059  this->_gbmv(bLeft, one, v, zero, vRes);
30060  }
30061 
30062  void _randomize(TR dFrom, TR dTo) override {
30063  __randomize<TR>(this->get(), this->size(), this->incr(), dFrom, dTo);
30064  }
30065 
30066  void _low_up(tint* nPivots) throw(cvmexception) override {
30067  __low_up<basic_srbmatrix>(*this, nPivots);
30068  }
30069 
30070  tint _ld_for_replace() const override {
30071  return this->mm;
30072  }
30073 
30074  tint _size_for_replace() const override {
30075  return this->mm * this->mn;
30076  }
30078 };
30079 
30080 
30109 template<typename TR, typename TC>
30110 class basic_scbmatrix : public basic_scmatrix<TR,TC>, public BandMatrix<TR,TC>
30111 {
30112  typedef basic_cvector<TR,TC> CVector;
30113  typedef basic_array<TR,TC> BaseArray;
30114  typedef Matrix<TR,TC> BaseMatrix;
30118 
30119 protected:
30120  mutable BaseSCMatrix mSM;
30121 
30122 public:
30145  : mSM()
30146  {
30147  }
30148 
30174  explicit basic_scbmatrix(tint nDim)
30175  : BaseSCMatrix(nDim, 1, true),
30176  BaseBandMatrix(0, 0)
30177  {
30178  }
30179 
30209  basic_scbmatrix(tint nDim, tint nKL, tint nKU)
30210  : BaseSCMatrix(nDim, 1 + nKL + nKU, true),
30211  BaseBandMatrix(nKL, nKU), mSM()
30212  {
30213  this->_check_dimensions();
30214  }
30215 
30259  basic_scbmatrix(TC* pd, tint nDim, tint nKL, tint nKU)
30260  : BaseSCMatrix(pd, nDim, 1 + nKL + nKU, nDim * (1 + nKL + nKU)),
30261  BaseBandMatrix(nKL, nKU), mSM()
30262  {
30263  this->_check_dimensions();
30264  }
30265 
30309  basic_scbmatrix(const TC* pd, tint nDim, tint nKL, tint nKU)
30310  : BaseSCMatrix(pd, nDim, 1 + nKL + nKU, nDim * (1 + nKL + nKU)),
30311  BaseBandMatrix(nKL, nKU), mSM()
30312  {
30313  this->_check_dimensions();
30314  }
30315 
30346  : BaseSCMatrix(m.msize(), 1 + m.lsize() + m.usize(), false),
30347  BaseBandMatrix(m.lsize(), m.usize()), mSM()
30348  {
30349  this->_massign(m);
30350  }
30351 
30370  : BaseSCMatrix(m.size(), m.incr(), m.msize(), m.nsize(), m.ld()),
30371  BaseBandMatrix(m.lsize(), m.usize()), mSM()
30372  {
30373  this->_mmove(std::move(m));
30374  }
30375 
30406  basic_scbmatrix(const BaseCMatrix& m, tint nKL, tint nKU)
30407  : BaseSCMatrix(m.msize(), 1 + nKL + nKU, false),
30408  BaseBandMatrix(nKL, nKU), mSM()
30409  {
30410  _check_ne(CVM_SIZESMISMATCH, this->msize(), this->nsize());
30411  this->_check_dimensions();
30412  _copy_b_matrix<TR,TC, BaseCMatrix, basic_scbmatrix>(const_cast<BaseCMatrix&>(m), *this, true);
30413  }
30414 
30437  explicit basic_scbmatrix(const CVector& v)
30438  : BaseSCMatrix(v.size(), 1, false),
30439  BaseBandMatrix(0, 0)
30440  {
30441  __copy<TC>(this->msize(), v, v.incr(), this->get(), 1);
30442  }
30443 
30473  explicit basic_scbmatrix(const basic_srbmatrix<TR>& m, bool bRealPart = true)
30474  : BaseSCMatrix(m.msize(), m.ld(), true),
30475  BaseBandMatrix(m.lsize(), m.usize()),
30476  mSM()
30477  {
30478  if (bRealPart) {
30479  __copy2<TR,TC>(this->get(), this->size(), this->incr(), m.get(), nullptr);
30480  }
30481  else {
30482  __copy2<TR,TC>(this->get(), this->size(), this->incr(), nullptr, m.get());
30483  }
30484  }
30485 
30514  : BaseSCMatrix(mRe.msize(), mRe.ld(), false),
30515  BaseBandMatrix(mRe.lsize(), mRe.usize()),
30516  mSM()
30517  {
30518  _check_ne(CVM_SIZESMISMATCH, mRe.msize(), mIm.msize());
30519  _check_ne(CVM_SIZESMISMATCH, mRe.nsize(), mIm.nsize());
30520  _check_ne(CVM_SIZESMISMATCH, mRe.lsize(), mIm.lsize());
30521  _check_ne(CVM_SIZESMISMATCH, mRe.usize(), mIm.usize());
30522  __copy2<TR,TC>(this->get(), this->size(), this->incr(), mRe, mIm, mRe.incr(), mIm.incr());
30523  }
30524 
30525  type_proxy<TC, TR> operator () (tint nRow, tint nCol) throw(cvmexception)
30526  {
30527  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
30528  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
30529  return this->_ij_proxy_val(nRow - CVM0, nCol - CVM0);
30530  }
30531 
30532  TC operator () (tint nRow, tint nCol) const throw(cvmexception)
30533  {
30534  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
30535  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
30536  return this->_ij_val(nRow - CVM0, nCol - CVM0);
30537  }
30538 
30539  // returns column which CAN NOT be l-value
30540  const CVector operator () (tint nCol) const throw(cvmexception)
30541  {
30542  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
30543  return this->_col(nCol - CVM0);
30544  }
30545 
30546  // returns row which CAN NOT be l-value
30547  const CVector operator [] (tint nRow) const throw(cvmexception)
30548  {
30549  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
30550  return this->_row(nRow - CVM0);
30551  }
30552 
30553  // real part
30554  const basic_srbmatrix<TR> real() const
30555  {
30556  basic_srbmatrix<TR> mRet(this->msize(), this->lsize(), this->usize());
30557  __copy<TR>(this->size(), __get_real_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
30558  return mRet;
30559  }
30560 
30561  // imaginary part
30562  const basic_srbmatrix<TR> imag() const
30563  {
30564  basic_srbmatrix<TR> mRet(this->msize(), this->lsize(), this->usize());
30565  __copy<TR>(this->size(), __get_imag_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
30566  return mRet;
30567  }
30568 
30601  basic_scbmatrix& operator = (const basic_scbmatrix& m) throw(cvmexception)
30602  {
30603  this->_check_dimensions(m);
30604  this->_massign(m);
30605  return *this;
30606  }
30607 
30621  basic_scbmatrix& operator = (basic_scbmatrix&& m) throw(cvmexception)
30622  {
30623  this->_check_dimensions(m);
30624  BaseSCMatrix::operator = (std::move(m));
30625  return *this;
30626  }
30627 
30628  // assigns vector
30629  basic_scbmatrix& assign(const CVector& v) throw(cvmexception)
30630  {
30631  _check_gt(CVM_SIZESMISMATCH_GT, this->size(), v.size());
30632  this->_assign(v, v.incr());
30633  return *this;
30634  }
30635 
30636  // assigns a external array (nIncr = 1)
30637  basic_scbmatrix& assign(const TC* pd)
30638  {
30639  this->_assign(pd, 1);
30640  return *this;
30641  }
30642 
30643  basic_scbmatrix& set(TC c)
30644  {
30645  this->_set(c);
30646  return *this;
30647  }
30648 
30675  basic_scbmatrix& assign_real(const basic_srbmatrix<TR>& mRe) throw(cvmexception)
30676  {
30677  _check_ne(CVM_SIZESMISMATCH, this->msize(), mRe.msize());
30678  _check_ne(CVM_SIZESMISMATCH, this->lsize(), mRe.lsize());
30679  _check_ne(CVM_SIZESMISMATCH, this->usize(), mRe.usize());
30680  __copy_real<TR,TC>(this->get(), this->size(), this->incr(), mRe, mRe.incr());
30681  return *this;
30682  }
30683 
30710  basic_scbmatrix& assign_imag(const basic_srbmatrix<TR>& mIm) throw(cvmexception)
30711  {
30712  _check_ne(CVM_SIZESMISMATCH, this->msize(), mIm.msize());
30713  _check_ne(CVM_SIZESMISMATCH, this->lsize(), mIm.lsize());
30714  _check_ne(CVM_SIZESMISMATCH, this->usize(), mIm.usize());
30715  __copy_imag<TR,TC>(this->get(), this->size(), this->incr(), mIm, mIm.incr());
30716  return *this;
30717  }
30718 
30719  // fills real part
30720  basic_scbmatrix& set_real(TR d)
30721  {
30722  this->_set_real_number(d);
30723  return *this;
30724  }
30725 
30726  // fills imaginary part
30727  basic_scbmatrix& set_imag(TR d)
30728  {
30729  this->_set_imag_number(d);
30730  return *this;
30731  }
30732 
30733  basic_scbmatrix& resize(tint nNewDim) throw(cvmexception)
30734  {
30735  this->_resize2(nNewDim, nNewDim);
30736  return *this;
30737  }
30738 
30775  basic_scbmatrix& resize_lu(tint nNewKL, tint nNewKU) throw(cvmexception)
30776  {
30777 #ifdef CVM_USE_POOL_MANAGER
30778  this->_resize_lu(nNewKL, nNewKU);
30779 #else
30780  this->_resize_lu(this->mp, nNewKL, nNewKU);
30781 #endif
30782  return *this;
30783  }
30784 
30816  bool operator == (const basic_scbmatrix& m) const
30817  {
30818  return this->msize() == m.msize() && this->nsize() == m.nsize() &&
30819  this->lsize() == m.lsize() && this->usize() == m.usize() && this->_mequals(m);
30820  }
30821 
30853  bool operator != (const basic_scbmatrix& m) const {
30854  return !(this->operator == (m));
30855  }
30856 
30896  basic_scbmatrix& operator << (const basic_scbmatrix& m) throw(cvmexception)
30897  {
30898  this->_check_ld(); // submatrix replacement is obviously not possible
30899 #ifdef CVM_USE_POOL_MANAGER
30900  this->_b_replace(m);
30901 #else
30902  this->_b_replace(this->mp, m);
30903 #endif
30904  this->_massign(m);
30905  return *this;
30906  }
30907 
30954  basic_scbmatrix operator + (const basic_scbmatrix& m) const throw(cvmexception)
30955  {
30956  this->_check_dimensions(m);
30957  basic_scbmatrix mSum(*this);
30958  mSum._mincr(m);
30959  return mSum;
30960  }
30961 
31008  basic_scbmatrix operator - (const basic_scbmatrix& m) const throw(cvmexception)
31009  {
31010  this->_check_dimensions(m);
31011  basic_scbmatrix mDiff(*this);
31012  mDiff._mdecr(m);
31013  return mDiff;
31014  }
31015 
31058  basic_scbmatrix& sum(const basic_scbmatrix& m1, const basic_scbmatrix& m2) throw(cvmexception)
31059  {
31060  this->_check_dimensions(m1);
31061  this->_check_dimensions(m2);
31062  this->_msum(m1, m2);
31063  return *this;
31064  }
31065 
31108  basic_scbmatrix& diff(const basic_scbmatrix& m1, const basic_scbmatrix& m2) throw(cvmexception)
31109  {
31110  this->_check_dimensions(m1);
31111  this->_check_dimensions(m2);
31112  this->_mdiff(m1, m2);
31113  return *this;
31114  }
31115 
31159  basic_scbmatrix& operator += (const basic_scbmatrix& m) throw(cvmexception)
31160  {
31161  this->_check_dimensions(m);
31162  this->_mincr(m);
31163  return *this;
31164  }
31165 
31209  basic_scbmatrix& operator -= (const basic_scbmatrix& m) throw(cvmexception)
31210  {
31211  this->_check_dimensions(m);
31212  this->_mdecr(m);
31213  return *this;
31214  }
31215 
31217  {
31218  static const TR mone(-1.);
31219  basic_scbmatrix mRes(*this);
31220  mRes._scalr(mone);
31221  return mRes;
31222  }
31223 
31224  // plus identity, prefix
31225  basic_scbmatrix& operator ++ ()
31226  {
31227  this->_plus_plus();
31228  return *this;
31229  }
31230 
31231  // plus identity, postfix
31232  basic_scbmatrix operator ++ (int)
31233  {
31234  this->_plus_plus();
31235  return *this;
31236  }
31237 
31238  // minus identity, prefix
31239  basic_scbmatrix& operator -- ()
31240  {
31241  this->_minus_minus();
31242  return *this;
31243  }
31244 
31245  // minus identity, postfix
31246  basic_scbmatrix operator -- (int)
31247  {
31248  this->_minus_minus();
31249  return *this;
31250  }
31251 
31253  {
31254  basic_scbmatrix mRes(*this);
31255  mRes._scalr(dMult);
31256  return mRes;
31257  }
31258 
31259  basic_scbmatrix operator / (TR dDiv) const throw(cvmexception)
31260  {
31261  basic_scbmatrix mRes(*this);
31262  mRes._div(dDiv);
31263  return mRes;
31264  }
31265 
31267  {
31268  basic_scbmatrix mRes(*this);
31269  mRes._scalc(cMult);
31270  return mRes;
31271  }
31272 
31273  basic_scbmatrix operator / (TC cDiv) const throw(cvmexception)
31274  {
31275  basic_scbmatrix mRes(*this);
31276  mRes._div(cDiv);
31277  return mRes;
31278  }
31279 
31280  basic_scbmatrix& operator *= (TR dMult)
31281  {
31282  this->_scalr(dMult);
31283  return *this;
31284  }
31285 
31286  basic_scbmatrix& operator /= (TR dDiv)
31287  {
31288  this->_div(dDiv);
31289  return *this;
31290  }
31291 
31292  basic_scbmatrix& operator *= (TC cMult)
31293  {
31294  this->_scalc(cMult);
31295  return *this;
31296  }
31297 
31298  basic_scbmatrix& operator /= (TC cDiv) throw(cvmexception)
31299  {
31300  this->_div(cDiv);
31301  return *this;
31302  }
31303 
31304  basic_scbmatrix& normalize()
31305  {
31306  this->_normalize();
31307  return *this;
31308  }
31309 
31310  // 6.1: transposed (not conjugated) matrix
31311  basic_scbmatrix operator !() const throw(cvmexception)
31312  {
31313  basic_scbmatrix mRes(*this);
31314  return mRes.transpose();
31315  }
31316 
31317  // hermitian conjugated matrix
31318  basic_scbmatrix operator ~() const throw(cvmexception)
31319  {
31320  basic_scbmatrix mRes(*this);
31321  return mRes.conj();
31322  }
31323 
31324 // 6.1: transposed (not conjugated) matrix
31368  basic_scbmatrix& transpose(const basic_scbmatrix& m) throw(cvmexception)
31369  {
31370  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
31371  _check_ne(CVM_SIZESMISMATCH, this->lsize(), m.usize());
31372  _check_ne(CVM_SIZESMISMATCH, this->usize(), m.lsize());
31373  *this << !m;
31374  return *this;
31375  }
31376 
31420  basic_scbmatrix& conj(const basic_scbmatrix& m) throw(cvmexception)
31421  {
31422  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
31423  _check_ne(CVM_SIZESMISMATCH, this->lsize(), m.usize());
31424  _check_ne(CVM_SIZESMISMATCH, this->usize(), m.lsize());
31425  *this << ~m;
31426  return *this;
31427  }
31428 
31429  // 6.1: transposed (not conjugated) matrix
31430  basic_scbmatrix& transpose() throw(cvmexception)
31431  {
31432  this->_transp();
31433  return *this;
31434  }
31435 
31436  basic_scbmatrix& conj() throw(cvmexception)
31437  {
31438  this->_conj();
31439  return *this;
31440  }
31441 
31442  CVector operator * (const CVector& v) const throw(cvmexception)
31443  {
31444  _check_ne(CVM_SIZESMISMATCH, this->nsize(), v.size());
31445  CVector vRes(this->msize());
31446  this->_multiply(vRes, v, false);
31447  return vRes;
31448  }
31449 
31450  // special exclusion since matrix product is not commutative
31451  BaseCMatrix operator * (const BaseCMatrix& m) const throw(cvmexception)
31452  {
31453  _bake_SM();
31454  return mSM * m;
31455  }
31456 
31488  BaseSCMatrix operator * (const BaseSCMatrix& m) const throw(cvmexception)
31489  {
31490  _bake_SM();
31491  return mSM * m;
31492  }
31493 
31527  basic_scbmatrix operator * (const basic_scbmatrix& m) const throw(cvmexception)
31528  {
31529  _bake_SM();
31530  m._bake_SM();
31531  return basic_scbmatrix(mSM * m.mSM,
31532  _cvm_min<tint>(this->msize() - 1, this->lsize() + m.lsize()),
31533  _cvm_min<tint>(this->msize() - 1, this->usize() + m.usize()));
31534  }
31535 
31536  // 6.1: reversed vector operator % returns solution of A*X=B equation
31537  // overridden to mask out operator / (TC)
31538  CVector operator / (const CVector& v) const throw(cvmexception) {
31539  return v % (*this);
31540  }
31541 
31633  basic_scbmatrix& low_up(const basic_scbmatrix& m, tint* nPivots) throw(cvmexception)
31634  {
31635  *this = m;
31636  this->_low_up(nPivots);
31637  return *this;
31638  }
31639 
31640  basic_scbmatrix low_up(tint* nPivots) const throw(cvmexception)
31641  {
31642  basic_scbmatrix mRes(*this);
31643  mRes._low_up(nPivots);
31644  return mRes;
31645  }
31646 
31647  basic_scbmatrix& identity()
31648  {
31649  this->_vanish();
31650  this->_plus_plus();
31651  return *this;
31652  }
31653 
31655  {
31656  this->_vanish();
31657  return *this;
31658  }
31659 
31660  basic_scbmatrix& randomize_real(TR dFrom, TR dTo)
31661  {
31662  this->_b_randomize(true, dFrom, dTo);
31663  return *this;
31664  }
31665 
31666  basic_scbmatrix& randomize_imag(TR dFrom, TR dTo)
31667  {
31668  this->_b_randomize(false, dFrom, dTo);
31669  return *this;
31670  }
31671 
31672  // Euclid norm - band matrices require special care because of tails
31673  TR norm() const override
31674  {
31675  TR dNorm = TR(0.), d;
31676  tint i;
31677  for (i = 0; i <= this->lsize(); ++i) {
31678  // non-const version shares mamory, it's faster
31679  d = const_cast<basic_scbmatrix*>(this)->diag(-i).norm();
31680  dNorm += d * d;
31681  }
31682  for (i = 1; i <= this->usize(); ++i) {
31683  // non-const version shares mamory, it's faster
31684  d = const_cast<basic_scbmatrix*>(this)->diag(i).norm();
31685  dNorm += d * d;
31686  }
31687  return _sqrt(dNorm);
31688  }
31689 
31690  TR norm1() const override {
31691  return this->_bnorm1();
31692  }
31693 
31694  TR norminf() const override {
31695  return this->_bnorminf();
31696  }
31697 
31698  // ATTENTION!!! This is not a good idea to use the following function. It's provided for
31699  // overriding of basic_rmatrix<TR>::mult only
31700  basic_scbmatrix& mult(const BaseCMatrix& m1, const BaseCMatrix& m2) throw(cvmexception)
31701  {
31702  this->_mult(m1, m2);
31703  return *this;
31704  }
31705 
31707  // redefinition of basic_array's function
31708  TC* _pd() override
31709  {
31710 #ifdef CVM_DEBUG
31711  // it's abnormal to call this function, this is pointer to copy, not to an object. only const version is allowed
31712  assert(false);
31713 #endif
31714  _bake_SM();
31715  return mSM._pd();
31716  }
31717 
31718  // redefinition of basic_array's function
31719  const TC* _pd() const override
31720  {
31721  _bake_SM();
31722  return mSM._pd();
31723  }
31724 
31725  // singular values in decreasing order
31726  void _svd(basic_rvector<TR>& vRes, BaseSCMatrix* pmU, BaseSCMatrix* pmVH) const throw(cvmexception) override
31727  {
31728  if (pmU != nullptr && pmVH != nullptr) {
31729  _check_ne(CVM_SIZESMISMATCH, this->msize(), pmU->msize());
31730  _check_ne(CVM_SIZESMISMATCH, this->nsize(), pmVH->msize());
31731  }
31732  __svd<TR,basic_scbmatrix, BaseSCMatrix>(vRes, vRes.size(), vRes.incr(), *this, pmU, pmVH);
31733  }
31734 
31735  void _pinv(BaseCMatrix& mX, TR threshold) const throw(cvmexception) override {
31736  __pinv<TR,basic_scbmatrix, BaseCMatrix>(mX, *this, threshold);
31737  }
31738 
31739  void _eig(CVector& vEig, basic_scmatrix<TR,TC>* mEigVect, bool bRightVect) const throw(cvmexception) override
31740  {
31741  _bake_SM();
31742  mSM._eig(vEig, mEigVect, bRightVect);
31743  }
31744 
31745  void _solve(const CVector& vB, CVector& vX,
31746  TR& dErr, const TC* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
31747  {
31748  vX = vB;
31749  CVector vB1;
31750  CVector vX1;
31751  if (vB.incr() > 1) vB1 << vB; // to make sure incr = 1
31752  if (vX.incr() > 1) vX1 << vX;
31753  __solve<TR,TC, basic_scbmatrix>(*this, 1, vB.incr() > 1 ? vB1 : vB, vB.size(), vX.incr() > 1 ? vX1 : vX, vX.size(),
31754  dErr, pLU, pPivots, transp_mode);
31755  if (vX.incr() > 1) vX = vX1;
31756  }
31757 
31758  void _solve(const BaseCMatrix& mB, BaseCMatrix& mX,
31759  TR& dErr, const TC* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
31760  {
31761  mX = mB;
31762  __solve<TR,TC, basic_scbmatrix>(*this, mB.nsize(), mB, mB.ld(), mX, mX.ld(), dErr, pLU, pPivots, transp_mode);
31763  }
31764 
31765  // ?gbmv routines perform a matrix-vector operation defined as
31766  // vRes = alpha*m*v + beta * vRes or vRes = alpha*v'*m + beta * vRes
31767  // not virtual since __gbmv calls all virtual methods inside
31768  void _gbmv(bool bLeft, TC dAlpha, const CVector& v, TC dBeta, CVector& vRes) const
31769  {
31770  CVector vTmp;
31771  basic_scbmatrix mTmp;
31772  const TC* pDv = v;
31773  if (vRes.get() == pDv) vTmp << v;
31774  if (vRes.get() == this->get()) mTmp << *this;
31775  __gbmv<TC, basic_scbmatrix, CVector>(bLeft, vRes.get() == this->get() ? mTmp : *this, dAlpha,
31776  vRes.get() == pDv ? vTmp : v, dBeta, vRes);
31777  }
31778 
31779  void _check_submatrix() const throw(cvmexception) override {
31780  throw cvmexception(CVM_SUBMATRIXNOTAVAILABLE, "scbmatrix");
31781  }
31782 
31783  const TC* _pb() const override {
31784  return this->get();
31785  }
31786 
31787  TC* _pb() override {
31788  return this->get();
31789  }
31790 
31791 protected:
31792  void _bake_SM() const
31793  {
31794  mSM.resize(this->msize());
31795  mSM.vanish();
31796  _copy_b_matrix<TR,TC, BaseSCMatrix, basic_scbmatrix>(mSM, *const_cast<basic_scbmatrix*>(this), false);
31797  }
31798 
31799  tint _size() const override {return this->size(); }
31800  tint _msize() const override {return this->msize(); }
31801  tint _nsize() const override {return this->nsize(); }
31802  tint _ld() const override {return this->ld(); }
31803 
31804  void _set_p(TC* pf) override
31805  {
31806 #ifdef CVM_USE_POOL_MANAGER
31807  this->mpd = pf;
31808 #else
31809  this->mpf = pf;
31810 #endif
31811  }
31812 
31813  void _set(TC* pf, tint nSize, tint nM, tint nN, tint nIncr, tint nLD) override
31814  {
31815 #ifdef CVM_USE_POOL_MANAGER
31816  this->mpd = pf;
31817 #else
31818  this->mpf = pf;
31819 #endif
31820  this->msz = nSize;
31821  this->mm = nM;
31822  this->mn = nN;
31823  this->mincr = nIncr;
31824  this->mld = nLD;
31825  }
31826 
31827  const TC* _pp(const BaseMatrix& m) const override { // for _msum _mdiff etc.
31828  return m.get();
31829  }
31830 
31831  tint _ldm() const override {
31832  return this->mm;
31833  }
31834 
31835  const tint* _pldm() const override {
31836  return &this->mm;
31837  }
31838 
31839  // 0-based, returns an l-value sharing memory
31840  CVector _row(tint m) override
31841  {
31842  CVector vRet(this->msize());
31843  this->_get_row(m, vRet, vRet.incr());
31844  return vRet;
31845  }
31846 
31847  // 0-based, returns not an l-value (copy)
31848  // looks like cut-n-paste, but it's not
31849  const CVector _row(tint m) const override
31850  {
31851  CVector vRet(this->msize());
31852  this->_get_row(m, vRet, vRet.incr());
31853  return vRet;
31854  }
31855 
31856  // 0-based, returns an l-value sharing memory
31857  CVector _col(tint n) override
31858  {
31859  CVector vRet(this->msize());
31860  this->_get_col(n, vRet, vRet.incr());
31861  return vRet;
31862  }
31863 
31864  // 0-based, returns not an l-value (copy)
31865  // looks like cut-n-paste, but it's not
31866  const CVector _col(tint n) const override
31867  {
31868  CVector vRet(this->msize());
31869  this->_get_col(n, vRet, vRet.incr());
31870  return vRet;
31871  }
31872 
31873  CVector _diag(tint nDiag) throw(cvmexception) override
31874  {
31875  const tint nD = _abs(nDiag);
31876  if (nDiag < 0) {
31877  _check_gt(CVM_INDEX_GT, nD, this->lsize());
31878  }
31879  else {
31880  _check_gt(CVM_INDEX_GT, nDiag, this->usize());
31881  }
31882  const tint nLU = this->lsize() + this->usize();
31883  return CVector(this->get() + this->usize() + (nDiag < 0 ? nD : nD * nLU), this->msize() - nD, nLU + 1);
31884  }
31885 
31886  const CVector _diag(tint nDiag) const throw(cvmexception) override
31887  {
31888  const tint nD = _abs(nDiag);
31889  if (nDiag < 0) {
31890  _check_gt(CVM_INDEX_GT, nD, this->lsize());
31891  }
31892  else {
31893  _check_gt(CVM_INDEX_GT, nDiag, this->usize());
31894  }
31895  const tint nLU = this->lsize() + this->usize();
31896  return CVector(this->get() + this->usize() + (nDiag < 0 ? nD : nD * nLU), this->msize() - nD, nLU + 1);
31897  }
31898 
31899  void _resize2(tint nNewM, tint) throw(cvmexception) override
31900  {
31901 #ifdef CVM_USE_POOL_MANAGER
31902  this->_bresize(nNewM);
31903 #else
31904  this->_bresize(this->mp, nNewM);
31905 #endif
31906  }
31907 
31908  bool _continuous() const override
31909  {
31910  return this->_bcontinuous();
31911  }
31912 
31913  void _massign(const BaseMatrix& m) override {
31914  this->_mbassign(m);
31915  }
31916 
31917  void _set(TC d) override {
31918  this->_bset(d);
31919  }
31920 
31921  void _vanish() override {
31922  this->_bvanish();
31923  }
31924 
31925  // zero based
31926  type_proxy<TC, TR> _ij_proxy_val(tint i, tint j) override {
31927  return this->_b_ij_proxy_val(i, j);
31928  }
31929 
31930  // zero based
31931  TC _ij_val(tint i, tint j) const override {
31932  return this->_b_ij_val(i, j);
31933  }
31934 
31935  void _transp() throw(cvmexception) override
31936  {
31937 #ifdef CVM_USE_POOL_MANAGER
31938  this->_btransp();
31939 #else
31940  this->_btransp(this->mp);
31941 #endif
31942  }
31943 
31944  void _plus_plus() override {
31945  this->_b_plus_plus();
31946  }
31947 
31948  void _minus_minus() override {
31949  this->_b_minus_minus();
31950  }
31951 
31952  tint _indofmax() const override
31953  {
31954  this->_check_ld();
31955  _bake_SM();
31956  return mSM.indofmax();
31957  }
31958 
31959  tint _indofmin() const override
31960  {
31961  this->_check_ld();
31962  _bake_SM();
31963  return mSM.indofmin();
31964  }
31965 
31966  CVector _low_up_diag(basic_array<tint,tint>& naPivots) const throw(cvmexception) override
31967  {
31968  // let temp matrix be const to get a copy of its main diagonal
31969  const basic_scbmatrix lu = this->low_up(naPivots);
31970  return lu.diag(0);
31971  }
31972 
31973  void _scalr(TR d) override {
31974  __scal<TR,TC>(this->get(), this->size(), this->incr(), d); // zero tails are supposed here
31975  }
31976 
31977  void _scalc(TC d) override {
31978  __scal<TC, TC>(this->get(), this->size(), this->incr(), d); // zero tails are supposed here
31979  }
31980 
31981  void _mult(const BaseCMatrix& m1, const BaseCMatrix& m2) throw(cvmexception) override
31982  {
31983  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
31984  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m2.nsize());
31985  _check_ne(CVM_SIZESMISMATCH, m1.nsize(), m2.msize());
31986  BaseSCMatrix mR(this->msize());
31987  mR.mult(m1, m2);
31988 #ifdef CVM_USE_POOL_MANAGER
31989  this->_resize_lu(this->msize() - 1, this->msize() - 1);
31990 #else
31991  this->_resize_lu(this->mp, this->msize() - 1, this->msize() - 1);
31992 #endif
31993  _copy_b_matrix<TR,TC, BaseSCMatrix, basic_scbmatrix>(const_cast<BaseSCMatrix&>(mR), *this, true);
31994  }
31995 
31996  void _multiply(CVector& vRes, const CVector& v, bool bLeft) const override
31997  {
31998  static const TC zero(0., 0.);
31999  static const TC one(1., 0.);
32000  this->_gbmv(bLeft, one, v, zero, vRes);
32001  }
32002 
32003  void _low_up(tint* nPivots) throw(cvmexception) override {
32004  __low_up<basic_scbmatrix>(*this, nPivots);
32005  }
32006 
32007  tint _ld_for_replace() const override {
32008  return this->mm;
32009  }
32010 
32011  tint _size_for_replace() const override {
32012  return this->mm * this->mn;
32013  }
32014 
32015  void _swap_rows(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_rows", "scbmatrix");}
32016  void _swap_cols(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_cols", "scbmatrix");}
32017  void _check_geru() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "geru", "scbmatrix");}
32018  void _check_gerc() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "gerc", "scbmatrix");}
32019  void _check_rank1update_u() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "rank1update_u", "scbmatrix");}
32020  void _check_rank1update_c() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "rank1update_c", "scbmatrix");}
32021  void _check_gemm() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "gemm", "scbmatrix");}
32022  void _check_hemm() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "hemm", "scbmatrix");}
32023  void _check_cholesky() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "cholesky", "scbmatrix");}
32024  void _check_bunch_kaufman() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "bunch_kaufman", "scbmatrix");}
32026 };
32027 
32028 
32035 template<typename TR>
32037 {
32038  typedef basic_rvector<TR> RVector;
32039  typedef basic_array<TR,TR> BaseArray;
32040  typedef Matrix<TR,TR> BaseMatrix;
32041  typedef SqMatrix<TR,TR> BaseSqMatrix;
32042  typedef basic_rmatrix<TR> BaseRMatrix;
32044 
32045 public:
32070  {
32071  }
32072 
32099  explicit basic_srsmatrix(tint nDim)
32100  : BaseSRMatrix(nDim)
32101  {
32102  }
32103 
32138  basic_srsmatrix(TR* pd, tint nDim, TR tol = basic_cvmMachSp<TR>())
32139  : BaseSRMatrix(pd, nDim, nDim, nDim * nDim)
32140  {
32141  this->_check_symmetric(tol);
32142  }
32143 
32177  basic_srsmatrix(const TR* pd, tint nDim, TR tol = basic_cvmMachSp<TR>())
32178  : BaseSRMatrix(pd, nDim, nDim, nDim * nDim)
32179  {
32180  this->_check_symmetric(tol);
32181  }
32182 
32210  : BaseSRMatrix(m.msize(), m.msize(), false)
32211  {
32212  this->_massign(m);
32213  }
32214 
32233  : BaseSRMatrix(std::move(m))
32234  {
32235  }
32236 
32262  explicit basic_srsmatrix(const BaseRMatrix& m, TR tol = basic_cvmMachSp<TR>())
32263  : BaseSRMatrix(m.msize(), m.nsize(), false)
32264  {
32265  _check_ne(CVM_SIZESMISMATCH, this->msize(), this->nsize());
32266  this->_massign(m);
32267  this->_check_symmetric(tol);
32268  }
32269 
32294  explicit basic_srsmatrix(const RVector& v)
32295  : BaseSRMatrix(v)
32296  {
32297  }
32298 
32326  : BaseSRMatrix(m._sub_pointer(nRowCol, nRowCol, nDim, nDim), nDim, m.ld(), nDim * nDim)
32327  {
32328  }
32329 
32330  TR operator () (tint nRow, tint nCol) const throw(cvmexception)
32331  {
32332  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
32333  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
32334  return this->_ij_val(nRow - CVM0, nCol - CVM0);
32335  }
32336 
32337  // returns column which is NOT l-value
32338  const RVector operator () (tint nCol) const throw(cvmexception)
32339  {
32340  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
32341  return this->_col(nCol - CVM0);
32342  }
32343 
32344  // returns row which is NOT l-value
32345  const RVector operator [] (tint nRow) const throw(cvmexception)
32346  {
32347  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
32348  return this->_row(nRow - CVM0);
32349  }
32350 
32351  // returns diagonal which is NOT l-value (since it could break symmetricity)
32352  // 0 - main, negative - low, positive - up
32353  const RVector diag(tint nDiag) const throw(cvmexception) {
32354  return this->_diag(nDiag);
32355  }
32356 
32382  basic_srsmatrix& operator = (const basic_srsmatrix& m) throw(cvmexception)
32383  {
32384  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
32385  this->_massign(m);
32386  return *this;
32387  }
32388 
32402  basic_srsmatrix& operator = (basic_srsmatrix&& m) throw(cvmexception)
32403  {
32404  // size check is in BaseSRMatrix
32405  BaseSRMatrix::operator = (std::move(m));
32406  return *this;
32407  }
32408 
32436  basic_srsmatrix& assign(const RVector& v, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
32437  {
32438  _check_gt(CVM_SIZESMISMATCH_GT, this->size(), v.size());
32439  this->_assign(v, v.incr());
32440  this->_check_symmetric(tol);
32441  return *this;
32442  }
32443 
32473  basic_srsmatrix& assign(const TR* pd, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
32474  {
32475  this->_assign(pd, 1);
32476  this->_check_symmetric(tol);
32477  return *this;
32478  }
32479 
32510  basic_srsmatrix& assign(tint nRowCol, const basic_srsmatrix& m) throw(cvmexception)
32511  {
32512  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRowCol, CVM0, this->msize() + CVM0);
32513  _check_gt(CVM_SIZESMISMATCH_GT, m.msize() + nRowCol - CVM0, this->msize());
32514  this->_assign_shifted(this->_sub_pointer_nocheck(nRowCol, nRowCol), m._pd(), m.msize(), m.nsize(), m.ld());
32515  return *this;
32516  }
32517 
32518  basic_srsmatrix& set(TR d)
32519  {
32520  this->_set(d);
32521  return *this;
32522  }
32523 
32550  basic_srsmatrix& set(tint nRow, tint nCol, TR d)
32551  {
32552  this->_set_at(nRow - CVM0, nCol - CVM0, d);
32553  return *this;
32554  }
32555 
32586  basic_srsmatrix& set_diag(tint nDiag, const RVector& vDiag) throw(cvmexception)
32587  {
32588  this->_diag(nDiag) = vDiag;
32589  if (nDiag != 0) {
32590  this->_diag(-nDiag) = vDiag;
32591  }
32592  return *this;
32593  }
32594 
32595  basic_srsmatrix& resize(tint nNewDim) throw(cvmexception)
32596  {
32597  this->_resize2(nNewDim, nNewDim);
32598  return *this;
32599  }
32600 
32628  bool operator == (const basic_srsmatrix& m) const {
32629  return this->msize() == m.msize() && this->nsize() == m.nsize() && this->_mequals(m);
32630  }
32631 
32659  bool operator != (const basic_srsmatrix& m) const {
32660  return !(this->operator == (m));
32661  }
32662 
32695  basic_srsmatrix& operator << (const basic_srsmatrix& m) throw(cvmexception)
32696  {
32697  this->_replace(m);
32698  this->_massign(m);
32699  return *this;
32700  }
32701 
32733  basic_srsmatrix operator + (const basic_srsmatrix& m) const throw(cvmexception)
32734  {
32735  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
32736  basic_srsmatrix mSum(*this);
32737  mSum._mincr(m);
32738  return mSum;
32739  }
32740 
32771  basic_srsmatrix operator - (const basic_srsmatrix& m) const throw(cvmexception)
32772  {
32773  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
32774  basic_srsmatrix mDiff(*this);
32775  mDiff._mdecr(m);
32776  return mDiff;
32777  }
32778 
32811  basic_srsmatrix& sum(const basic_srsmatrix& m1, const basic_srsmatrix& m2) throw(cvmexception)
32812  {
32813  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
32814  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
32815  this->_msum(m1, m2);
32816  return *this;
32817  }
32818 
32851  basic_srsmatrix& diff(const basic_srsmatrix& m1, const basic_srsmatrix& m2) throw(cvmexception)
32852  {
32853  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
32854  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
32855  this->_mdiff(m1, m2);
32856  return *this;
32857  }
32858 
32895  basic_srsmatrix& operator += (const basic_srsmatrix& m) throw(cvmexception)
32896  {
32897  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
32898  this->_mincr(m);
32899  return *this;
32900  }
32901 
32938  basic_srsmatrix& operator -= (const basic_srsmatrix& m) throw(cvmexception)
32939  {
32940  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
32941  this->_mdecr(m);
32942  return *this;
32943  }
32944 
32967  {
32968  static const TR mone(-1.);
32969  basic_srsmatrix mRes(*this);
32970  mRes._scalr(mone);
32971  return mRes;
32972  }
32973 
32974  // plus identity, prefix
32975  basic_srsmatrix& operator ++ ()
32976  {
32977  this->_plus_plus();
32978  return *this;
32979  }
32980 
32981  // plus identity, postfix
32982  basic_srsmatrix operator ++ (int)
32983  {
32984  this->_plus_plus();
32985  return *this;
32986  }
32987 
32988  // minus identity, prefix
32989  basic_srsmatrix& operator -- ()
32990  {
32991  this->_minus_minus();
32992  return *this;
32993  }
32994 
32995  // minus identity, postfix
32996  basic_srsmatrix operator -- (int)
32997  {
32998  this->_minus_minus();
32999  return *this;
33000  }
33001 
33003  {
33004  basic_srsmatrix mRes(*this);
33005  mRes._scalr(dMult);
33006  return mRes;
33007  }
33008 
33009  basic_srsmatrix operator / (TR dDiv) const throw(cvmexception)
33010  {
33011  basic_srsmatrix mRes(*this);
33012  mRes._div(dDiv);
33013  return mRes;
33014  }
33015 
33016  basic_srsmatrix& operator *= (TR dMult)
33017  {
33018  this->_scalr(dMult);
33019  return *this;
33020  }
33021 
33022  basic_srsmatrix& operator /= (TR dDiv) throw(cvmexception)
33023  {
33024  this->_div(dDiv);
33025  return *this;
33026  }
33027 
33028  basic_srsmatrix& normalize()
33029  {
33030  this->_normalize();
33031  return *this;
33032  }
33033 
33037  basic_srsmatrix operator ~() const {
33038  return *this;
33039  }
33040 
33044  basic_srsmatrix& transpose(const basic_srsmatrix& m) throw(cvmexception)
33045  {
33046  (*this) = m;
33047  return *this;
33048  }
33049 
33054  return *this;
33055  }
33056 
33057  RVector operator * (const RVector& v) const throw(cvmexception)
33058  {
33059  _check_ne(CVM_SIZESMISMATCH, this->nsize(), v.size());
33060  RVector vRes(this->msize());
33061  this->_multiply(vRes, v, false);
33062  return vRes;
33063  }
33064 
33065  // special exclusion since matrix product is not commutative
33066  BaseRMatrix operator * (const BaseRMatrix& m) const throw(cvmexception)
33067  {
33068  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
33069  static const TR zero = TR(0.);
33070  static const TR one = TR(1.);
33071  BaseRMatrix mRes(m.msize(), m.nsize());
33072  mRes._symm(true, *this, m, one, zero);
33073  return mRes;
33074  }
33075 
33113  BaseSRMatrix operator * (const BaseSRMatrix& m) const throw(cvmexception)
33114  {
33115  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
33116  static const TR zero = TR(0.);
33117  static const TR one = TR(1.);
33118  BaseSRMatrix mRes(this->msize());
33119  mRes._symm(true, *this, m, one, zero);
33120  return mRes;
33121  }
33122 
33123  // 6.1: reversed vector operator % returns solution of A*X=B equation
33124  // overridden to mask out operator / (TR)
33125  RVector operator / (const RVector& v) const throw(cvmexception) {
33126  return v % (*this);
33127  }
33128 
33129  // this = alpha*v*v' + beta*this
33176  basic_srsmatrix& syrk(TR alpha, const RVector& v, TR beta) throw(cvmexception)
33177  {
33178  _check_ne(CVM_SIZESMISMATCH, this->msize(), v.size());
33179  RVector vc(v); // has to guarantee incr to be 1
33180  __syrk<TR,basic_srsmatrix>(false, alpha, 1, vc, vc.size(), beta, *this);
33181  this->_flip();
33182  return *this;
33183  }
33184 
33185 // this = alpha*a*a' + beta*this or this = alpha*a'*a + beta*this
33246  basic_srsmatrix& syrk(bool bTransp, TR alpha, const BaseRMatrix& m, TR beta) throw(cvmexception)
33247  {
33248  _check_ne(CVM_SIZESMISMATCH, this->msize(), bTransp ? m.nsize() : m.msize());
33249  __syrk<TR,basic_srsmatrix>(bTransp, alpha, bTransp ? m.msize() : m.nsize(), m, m.ld(), beta, *this);
33250  this->_flip();
33251  return *this;
33252  }
33253 
33254 // this = alpha*v1*v2' + alpha*v2*v1' + beta*this
33299  basic_srsmatrix& syr2k(TR alpha, const RVector& v1, const RVector& v2, TR beta) throw(cvmexception)
33300  {
33301  _check_ne(CVM_SIZESMISMATCH, this->msize(), v1.size());
33302  _check_ne(CVM_SIZESMISMATCH, this->msize(), v2.size());
33303  RVector v1c(v1); // has to guarantee incr to be 1
33304  RVector v2c(v2);
33305  __syr2k<TR,basic_srsmatrix>(false, alpha, 1, v1c, v1c.size(), v2c, v2c.size(), beta, *this);
33306  this->_flip();
33307  return *this;
33308  }
33309 
33310 // this = alpha*a*b' + alpha*b*a' + beta*this or this = alpha*a'*b + alpha*b'*a + beta*this
33376  basic_srsmatrix& syr2k(bool bTransp, TR alpha, const BaseRMatrix& m1, const BaseRMatrix& m2, TR beta) throw(cvmexception)
33377  {
33378  if (bTransp) {
33379  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.nsize());
33380  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.nsize());
33381  _check_ne(CVM_SIZESMISMATCH, m1.msize(), m2.msize());
33382  } else {
33383  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
33384  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
33385  _check_ne(CVM_SIZESMISMATCH, m1.nsize(), m2.nsize());
33386  }
33387  __syr2k<TR,basic_srsmatrix>(bTransp, alpha, bTransp ? m1.msize() : m1.nsize(), m1, m1.ld(), m2, m2.ld(), beta, *this);
33388  this->_flip();
33389  return *this;
33390  }
33391 
33423  basic_srsmatrix& inv(const basic_srsmatrix& m) throw(cvmexception)
33424  {
33425  __inv<basic_srsmatrix>(*this, m);
33426  return *this;
33427  }
33428 
33458  basic_srsmatrix inv() const throw(cvmexception)
33459  {
33460  basic_srsmatrix mRes(this->msize());
33461  __inv<basic_srsmatrix>(mRes, *this);
33462  return mRes;
33463  }
33464 
33526  basic_srsmatrix& exp(const basic_srsmatrix& m, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
33527  {
33528  __exp_symm<basic_srsmatrix, TR>(*this, m, tol);
33529  return *this;
33530  }
33531 
33589  basic_srsmatrix exp(TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
33590  {
33591  basic_srsmatrix msRes(this->msize());
33592  __exp_symm<basic_srsmatrix, TR>(msRes, *this, tol);
33593  return msRes;
33594  }
33595 
33596 // this = v(1)*I + v(2)*m + v(3)*m^2 + ... + v(N)*m^(N-1)
33663  basic_srsmatrix& polynom(const basic_srsmatrix& m, const RVector& v) throw(cvmexception)
33664  {
33665  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
33666  RVector v1;
33667  if (v.incr() > 1) v1 << v; // to make sure incr = 1
33668  __polynom<TR,RVector>(this->get(), this->ld(), this->msize(), m._pd(), m._ldm(), v.incr() > 1 ? v1 : v);
33669  return *this;
33670  }
33671 
33672 // returns v(1)*I + v(2)*this + v(3)*this^2 + ... + v(N)*this^(N-1)
33736  basic_srsmatrix polynom(const RVector& v) const
33737  {
33738  basic_srsmatrix msRes(this->msize());
33739  RVector v1;
33740  if (v.incr() > 1) v1 << v; // to make sure incr = 1
33741  __polynom<TR,RVector>(msRes, msRes.ld(), this->msize(), this->get(), this->ld(), v.incr() > 1 ? v1 : v);
33742  return msRes;
33743  }
33744 
33787  RVector eig(BaseSRMatrix& mEigVect) const throw(cvmexception)
33788  {
33789  RVector vEig(this->msize());
33790  __eig<RVector, basic_srsmatrix, BaseSRMatrix>(vEig, *this, &mEigVect, true);
33791  return vEig;
33792  }
33793 
33824  RVector eig() const throw(cvmexception)
33825  {
33826  RVector vEig(this->msize());
33827  __eig<RVector, basic_srsmatrix, BaseSRMatrix>(vEig, *this, nullptr, true);
33828  return vEig;
33829  }
33830 
33870  BaseSRMatrix cholesky() const throw(cvmexception)
33871  {
33872  BaseSRMatrix mRes(*this);
33873  tint nOutInfo = __cholesky<BaseSRMatrix>(mRes);
33874  _check_negative(CVM_WRONGMKLARG, nOutInfo);
33875  _check_positive(CVM_NOTPOSITIVEDEFINITE, nOutInfo);
33876  mRes._clean_low_triangle();
33877  return mRes;
33878  }
33879 
33908  BaseSRMatrix bunch_kaufman(tint* nPivots) const throw(cvmexception)
33909  {
33910  BaseSRMatrix mRes(*this);
33911  __bunch_kaufman<BaseSRMatrix>(mRes, nPivots);
33912  return mRes;
33913  }
33914 
33915  basic_srsmatrix& identity()
33916  {
33917  this->_vanish();
33918  this->_plus_plus();
33919  return *this;
33920  }
33921 
33923  {
33924  this->_vanish();
33925  return *this;
33926  }
33927 
33928  basic_srsmatrix& randomize(TR dFrom, TR dTo)
33929  {
33930  this->_randomize(dFrom, dTo);
33931  return *this;
33932  }
33933 
33934  // infinity-norm - the same as 1-norm for symmetric matrices
33935  TR norminf() const override {
33936  return this->norm1();
33937  }
33938 
33944  bool is_positive_definite() const
33945  {
33946  static const TR zero = TR(0.);
33947  const TR* pd = this->_pv();
33948  const tint nSize = this->_size();
33949  const tint nNext = this->_msize() + 1;
33950  CVM_ASSERT(pd, nSize * sizeof(TR))
33951  for (tint i = 0; i < nSize; i += nNext) {
33952  if (pd[i] <= zero) {
33953  return false;
33954  }
33955  }
33956  return true;
33957  }
33958 
33966  bool equilibrate(RVector& vScalings, RVector& vB) throw(cvmexception)
33967  {
33968  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
33969  bool bRes = this->_equilibrate(vScalings);
33970  if (bRes) {
33971  for (tint i = CVM0; i < this->msize() + CVM0; ++i) {
33972  vB[i] *= vScalings[i];
33973  }
33974  }
33975  return bRes;
33976  }
33977 
33985  bool equilibrate(RVector& vScalings, BaseRMatrix& mB) throw(cvmexception)
33986  {
33987  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
33988  bool bRes = this->_equilibrate(vScalings);
33989  if (bRes) {
33990  for (tint j = CVM0; j < mB.nsize() + CVM0; ++j) {
33991  for (tint i = CVM0; i < this->msize() + CVM0; ++i) {
33992  mB(i, j) *= vScalings[i];
33993  }
33994  }
33995  }
33996  return bRes;
33997  }
33998 
34000  // special care for symmetric matrices
34001  basic_srsmatrix& _factorize(const basic_srsmatrix& m, tint* nPivots, bool& bPositiveDefinite) throw(cvmexception)
34002  {
34003  (*this) = m;
34004  tint nOutInfo = __cholesky<BaseSRMatrix>(*this);
34005  _check_negative(CVM_WRONGMKLARG, nOutInfo);
34006  if (nOutInfo > 0) {
34007  (*this) = m;
34008  __bunch_kaufman<BaseSRMatrix>(*this, nPivots);
34009  bPositiveDefinite = false;
34010  } else {
34011  bPositiveDefinite = true;
34012  }
34013  return *this;
34014  }
34015 
34016  // makes lower triangle to be equal to upper one
34017  void _flip()
34018  {
34019  if (this->msize() > 1) {
34020  const tint nM1 = this->ld() + 1, nM1m = this->ld() - 1, nM2m = this->msize() - 1;
34021  tint i = 1, j = 1, m;
34022  for (;;) {
34023  m = this->msize() - i;
34024  __copy<TR>(m, this->get() + j + nM1m, this->ld(), this->get() + j, 1);
34025  if (i >= nM2m) {
34026  break;
34027  }
34028  i++;
34029  j += nM1;
34030  }
34031  }
34032  }
34033 
34034  // redefinition of basic_array's function
34035  TR* _pd() override
34036  {
34037  return this->get();
34038  }
34039 
34040  // redefinition of basic_array's function
34041  const TR* _pd() const override {
34042  return this->get();
34043  }
34044 
34045  void _check_submatrix() const throw(cvmexception) override {
34046  throw cvmexception(CVM_SUBMATRIXNOTAVAILABLE, "srsmatrix");
34047  }
34048 
34049 protected:
34050  const TR* _pp(const BaseMatrix& m) const override { // for _msum _mdiff etc.
34051  return m.get();
34052  }
34053 
34054  void _check_ger() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "ger", "srsmatrix");}
34055  void _check_rank1update() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "rank1update", "srsmatrix");}
34056  void _check_gemm() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "gemm", "srsmatrix");}
34057  void _swap_rows(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_rows", "srsmatrix");}
34058  void _swap_cols(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_cols", "srsmatrix");}
34059 
34060  // we do nothing here - it's symmetric
34061  void _transp() override {
34062  }
34063 
34064  // returns main diagonal of low_up factorization
34065  // this call is useless for symmetric matrices. this call would mean serious CVM internal error
34066  RVector _low_up_diag(basic_array<tint,tint>&) const throw(cvmexception) override {
34067  throw cvmexception(CVM_NOTIMPLEMENTED, "_low_up_diag");
34068  }
34069 
34070  void _scalr(TR d) override {
34071  __scal<TR,TR>(this->get(), this->size(), this->incr(), d); // zero tails are supposed here
34072  }
34073 
34074  void _multiply(RVector& vRes, const RVector& v, bool) const override
34075  {
34076  RVector vTmp;
34077  basic_srsmatrix mTmp;
34078  static const TR zero = TR(0.);
34079  static const TR one = TR(1.);
34080  const TR* pDm = this->get();
34081  const TR* pDv = v;
34082  if (vRes.get() == pDv) vTmp << v;
34083  if (vRes.get() == pDm) mTmp << *this;
34084  __symv<TR,basic_srsmatrix, RVector>(vRes.get() == pDm ? mTmp : *this, one,
34085  vRes.get() == pDv ? vTmp : v, zero, vRes);
34086  }
34087 
34088  void _randomize(TR dFrom, TR dTo) override
34089  {
34090  this->BaseSRMatrix::_randomize(dFrom, dTo);
34091  this->_flip();
34092  }
34093 
34094  void _solve(const RVector& vB, RVector& vX,
34095  TR& dErr, const TR* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
34096  {
34097  // 6.1: fix for non-positive definite solutions
34098  if (!this->is_positive_definite()) {
34099  BaseSRMatrix::_solve(vB, vX, dErr, pLU, pPivots, transp_mode);
34100  return;
34101  }
34102  RVector vB1(vB); // to make sure incr = 1 and equilibrate
34103  RVector vScalings(this->msize());
34104  basic_srsmatrix m(*this);
34105  const bool bEquilibrated = m.equilibrate(vScalings, vB1);
34106  RVector vX1(vB1);
34107  __solve<TR,TR, basic_srsmatrix>(m, 1, vB1, vB1.size(), vX1, vX1.size(), dErr, pLU, pPivots, 0); // no transpose
34108  if (bEquilibrated) {
34109  for (tint i = 1; i <= this->msize(); ++i) {
34110  vX[i] = vX1[i] * vScalings[i];
34111  }
34112  } else {
34113  vX = vX1;
34114  }
34115  }
34116 
34117  void _solve(const BaseRMatrix& mB, BaseRMatrix& mX,
34118  TR& dErr, const TR* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
34119  {
34120  // 6.1: fix for non-positive definite solutions
34121  if (!this->is_positive_definite()) {
34122  BaseSRMatrix::_solve(mB, mX, dErr, pLU, pPivots, transp_mode);
34123  return;
34124  }
34125  BaseRMatrix mB1(mB); // to equilibrate
34126  RVector vScalings(this->msize());
34127  basic_srsmatrix m(*this);
34128  const bool bEquilibrated = m.equilibrate(vScalings, mB1);
34129  mX = mB1;
34130  __solve<TR,TR, basic_srsmatrix>(m, mB.nsize(), mB, mB.ld(), mX, mX.ld(), dErr, pLU, pPivots, 0); // no transpose
34131  if (bEquilibrated) {
34132  for (tint j = 1; j <= mX.nsize(); ++j) {
34133  for (tint i = 1; i <= this->msize(); ++i) {
34134  mX(i, j) *= vScalings[i];
34135  }
34136  }
34137  }
34138  }
34139 
34140  // matrix determinant
34141  TR _det() const throw(cvmexception) override
34142  {
34143  TR dDet = TR(0.);
34144  switch (this->msize()) {
34145  case 0:
34146  break;
34147  case 1:
34148  dDet = this->_ij_val(0, 0);
34149  break;
34150  case 2:
34151  dDet = this->_ij_val(0, 0) * this->_ij_val(1, 1) -
34152  this->_ij_val(1, 0) * this->_ij_val(0, 1);
34153  break;
34154  default:
34155  try {
34156  static const TR one(1.);
34157  bool bPositiveDefinite = false;
34158  basic_srsmatrix m(this->msize());
34159  basic_array<tint,tint> nPivots(this->msize());
34160  m._factorize(*this, nPivots, bPositiveDefinite);
34161 
34162  tint i;
34163  dDet = one;
34164  if (bPositiveDefinite) {
34165  const RVector vUpDiag = m.diag(0);
34166  for (i = 1; i <= this->msize(); ++i) {
34167  dDet *= vUpDiag[i] * vUpDiag[i]; //here we use Cholesky factorization
34168  }
34169  } else {
34170  const RVector vEig = this->eig();
34171  for (i = 1; i <= this->msize(); ++i) {
34172  dDet *= vEig[i]; //here we use eigenvalues. probably there is a better way.
34173  }
34174  }
34175  }
34176  catch (const cvmexception& e) {
34177  if (e.cause() != CVM_WRONGBUNCHKAUFMANFACTOR) throw e;
34178  }
34179  break;
34180  }
34181  return dDet;
34182  }
34183 
34184  // matrix equilibration helper
34185  bool _equilibrate(RVector& vScalings) throw(cvmexception)
34186  {
34187  _check_ne(CVM_SIZESMISMATCH, this->msize(), vScalings.size());
34188  bool bRes = false;
34189  TR dCond(0.);
34190  TR dMax = TR();
34191  static const TR sp = basic_cvmMachSp<TR>();
34192  static const TR sp_inv = TR(1.) / sp;
34193 
34194  __poequ<TR,basic_srsmatrix, RVector>(*this, vScalings, dCond, dMax);
34195 
34196  if (dCond < TR(0.1) || _abs(dMax) <= sp || _abs(dMax) >= sp_inv) {
34197  bRes = true;
34198  for (tint i = 0; i < this->msize(); ++i) {
34199  for (tint j = i; j < this->msize(); ++j) {
34200  this->get()[this->ld() * j + i] *= vScalings[i + CVM0] * vScalings[j + CVM0];
34201  }
34202  }
34203  }
34204  return bRes;
34205  }
34206 
34207  // sets both elements to keep matrix symmetric, checks ranges
34208  // zero based
34209  void _set_at(tint nRow, tint nCol, TR val) throw(cvmexception)
34210  {
34211  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, TINT_ZERO, this->msize());
34212  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, TINT_ZERO, this->nsize());
34213  this->get()[this->ld() * nCol + nRow] = val;
34214  if (nRow != nCol) {
34215  this->get()[this->ld() * nRow + nCol] = val;
34216  }
34217  }
34218 
34219  void _check_symmetric(TR tol) const throw(cvmexception)
34220  {
34221  for (tint j = 0; j < this->nsize(); ++j) {
34222  for (tint i = 0; i < this->msize(); ++i) {
34223  if (i != j && _abs(this->get()[this->ld() * j + i] - this->get()[this->ld() * i + j]) > tol) {
34224  throw cvmexception(CVM_MATRIXNOTSYMMETRIC);
34225  }
34226  }
34227  }
34228  }
34230 };
34231 
34232 
34240 template<typename TR, typename TC>
34241 class basic_schmatrix : public basic_scmatrix<TR,TC>
34242 {
34243  typedef basic_rvector<TR> RVector;
34244  typedef basic_cvector<TR,TC> CVector;
34245  typedef Matrix<TR,TC> BaseMatrix;
34248 
34249 public:
34272  {
34273  }
34274 
34301  explicit basic_schmatrix(tint nDim)
34302  : BaseSCMatrix(nDim)
34303  {
34304  }
34305 
34342  basic_schmatrix(TC* pd, tint nDim, TR tol = basic_cvmMachSp<TR>())
34343  : BaseSCMatrix(pd, nDim, nDim, nDim * nDim)
34344  {
34345  this->_check_hermitian(tol);
34346  }
34347 
34383  basic_schmatrix(const TC* pd, tint nDim, TR tol = basic_cvmMachSp<TR>())
34384  : BaseSCMatrix(pd, nDim, nDim, nDim * nDim)
34385  {
34386  this->_check_hermitian(tol);
34387  }
34388 
34420  : BaseSCMatrix(m.msize(), m.msize(), false)
34421  {
34422  this->_massign(m);
34423  }
34424 
34443  : BaseSCMatrix(std::move(m))
34444  {
34445  }
34446 
34473  explicit basic_schmatrix(const BaseCMatrix& m, TR tol = basic_cvmMachSp<TR>())
34474  : BaseSCMatrix(m.msize(), m.nsize(), false)
34475  {
34476  _check_ne(CVM_SIZESMISMATCH, this->msize(), this->nsize());
34477  this->_massign(m);
34478  this->_check_hermitian(tol);
34479  }
34480 
34507  explicit basic_schmatrix(const RVector& v)
34508  : BaseSCMatrix(v.size(), v.size(), true)
34509  {
34510  __copy2<TR,TC>(this->get(), v.size(), this->ld() + 1, v._pd(), nullptr, v.incr());
34511  }
34512 
34535  : BaseSCMatrix(m.msize(), m.msize(), true)
34536  {
34537  __copy2<TR,TC>(this->get(), this->size(), this->incr(), m._pd(), nullptr);
34538  }
34539 
34569  basic_schmatrix(const TR* pRe, const TR* pIm, tint nDim, TR tol = basic_cvmMachSp<TR>())
34570  : BaseSCMatrix(pRe, pIm, nDim)
34571  {
34572  this->_check_hermitian(tol);
34573  }
34574 
34604  basic_schmatrix(const basic_srmatrix<TR>& mRe, const basic_srmatrix<TR>& mIm, TR tol = basic_cvmMachSp<TR>())
34605  : BaseSCMatrix(mRe, mIm)
34606  {
34607  this->_check_hermitian(tol);
34608  }
34609 
34637  : BaseSCMatrix(m._sub_pointer(nRowCol, nRowCol, nDim, nDim), nDim, m.ld(), nDim * nDim)
34638  {
34639  }
34640 
34641  TC operator () (tint nRow, tint nCol) const throw(cvmexception)
34642  {
34643  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
34644  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
34645  return this->_ij_val(nRow - CVM0, nCol - CVM0);
34646  }
34647 
34648  // returns column which is NOT l-value
34649  const CVector operator () (tint nCol) const throw(cvmexception)
34650  {
34651  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nCol, CVM0, this->nsize() + CVM0);
34652  return this->_col(nCol - CVM0);
34653  }
34654 
34655  // returns row which is NOT l-value
34656  const CVector operator [] (tint nRow) const throw(cvmexception)
34657  {
34658  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRow, CVM0, this->msize() + CVM0);
34659  return this->_row(nRow - CVM0);
34660  }
34661 
34662  // returns diagonal which IS NOT l-value
34663  // 0 - main, negative - low, positive - up
34664  const CVector diag(tint nDiag) const throw(cvmexception) {
34665  return this->_diag(nDiag);
34666  }
34667 
34668  // real part (symmetric)
34669  const basic_srsmatrix<TR> real() const
34670  {
34671  basic_srsmatrix<TR> mRet(this->msize());
34672  __copy<TR>(this->size(), __get_real_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
34673  return mRet;
34674  }
34675 
34676  // imaginary part (NOT symmetric)
34677  const basic_srmatrix<TR> imag() const
34678  {
34679  basic_srmatrix<TR> mRet(this->msize());
34680  __copy<TR>(this->size(), __get_imag_p<TR>(this->get()), this->incr() * 2, mRet, mRet.incr());
34681  return mRet;
34682  }
34683 
34716  basic_schmatrix& operator = (const basic_schmatrix& m) throw(cvmexception)
34717  {
34718  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
34719  this->_massign(m);
34720  return *this;
34721  }
34722 
34736  basic_schmatrix& operator = (basic_schmatrix&& m) throw(cvmexception)
34737  {
34738  // size check is in BaseSCMatrix
34739  BaseSCMatrix::operator = (std::move(m));
34740  return *this;
34741  }
34742 
34771  basic_schmatrix& assign(const CVector& v, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
34772  {
34773  _check_gt(CVM_SIZESMISMATCH_GT, this->size(), v.size());
34774  this->_assign(v, v.incr());
34775  this->_check_hermitian(tol);
34776  return *this;
34777  }
34778 
34809  basic_schmatrix& assign(const TC* pd, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
34810  {
34811  this->_assign(pd, 1);
34812  this->_check_hermitian(tol);
34813  return *this;
34814  }
34815 
34846  basic_schmatrix& assign(tint nRowCol, const basic_schmatrix& m) throw(cvmexception)
34847  {
34848  _check_lt_ge(CVM_OUTOFRANGE_LTGE, nRowCol, CVM0, this->msize() + CVM0);
34849  _check_gt(CVM_SIZESMISMATCH_GT, m.msize() + nRowCol - CVM0, this->msize());
34850  this->_assign_shifted(this->_sub_pointer_nocheck(nRowCol, nRowCol), m._pd(), m.msize(), m.nsize(), m.ld());
34851  return *this;
34852  }
34853 
34883  basic_schmatrix& set(tint nRow, tint nCol, TC c) throw(cvmexception)
34884  {
34885  this->_set_at(nRow - CVM0, nCol - CVM0, c);
34886  return *this;
34887  }
34888 
34922  basic_schmatrix& set_diag(tint nDiag, const CVector& vDiag) throw(cvmexception)
34923  {
34924  if (nDiag == 0) throw cvmexception(CVM_BREAKS_HERMITIANITY, "set_main_diag");
34925  const tint nD = _abs(nDiag);
34926  const tint nSize = vDiag.size();
34927  _check_ne(CVM_SIZESMISMATCH, this->msize() - nD, nSize);
34928  const tint nShift = nDiag * this->ld();
34929  const tint nIncr = this->ld() + 1;
34930  TC* pD1 = this->get() + (nDiag > 0 ? nShift : nD);
34931  TC* pD2 = this->get() + (nDiag > 0 ? nD : nShift);
34932  __copy<TC>(nSize, vDiag, vDiag.incr(), pD1, nIncr);
34933  __copy<TC>(nSize, vDiag, vDiag.incr(), pD2, nIncr);
34934  __conj<TC>(pD2, nSize, nIncr);
34935  return *this;
34936  }
34937 
34965  basic_schmatrix& set_main_diag(const RVector& vDiag) throw(cvmexception)
34966  {
34967  _check_ne(CVM_SIZESMISMATCH, this->msize(), vDiag.size());
34968  __copy_real<TR,TC>(this->get(), this->msize(), this->ld() + 1, vDiag, vDiag.incr());
34969  return *this;
34970  }
34971 
34998  basic_schmatrix& assign_real(const basic_srsmatrix<TR>& mRe) throw(cvmexception)
34999  {
35000  _check_ne(CVM_SIZESMISMATCH, this->msize(), mRe.msize());
35001  _check_ne(CVM_SIZESMISMATCH, this->nsize(), mRe.nsize());
35002  __copy_real<TR,TC>(this->get(), this->size(), this->incr(), mRe._pd(), mRe.incr());
35003  return *this;
35004  }
35005 
35006  // fills real part
35007  basic_schmatrix& set_real(TR d)
35008  {
35009  this->_set_real_number(d);
35010  return *this;
35011  }
35012 
35013  basic_schmatrix& resize(tint nNewDim) throw(cvmexception)
35014  {
35015  this->_resize2(nNewDim, nNewDim);
35016  return *this;
35017  }
35018 
35045  bool operator == (const basic_schmatrix& m) const {
35046  return this->msize() == m.msize() && this->nsize() == m.nsize() && this->_mequals(m);
35047  }
35048 
35076  bool operator != (const basic_schmatrix& m) const {
35077  return !(this->operator == (m));
35078  }
35079 
35114  basic_schmatrix& operator << (const basic_schmatrix& m) throw(cvmexception)
35115  {
35116  this->_replace(m);
35117  this->_massign(m);
35118  return *this;
35119  }
35120 
35150  basic_schmatrix operator + (const basic_schmatrix& m) const throw(cvmexception)
35151  {
35152  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
35153  basic_schmatrix mSum(*this);
35154  mSum._mincr(m);
35155  return mSum;
35156  }
35157 
35186  basic_schmatrix operator - (const basic_schmatrix& m) const throw(cvmexception)
35187  {
35188  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
35189  basic_schmatrix mDiff(*this);
35190  mDiff._mdecr(m);
35191  return mDiff;
35192  }
35193 
35223  basic_schmatrix& sum(const basic_schmatrix& m1, const basic_schmatrix& m2) throw(cvmexception)
35224  {
35225  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
35226  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
35227  this->_msum(m1, m2);
35228  return *this;
35229  }
35230 
35260  basic_schmatrix& diff(const basic_schmatrix& m1, const basic_schmatrix& m2) throw(cvmexception)
35261  {
35262  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
35263  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
35264  this->_mdiff(m1, m2);
35265  return *this;
35266  }
35267 
35303  basic_schmatrix& operator += (const basic_schmatrix& m) throw(cvmexception)
35304  {
35305  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
35306  this->_mincr(m);
35307  return *this;
35308  }
35309 
35345  basic_schmatrix& operator -= (const basic_schmatrix& m) throw(cvmexception)
35346  {
35347  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
35348  this->_mdecr(m);
35349  return *this;
35350  }
35351 
35353  {
35354  static const TR mone(-1.);
35355  basic_schmatrix mRes(*this);
35356  mRes._scalr(mone);
35357  return mRes;
35358  }
35359 
35360  // plus identity, prefix
35361  basic_schmatrix& operator ++ ()
35362  {
35363  this->_plus_plus();
35364  return *this;
35365  }
35366 
35367  // plus identity, postfix
35368  basic_schmatrix operator ++ (int)
35369  {
35370  this->_plus_plus();
35371  return *this;
35372  }
35373 
35374  // minus identity, prefix
35375  basic_schmatrix& operator -- ()
35376  {
35377  this->_minus_minus();
35378  return *this;
35379  }
35380 
35381  // minus identity, postfix
35382  basic_schmatrix operator -- (int)
35383  {
35384  this->_minus_minus();
35385  return *this;
35386  }
35387 
35389  {
35390  basic_schmatrix mRes(*this);
35391  mRes._scalr(dMult);
35392  return mRes;
35393  }
35394 
35395  basic_schmatrix operator / (TR dDiv) const throw(cvmexception)
35396  {
35397  basic_schmatrix mRes(*this);
35398  mRes._div(dDiv);
35399  return mRes;
35400  }
35401 
35402  BaseSCMatrix operator * (TC cMult) const
35403  {
35404  BaseSCMatrix mRes(*this);
35405  mRes._scalc(cMult);
35406  return mRes;
35407  }
35408 
35409  BaseSCMatrix operator / (TC cDiv) const throw(cvmexception)
35410  {
35411  BaseSCMatrix mRes(*this);
35412  mRes._div(cDiv);
35413  return mRes;
35414  }
35415 
35416  basic_schmatrix& operator *= (TR dMult)
35417  {
35418  this->_scalr(dMult);
35419  return *this;
35420  }
35421 
35422  basic_schmatrix& operator /= (TR dDiv) throw(cvmexception)
35423  {
35424  this->_div(dDiv);
35425  return *this;
35426  }
35427 
35428  // array normalizing
35429  basic_schmatrix& normalize()
35430  {
35431  this->_normalize();
35432  return *this;
35433  }
35434 
35435 // 6.1: transposed (not conjugated) matrix
35473  basic_schmatrix operator !() const throw(cvmexception)
35474  {
35475  basic_schmatrix mRes(*this);
35476  return mRes.transpose();
35477  }
35478 
35482  basic_schmatrix operator ~() const {
35483  return *this;
35484  }
35485 
35525  basic_schmatrix& transpose(const basic_schmatrix& m) throw(cvmexception)
35526  {
35527  (*this) = m;
35528  return this->transpose();
35529  }
35530 
35534  basic_schmatrix& conj(const basic_schmatrix& m) throw(cvmexception)
35535  {
35536  (*this) = m;
35537  return *this;
35538  }
35539 
35540 // 6.1: transposed (not conjugated) matrix
35579  basic_schmatrix& transpose() throw(cvmexception)
35580  {
35581  this->_transp();
35582  return *this;
35583  }
35584 
35589  return *this;
35590  }
35591 
35592  CVector operator * (const CVector& v) const throw(cvmexception)
35593  {
35594  _check_ne(CVM_SIZESMISMATCH, this->nsize(), v.size());
35595  CVector vRes(this->msize());
35596  this->_multiply(vRes, v, false);
35597  return vRes;
35598  }
35599 
35600  // special exclusion since matrix product is not commutative
35601  BaseCMatrix operator * (const BaseCMatrix& m) const throw(cvmexception)
35602  {
35603  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
35604  static const TR zero = TR(0.);
35605  static const TR one = TR(1.);
35606  BaseCMatrix mRes(m.msize(), m.nsize());
35607  mRes._hemm(true, *this, m, one, zero);
35608  return mRes;
35609  }
35610 
35643  BaseSCMatrix operator * (const BaseSCMatrix& m) const throw(cvmexception)
35644  {
35645  _check_ne(CVM_SIZESMISMATCH, this->nsize(), m.msize());
35646  static const TR zero = TR(0.);
35647  static const TR one = TR(1.);
35648  BaseSCMatrix mRes(this->msize());
35649  mRes._hemm(true, *this, m, one, zero);
35650  return mRes;
35651  }
35652 
35653  // 6.1: reversed vector operator % returns solution of A*X=B equation
35654  // overridden to mask out operator / (TC)
35655  CVector operator / (const CVector& v) const throw(cvmexception) {
35656  return v % (*this);
35657  }
35658 
35659 // this = alpha*v*v' + beta*this
35707  basic_schmatrix& herk(TR alpha, const CVector& v, TR beta) throw(cvmexception)
35708  {
35709  _check_ne(CVM_SIZESMISMATCH, this->msize(), v.size());
35710  CVector vc(v); // has to guarantee incr to be 1
35711  __herk<TR,TC, basic_schmatrix>(false, alpha, 1, vc, vc.size(), beta, *this);
35712  this->_flip();
35713  return *this;
35714  }
35715 
35716 // this = alpha*a*a' + beta*this or this = alpha*a'*a + beta*this
35781  basic_schmatrix& herk(bool bTransp, TR alpha, const BaseCMatrix& m, TR beta) throw(cvmexception)
35782  {
35783  _check_ne(CVM_SIZESMISMATCH, this->msize(), bTransp ? m.nsize() : m.msize());
35784  __herk<TR,TC, basic_schmatrix>(bTransp, alpha, bTransp ? m.msize() : m.nsize(), m, m.ld(), beta, *this);
35785  this->_flip();
35786  return *this;
35787  }
35788 
35789 // this = alpha*v1*v2' + alpha*v2*v1' + beta*this
35836  basic_schmatrix& her2k(TC alpha, const CVector& v1, const CVector& v2, TR beta) throw(cvmexception)
35837  {
35838  _check_ne(CVM_SIZESMISMATCH, this->msize(), v1.size());
35839  _check_ne(CVM_SIZESMISMATCH, this->msize(), v2.size());
35840  CVector v1c(v1); // has to guarantee incr to be 1
35841  CVector v2c(v2);
35842  __her2k<TR,TC, basic_schmatrix>(false, alpha, 1, v1c, v1c.size(), v2c, v2c.size(), beta, *this);
35843  this->_flip();
35844  return *this;
35845  }
35846 
35847 // this = alpha*a*b' + alpha*b*a' + beta*this or this = alpha*a'*b + alpha*b'*a + beta*this
35925  basic_schmatrix& her2k(bool bTransp, TC alpha, const BaseCMatrix& m1, const BaseCMatrix& m2, TR beta) throw(cvmexception)
35926  {
35927  if (bTransp) {
35928  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.nsize());
35929  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.nsize());
35930  _check_ne(CVM_SIZESMISMATCH, m1.msize(), m2.msize());
35931  } else {
35932  _check_ne(CVM_SIZESMISMATCH, this->msize(), m1.msize());
35933  _check_ne(CVM_SIZESMISMATCH, this->msize(), m2.msize());
35934  _check_ne(CVM_SIZESMISMATCH, m1.nsize(), m2.nsize());
35935  }
35936  __her2k<TR,TC, basic_schmatrix>(bTransp, alpha, bTransp ? m1.msize() : m1.nsize(), m1, m1.ld(), m2, m2.ld(), beta, *this);
35937  this->_flip();
35938  return *this;
35939  }
35940 
35973  basic_schmatrix& inv(const basic_schmatrix& m) throw(cvmexception)
35974  {
35975  __inv<basic_schmatrix>(*this, m);
35976  return *this;
35977  }
35978 
36009  basic_schmatrix inv() const throw(cvmexception)
36010  {
36011  basic_schmatrix mRes(this->msize());
36012  __inv<basic_schmatrix>(mRes, *this);
36013  return mRes;
36014  }
36015 
36100  basic_schmatrix& exp(const basic_schmatrix& m, TR tol = basic_cvmMachSp<TR>()) throw(cvmexception)
36101  {
36102  __exp_symm<basic_schmatrix, TR>(*this, m, tol);
36103  return *this;
36104  }
36105 
36187  basic_schmatrix exp(TR tol = basic_cvmMachSp<TR>()) const throw(cvmexception)
36188  {
36189  basic_schmatrix msRes(this->msize());
36190  __exp_symm<basic_schmatrix, TR>(msRes, *this, tol);
36191  return msRes;
36192  }
36193 
36194 // this = v(1)*I + v(2)*m + v(3)*m^2 + ... + v(N)*m^(N-1)
36284  basic_schmatrix& polynom(const basic_schmatrix& m, const RVector& v) throw(cvmexception)
36285  {
36286  _check_ne(CVM_SIZESMISMATCH, this->msize(), m.msize());
36287  CVector vc(v);
36288  __polynom<TC, CVector>(this->get(), this->ld(), this->msize(), m._pd(), m._ldm(), vc);
36289  return *this;
36290  }
36291 
36292 // returns v(1)*I + v(2)*this + v(3)*this^2 + ... + v(N)*this^(N-1)
36380  basic_schmatrix polynom(const RVector& v) const
36381  {
36382  basic_schmatrix msRes(this->msize());
36383  CVector vc(v);
36384  __polynom<TC, CVector>(msRes, msRes.ld(), this->msize(), this->get(), this->ld(), vc);
36385  return msRes;
36386  }
36387 
36441  RVector eig(BaseSCMatrix& mEigVect) const throw(cvmexception)
36442  {
36443  RVector vEig(this->msize());
36444  // we don't use _eig here since this is the special case - hermitian matrix
36445  __eig<RVector, basic_schmatrix, BaseSCMatrix>(vEig, *this, &mEigVect, true);
36446  return vEig;
36447  }
36448 
36480  RVector eig() const throw(cvmexception)
36481  {
36482  RVector vEig(this->msize());
36483  // we don't use _eig here since this is the special case - hermitian matrix
36484  __eig<RVector, basic_schmatrix, BaseSCMatrix>(vEig, *this, nullptr, true);
36485  return vEig;
36486  }
36487 
36528  BaseSCMatrix cholesky() const throw(cvmexception)
36529  {
36530  BaseSCMatrix mRes(*this);
36531  tint nOutInfo = __cholesky<BaseSCMatrix>(mRes);
36532  _check_negative(CVM_WRONGMKLARG, nOutInfo);
36533  _check_positive(CVM_NOTPOSITIVEDEFINITE, nOutInfo);
36534  mRes._clean_low_triangle();
36535  return mRes;
36536  }
36537 
36566  BaseSCMatrix bunch_kaufman(tint* nPivots) const throw(cvmexception)
36567  {
36568  BaseSCMatrix mRes(*this);
36569  __bunch_kaufman<BaseSCMatrix>(mRes, nPivots);
36570  return mRes;
36571  }
36572 
36573  basic_schmatrix& identity()
36574  {
36575  this->_vanish();
36576  this->_plus_plus();
36577  return *this;
36578  }
36579 
36581  {
36582  this->_vanish();
36583  return *this;
36584  }
36585 
36586  basic_schmatrix& randomize_real(TR dFrom, TR dTo)
36587  {
36588  this->_randomize_real(dFrom, dTo);
36589  return *this;
36590  }
36591 
36592  basic_schmatrix& randomize_imag(TR dFrom, TR dTo)
36593  {
36594  this->_randomize_imag(dFrom, dTo);
36595  return *this;
36596  }
36597 
36598  // infinity-norm - the same as 1-norm for symmetric matrices
36599  TR norminf() const override
36600  {
36601  return this->norm1();
36602  }
36603 
36609  bool is_positive_definite() const
36610  {
36611  static const TR zero = TR(0.);
36612  const TC* pd = this->_pv();
36613  const tint nSize = this->_size();
36614  const tint nNext = this->_msize() + 1;
36615  CVM_ASSERT(pd, nSize * sizeof(TC))
36616  for (tint i = 0; i < nSize; i += nNext) {
36617  if (pd[i].real() <= zero) { // real numbers on main diagonal
36618  return false;
36619  }
36620  }
36621  return true;
36622  }
36623 
36631  bool equilibrate(basic_rvector<TR>& vScalings, CVector& vB) throw(cvmexception)
36632  {
36633  _check_ne(CVM_SIZESMISMATCH, this->msize(), vB.size());
36634  bool bRes = this->_equilibrate(vScalings);
36635  if (bRes) {
36636  for (tint i = CVM0; i < this->msize() + CVM0; ++i) {
36637  vB[i] *= vScalings[i];
36638  }
36639  }
36640  return bRes;
36641  }
36642 
36650  bool equilibrate(basic_rvector<TR>& vScalings, BaseCMatrix& mB) throw(cvmexception)
36651  {
36652  _check_ne(CVM_SIZESMISMATCH, this->msize(), mB.msize());
36653  bool bRes = this->_equilibrate(vScalings);
36654  if (bRes) {
36655  for (tint j = CVM0; j <= mB.nsize() + CVM0; ++j) {
36656  for (tint i = CVM0; i <= this->msize() + CVM0; ++i) {
36657  mB(i, j) *= vScalings[i];
36658  }
36659  }
36660  }
36661  return bRes;
36662  }
36663 
36665  // special care for symmetric matrices
36666  basic_schmatrix& _factorize(const basic_schmatrix& m, tint* nPivots, bool& bPositiveDefinite) throw(cvmexception)
36667  {
36668  (*this) = m;
36669  tint nOutInfo = __cholesky<BaseSCMatrix>(*this);
36670  _check_negative(CVM_WRONGMKLARG, nOutInfo);
36671  if (nOutInfo > 0) {
36672  (*this) = m;
36673  __bunch_kaufman<BaseSCMatrix>(*this, nPivots);
36674  bPositiveDefinite = false;
36675  } else {
36676  bPositiveDefinite = true;
36677  }
36678  return *this;
36679  }
36680 
36681  // makes lower triangle to be equal to conjugated upper one
36682  void _flip()
36683  {
36684  if (this->msize() > 1) {
36685  const tint nM1 = this->ld() + 1, nM1m = this->ld() - 1, nM2m = this->msize() - 1;
36686  tint i = 1, j = 1, m;
36687  for (;;) {
36688  m = this->msize() - i;
36689  __copy<TC>(m, this->get() + j + nM1m, this->ld(), this->get() + j, 1);
36690  __conj<TC>(this->get() + j, m, 1);
36691  if (i >= nM2m) break;
36692  ++i;
36693  j += nM1;
36694  }
36695  }
36696  }
36697 
36698  // redefinition of basic_array's function
36699  TC* _pd() override {
36700  return this->get();
36701  }
36702 
36703  // redefinition of basic_array's function
36704  const TC* _pd() const override {
36705  return this->get();
36706  }
36707 
36708  void _check_submatrix() const throw(cvmexception) override {
36709  throw cvmexception(CVM_SUBMATRIXNOTAVAILABLE, "schmatrix");
36710  }
36711 
36712 protected:
36713  const TC* _pp(const BaseMatrix& m) const override { // for _msum _mdiff etc.
36714  return m.get();
36715  }
36716 
36717  // not applicable - see below
36718  basic_schmatrix& set(TC z) throw(cvmexception)
36719  {
36720  this->_set(z);
36721  return *this;
36722  }
36723 
36724  void _set(TC) throw(cvmexception) override {
36725  throw cvmexception(CVM_BREAKS_HERMITIANITY, "set_real");
36726  }
36727 
36728  void _randomize_real(TR dFrom, TR dTo) override
36729  {
36730  this->BaseSCMatrix::_randomize_real(dFrom, dTo);
36731  this->_flip();
36732  this->_make_main_diag_real();
36733  }
36734 
36735  void _randomize_imag(TR dFrom, TR dTo) override
36736  {
36737  this->BaseSCMatrix::_randomize_imag(dFrom, dTo);
36738  this->_flip();
36739  this->_make_main_diag_real();
36740  }
36741 
36742  void _transp() override {
36743  this->_sq_transp();
36744  }
36745 
36746  //6.1: unlike transp, this one does nothing for hermitian matrices
36747  void _conj() override {
36748  }
36749 
36750  // returns main diagonal of low_up factorization
36751  CVector _low_up_diag(basic_array<tint,tint>&) const throw(cvmexception) override
36752  {
36753  // well, this stuff is useless for symmetric matrices. this call would mean serious CVM internal error
36754  throw cvmexception(CVM_NOTIMPLEMENTED, "_low_up_diag");
36755  }
36756 
36757  void _scalr(TR d) override {
36758  __scal<TR,TC>(this->get(), this->size(), this->incr(), d);
36759  }
36760 
36761  void _scalc(TC d) override {
36762  __scal<TC, TC>(this->get(), this->size(), this->incr(), d);
36763  }
36764 
36765  void _multiply(CVector& vRes, const CVector& v, bool bLeft) const override
36766  {
36767  // 6.1 fix for left-sided multiplication
36768  if (bLeft) {
36769  BaseCMatrix::_multiply(vRes, v, bLeft);
36770  } else {
36771  CVector vTmp;
36772  basic_schmatrix mTmp;
36773  static const TR zero = TR(0.);
36774  static const TR one = TR(1.);
36775  const TC* pDm = this->get();
36776  const TC* pDv = v;
36777  if (vRes.get() == pDv) vTmp << v;
36778  if (vRes.get() == pDm) mTmp << *this;
36779  __shmv<TC, basic_schmatrix, CVector>(vRes.get() == pDm ? mTmp : *this, one,
36780  vRes.get() == pDv ? vTmp : v, zero, vRes);
36781  }
36782  }
36783 
36784  // sets both elements to keep matrix hermitian, checks ranges
36785  // zero based
36786  void _set_at(tint nRow, tint nCol, TC val) throw(cvmexception)
36787  {
36788  _check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
36789  _check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
36790  if (nRow == nCol && _abs(val.imag()) > basic_cvmMachMin<TR>()) { // only reals on main diagonal
36791  throw cvmexception(CVM_BREAKS_HERMITIANITY, "real number");
36792  }
36793  this->get()[this->ld() * nCol + nRow] = val;
36794  if (nRow != nCol) {
36795  this->get()[this->ld() * nRow + nCol] = _conjugate(val);
36796  }
36797  }
36798 
36799  void _check_hermitian(TR tol) const throw(cvmexception)
36800  {
36801  TR discr;
36802  TC c1, c2;
36803  for (tint j = 0; j < this->nsize(); ++j) {
36804  for (tint i = 0; i < this->msize(); ++i) {
36805  if (i == j) {
36806  discr = _abs(this->get()[this->ld() * j + i].imag());
36807  if (discr > tol) { // real numbers on main diagonal
36808  throw cvmexception(CVM_MATRIXNOTHERMITIAN, discr, tol);
36809  }
36810  continue;
36811  }
36812  c1 = this->get()[this->ld() * j + i];
36813  c2 = this->get()[this->ld() * i + j];
36814  if (!_conjugated<TR>(c1, c2, tol)) {
36815  throw cvmexception(CVM_NOT_CONJUGATED, c1.real(), c1.imag(), c2.real(), c2.imag(), tol);
36816  }
36817  }
36818  }
36819  }
36820 
36821  void _solve(const CVector& vB, CVector& vX, TR& dErr,
36822  const TC* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
36823  {
36824  // 6.1: fix for non-positive definite solutions (we also need to call base version for transposed mode)
36825  if (transp_mode == 1 || !this->is_positive_definite()) {
36826  BaseSCMatrix::_solve(vB, vX, dErr, pLU, pPivots, transp_mode);
36827  return;
36828  }
36829  CVector vB1(vB); // to make sure incr = 1 and equilibrate
36830  basic_rvector<TR> vScalings(this->msize());
36831  basic_schmatrix m(*this);
36832  const bool bEquilibrated = m.equilibrate(vScalings, vB1);
36833  CVector vX1(vB1); // to make sure incr = 1
36834  __solve<TR,TC, basic_schmatrix>(m, 1, vB1, vB1.size(), vX1, vX1.size(), dErr, pLU, pPivots, 0); // no transpose
36835 
36836  if (bEquilibrated) {
36837  for (tint i = CVM0; i <= this->msize() - (1 - CVM0); ++i) {
36838  vX[i] = vX1[i] * vScalings[i];
36839  }
36840  } else {
36841  vX = vX1;
36842  }
36843  }
36844 
36845  void _solve(const BaseCMatrix& mB, BaseCMatrix& mX, TR& dErr,
36846  const TC* pLU, const tint* pPivots, int transp_mode) const throw(cvmexception) override
36847  {
36848  // 6.1: fix for non-positive definite solutions (we also need to call base version for transposed mode)
36849  if (transp_mode == 1 || !this->is_positive_definite()) {
36850  BaseSCMatrix::_solve(mB, mX, dErr, pLU, pPivots, transp_mode);
36851  return;
36852  }
36853  BaseCMatrix mB1(mB); // to equilibrate
36854  basic_rvector<TR> vScalings(this->msize());
36855  basic_schmatrix m(*this);
36856  const bool bEquilibrated = m.equilibrate(vScalings, mB1);
36857  mX = mB1;
36858  __solve<TR,TC, basic_schmatrix>(m, mB.nsize(), mB, mB.ld(), mX, mX.ld(), dErr, pLU, pPivots, 0); // no transpose
36859  if (bEquilibrated) {
36860  for (tint j = CVM0; j < mX.nsize() + CVM0; ++j) {
36861  for (tint i = CVM0; i < this->msize() + CVM0; ++i) {
36862  mX(i, j) *= vScalings[i];
36863  }
36864  }
36865  }
36866  }
36867 
36868  // matrix determinant
36869  TC _det() const throw(cvmexception) override
36870  {
36871  TC dDet = TC(0.);
36872  switch (this->msize()) {
36873  case 0:
36874  break;
36875  case 1:
36876  dDet = this->_ij_val(0, 0);
36877  break;
36878  case 2:
36879  dDet = this->_ij_val(0, 0) * this->_ij_val(1, 1) -
36880  this->_ij_val(1, 0) * this->_ij_val(0, 1);
36881  break;
36882  default:
36883  try {
36884  static const TC one(1., 0.);
36885  bool bPositiveDefinite = false;
36886  basic_schmatrix m(this->msize());
36887  basic_array<tint,tint> nPivots(this->msize());
36888  m._factorize(*this, nPivots, bPositiveDefinite);
36889 
36890  tint i;
36891  dDet = one;
36892  if (bPositiveDefinite) {
36893  const CVector vUpDiag = m.diag(0);
36894  for (i = CVM0; i < this->msize() + CVM0; ++i) {
36895  dDet *= vUpDiag[i] * vUpDiag[i]; // here we use Cholesky factorization
36896  }
36897  } else {
36898  const basic_rvector<TR> vEig = this->eig();
36899  for (i = CVM0; i < this->msize() + CVM0; ++i) {
36900  dDet *= vEig[i]; // here we use eigenvalues. probably there is a better way.
36901  }
36902  }
36903  }
36904  catch (const cvmexception& e) {
36905  if (e.cause() != CVM_WRONGBUNCHKAUFMANFACTOR) throw e;
36906  }
36907  break;
36908  }
36909  return dDet;
36910  }
36911 
36912  // matrix equilibration helper
36913  bool _equilibrate(basic_rvector<TR>& vScalings) throw(cvmexception)
36914  {
36915  _check_ne(CVM_SIZESMISMATCH, this->msize(), vScalings.size());
36916  bool bRes = false;
36917  TR dCond = TR();
36918  TR dMax = TR();
36919  static const TR sp = basic_cvmMachSp<TR>();
36920  static const TR sp_inv = TR(1.) / sp;
36921 
36922  __poequ<TR,basic_schmatrix, basic_rvector<TR> >(*this, vScalings, dCond, dMax);
36923 
36924  if (dCond < TR(0.1) || _abs(dMax) <= sp || _abs(dMax) >= sp_inv) {
36925  bRes = true;
36926  for (tint i = 0; i < this->msize(); ++i) {
36927  for (tint j = i; j < this->msize(); ++j) {
36928  this->get()[this->ld() * j + i] *= vScalings[i + CVM0] * vScalings[j + CVM0];
36929  }
36930  }
36931  }
36932  return bRes;
36933  }
36934 
36935  void _make_main_diag_real()
36936  {
36937  static const TR zero = TR(0.);
36938  __scal<TR,TR>(__get_imag_p<TR>(this->get()), this->msize(), (this->ld() + 1) * 2, zero);
36939  }
36940 
36941  void _check_gerc() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "gerc", "schmatrix");}
36942  void _check_geru() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "geru", "schmatrix");}
36943  void _check_rank1update_c() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "rank1update_c", "schmatrix");}
36944  void _check_rank1update_u() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "rank1update_u", "schmatrix");}
36945  void _check_gemm() throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "gemm", "schmatrix");}
36946  void _swap_rows(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_rows", "schmatrix");}
36947  void _swap_cols(tint, tint) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "swap_cols", "schmatrix");}
36948  void _set_imag_number(TR) throw(cvmexception) override { throw cvmexception(CVM_METHODNOTAVAILABLE, "set_imag", "schmatrix");}
36950 };
36951 
36952 
36954 template<typename TR>
36956  return v * d;
36957 }
36959 template<typename TR>
36961  return m * d;
36962 }
36964 template<typename TR>
36966  return m * d;
36967 }
36969 template<typename TR>
36971  return m * d;
36972 }
36974 template<typename TR>
36976  return m * d;
36977 }
36978 
36980 template<typename TR, typename TC>
36982  return v * d;
36983 }
36985 template<typename TR, typename TC>
36987  return m * d;
36988 }
36990 template<typename TR, typename TC>
36992  return m * d;
36993 }
36995 template<typename TR, typename TC>
36997  return m * d;
36998 }
37000 template<typename TR, typename TC>
37002  return m * d;
37003 }
37004 
37006 template<typename TR, typename TC>
37007 inline basic_cvector<TR,TC> operator * (std::complex<TR> c, const basic_cvector<TR,TC>& v) {
37008  return v * c;
37009 }
37011 template<typename TR, typename TC>
37012 inline basic_cmatrix<TR,TC> operator * (std::complex<TR> c, const basic_cmatrix<TR,TC>& m) {
37013  return m * c;
37014 }
37016 template<typename TR, typename TC>
37017 inline basic_scmatrix<TR,TC> operator * (std::complex<TR> c, const basic_scmatrix<TR,TC>& m) {
37018  return m * c;
37019 }
37021 template<typename TR, typename TC>
37022 inline basic_scbmatrix<TR,TC> operator * (std::complex<TR> c, const basic_scbmatrix<TR,TC>& m) {
37023  return m * c;
37024 }
37026 template<typename TR, typename TC>
37027 inline basic_scmatrix<TR,TC> operator * (std::complex<TR> c, const basic_schmatrix<TR,TC>& m) {
37028  return m * c;
37029 }
37030 
37032 template<typename TR>
37033 inline basic_rvector<TR> operator * (CVM_LONGEST_INT d, const basic_rvector<TR>& v) {
37034  return v * static_cast<TR>(d);
37035 }
37037 template<typename TR>
37038 inline basic_rmatrix<TR> operator * (CVM_LONGEST_INT d, const basic_rmatrix<TR>& m) {
37039  return m * static_cast<TR>(d);
37040 }
37042 template<typename TR>
37043 inline basic_srmatrix<TR> operator * (CVM_LONGEST_INT d, const basic_srmatrix<TR>& m) {
37044  return m * static_cast<TR>(d);
37045 }
37047 template<typename TR>
37048 inline basic_srbmatrix<TR> operator * (CVM_LONGEST_INT d, const basic_srbmatrix<TR>& m) {
37049  return m * static_cast<TR>(d);
37050 }
37052 template<typename TR>
37053 inline basic_srsmatrix<TR> operator * (CVM_LONGEST_INT d, const basic_srsmatrix<TR>& m) {
37054  return m * static_cast<TR>(d);
37055 }
37056 
37058 template<typename TR, typename TC>
37059 inline basic_cvector<TR,TC> operator * (CVM_LONGEST_INT d, const basic_cvector<TR,TC>& v) {
37060  return v * static_cast<TR>(d);
37061 }
37063 template<typename TR, typename TC>
37064 inline basic_cmatrix<TR,TC> operator * (CVM_LONGEST_INT d, const basic_cmatrix<TR,TC>& m) {
37065  return m * static_cast<TR>(d);
37066 }
37068 template<typename TR, typename TC>
37069 inline basic_scmatrix<TR,TC> operator * (CVM_LONGEST_INT d, const basic_scmatrix<TR,TC>& m) {
37070  return m * static_cast<TR>(d);
37071 }
37073 template<typename TR, typename TC>
37074 inline basic_scbmatrix<TR,TC> operator * (CVM_LONGEST_INT d, const basic_scbmatrix<TR,TC>& m) {
37075  return m * static_cast<TR>(d);
37076 }
37078 template<typename TR, typename TC>
37079 inline basic_schmatrix<TR,TC> operator * (CVM_LONGEST_INT d, const basic_schmatrix<TR,TC>& m) {
37080  return m * static_cast<TR>(d);
37081 }
37082 
37083 
37084 #if defined (CVM_FLOAT)
37085 typedef float treal;
37086 #else
37087 typedef double treal;
37088 #endif
37089 
37090 typedef std::complex<treal> tcomplex;
37091 
37103 
37104 
37106 template<typename TR>
37108 {
37109  basic_srmatrix<TR> mI(nM);
37110  ++mI;
37111  return mI;
37112 }
37114 template<typename TR, typename TC>
37116 {
37117  basic_scmatrix<TR,TC> mI(nM);
37118  ++mI;
37119  return mI;
37120 }
37121 
37123 inline const srmatrix eye_real(tint nM) {
37124  return basic_eye_real<treal>(nM);
37125 }
37127 inline const scmatrix eye_complex(tint nM) {
37128  return basic_eye_complex<treal, tcomplex>(nM);
37129 }
37130 
37150 inline treal cvmMachMin() {
37151  return basic_cvmMachMin<treal>();
37152 }
37153 
37175 inline treal cvmMachSp() {
37176  return basic_cvmMachSp<treal>();
37177 }
37178 
37179 
37181 #if !defined (CVM_STD_MUTEX)
37182 
37183 class CriticalSection
37184 {
37185 #if defined (CVM_MT)
37186 private:
37187  bool mbOK;
37188 
37189 #if defined (WIN32) || defined (_WIN32)
37190 #if defined (CVM_USE_CRITICAL_SECTION_NOT_MUTEX)
37191  ::CRITICAL_SECTION mCriticalSection;
37192 #else
37193  HANDLE mMutex;
37194 #endif
37195 #else // POSIX Threads library assumed
37196  pthread_mutex_t mMutex;
37197  pthread_mutexattr_t mMutexAttr;
37198 #endif
37199 #endif
37200 
37201 public:
37202  CriticalSection();
37203  ~CriticalSection();
37204 
37205  void enter()
37206 #if defined (CVM_MT)
37207  throw(cvmexception)
37208 #endif
37209  ;
37210  void leave()
37211 #if defined (CVM_MT)
37212  throw(cvmexception)
37213 #endif
37214  ;
37215 };
37216 
37217 class Lock
37218 {
37219  CriticalSection& mcs;
37220 public:
37221  Lock(CriticalSection& cs) : mcs(cs) {
37222  mcs.enter();
37223  }
37224  ~Lock() {
37225  mcs.leave();
37226  }
37227 private:
37228  Lock& operator = (const Lock&) {
37229  return *this;
37230  }
37231 };
37232 #endif
37233 
37234 
37235 
37236 #if defined(CVM_USE_USER_LITERALS)
37237 
37238 constexpr std::complex<treal> operator "" _i(long double im)
37239 {
37240  return { 0., static_cast<treal>(im) };
37241 }
37242 
37243 constexpr std::complex<treal> operator "" _i(unsigned long long int im)
37244 {
37245  return { 0., static_cast<treal>(im) };
37246 }
37247 
37248 template<typename T, typename TR>
37249 inline std::complex<TR> operator + (T re, const std::complex<TR>& c) {
37250  return { static_cast<TR>(re) + c.real(), c.imag() };
37251 }
37252 
37253 template<typename T, typename TR>
37254 inline std::complex<TR> operator - (T re, const std::complex<TR>& c) {
37255  return { static_cast<TR>(re) - c.real(), - c.imag() };
37256 }
37257 
37258 template<typename T, typename TR>
37259 inline std::complex<TR> operator + (const std::complex<TR>& c, const T& re) {
37260  return { c.real() + static_cast<TR>(re), c.imag() };
37261 }
37262 
37263 template<typename T, typename TR>
37264 inline std::complex<TR> operator - (const std::complex<TR>& c, const T& re) {
37265  return { c.real() - static_cast<TR>(re), c.imag() };
37266 }
37267 
37268 #endif
37269 
37270 
37272 
37273 
37275 #if !defined (_MSC_VER)
37276 # define XERBLA xerbla_
37277 #endif
37278 
37279 extern "C"
37280 {
37281  void __stdcall XERBLA(const char* szSubName,
37282 #if defined (CVM_PASS_STRING_LENGTH_TO_FTN_SUBROUTINES)
37283  const tint nLen,
37284 #endif
37285  const tint* pnParam) throw(cvm::cvmexception);
37286 }
37287 
37288 #endif // _CVM_H
37289