1% !TEX root = TMV_Documentation.tex 2 3\section{Symmetric and hermitian band matrices} 4\index{SymBandMatrix} 5\index{HermBandMatrix|see{SymBandMatrix}} 6\label{SymBandMatrix} 7 8The \tt{SymBandMatrix} class is our symmetric band matrix, which combines 9the properties of \tt{SymMatrix} and \tt{BandMatrix}; it has a banded structure and 10$m = m^T$. Likewise \tt{HermBandMatrix} is our hermitian band matrix for 11which $m = m^\dagger$. 12 13As with the documentation for \tt{SymMatrix}/\tt{HermMatrix}, the descriptions 14below will only be written for \tt{SymBandMatrix} with the implication 15that a \tt{HermBandMatrix} has the same functionality, but with the calculations 16appropriate for a hermitian matrix, rather than symmetric. 17 18One general caveat about complex \tt{HermBandMatrix} calculations is that 19the diagonal elements should all be real. Some calculations assume this, and 20only use the real part of the diagonal elements. Other calculations use the 21full complex value as it is in memory. Therefore, if you set a diagonal element 22to a non-real value at some point, the results will likely be wrong in 23unpredictable ways. Plus of course, your matrix will not actually be 24hermitian any more, so the right answer is undefined in any case. 25 26All the \tt{SymBandMatrix} and \tt{HermBandMatrix} routines are included by: 27\begin{tmvcode} 28#include "TMV_SymBand.h" 29\end{tmvcode} 30\index{TMV\_SymBand.h} 31 32In addition to the data type template parameter (indicated here by \tt{T} as usual), 33there is also a second template parameter that specifies attributes of the 34\tt{SymBandMatrix} or \tt{HermBandMatrix}. The attributes that are allowed are: 35\begin{description} \itemsep -2pt 36\item[$\bullet$] \tt{CStyle} or \tt{FortranStyle} 37\item[$\bullet$] \tt{ColMajor}, \tt{RowMajor}, or \tt{DiagMajor} 38\item[$\bullet$] \tt{Lower} or \tt{Upper} 39\end{description} 40The default attributes are \tt{CStyle}, \tt{ColMajor} and \tt{Lower}. 41 42The storage size required is the same as for the \tt{BandMatrix} of 43the upper or lower band portion. 44(See \ref{BandMatrix}.) 45As with square band matrices, 46all three storage methods always need the same amount of memory, so the 47decision about which method to use should generally be based on performance 48considerations rather than memory usage. 49The speed of the various matrix operations are different for the different storage 50types. If the matrix calculation speed is important, it may be worth trying 51all three to see which is fastest for the operations you are using. 52 53Also, as with \tt{BandMatrix}, the storage for \tt{Lower}, \tt{DiagMajor} 54does not start with the upper left element as usual. 55Rather, it starts at the start of the lowest sub-diagonal. 56 57Most functions and methods for \tt{SymBandMatrix} and \tt{HermBandMatrix} 58work the same as they do for \tt{Matrix}. 59In these cases, we will just list the functions that are allowed with the 60effect understood to be the same as for a regular \tt{Matrix}. Of course, there are 61almost always algorithmic speed-ups, which the code will use to take advantage of the 62symmetric (or hermitian) banded structure. 63Whenever there is a difference in how a function works, 64we will explain the difference. 65 66\subsection{Constructors} 67\index{SymBandMatrix!Constructors} 68\label{SymBandMatrix_Constructors} 69 70As usual, the optional \tt{A} template argument specifies attributes about 71the \tt{SymBandMatrix}. The default attributes if not specified are 72\tt{CStyle|ColMajor|Lower}. 73 74\begin{itemize} 75 76\item 77\begin{tmvcode} 78tmv::SymBandMatrix<T,A> sb() 79tmv::HermBandMatrix<T,A> hb() 80\end{tmvcode} 81Makes a \tt{SymBandMatrix} or \tt{HermBandMatrix} with zero size. You would normally use the \tt{resize} function later to 82change the size to some useful value. 83 84\item 85\begin{tmvcode} 86tmv::SymBandMatrix<T,A> sb(int n, int nlo) 87tmv::HermBandMatrix<T,A> hb(int n, int nlo) 88\end{tmvcode} 89Makes an \tt{n} $\times$ \tt{n} \tt{SymBandMatrix} or \tt{HermBandMatrix} with 90\tt{nlo} off-diagonals 91and with {\em uninitialized} values. 92If extra debugging is turned on (with the compiler flag \tt{-DTMV\_EXTRA\_DEBUG}), then the values are initialized to 888. 93 94\item 95\begin{tmvcode} 96tmv::SymBandMatrix<T,A> sb(int n, int nlo, T x) 97tmv::HermBandMatrix<T,A> hb(int n, int nlo, RT x) 98\end{tmvcode} 99Makes an \tt{n} $\times$ \tt{n} \tt{SymBandMatrix} or \tt{HermBandMatrix} with \tt{nlo} off-diagonals 100and with all values equal to \tt{x}. For the \tt{HermBandMatrix} version of this, \tt{x} must be real. 101 102\item 103\begin{tmvcode} 104tmv::SymBandMatrix<T,A> sb(const Matrix<T,A2>& m, int nlo) 105tmv::SymBandMatrix<T,A> sb(const SymMatrix<T,A2>& m, int nlo) 106tmv::SymBandMatrix<T,A> sb(const BandMatrix<T,A2>& m, int nlo) 107tmv::SymBandMatrix<T,A> sb(const SymBandMatrix<T,A2>& m, int nlo) 108\end{tmvcode} 109Makes a \tt{SymBandMatrix} which copies the corresponding values of \tt{m}. 110For the last two, \tt{nlo} must not be larger than the number of upper 111or lower bands in \tt{m}. There are similar constructors for \tt{HermBandMatrix}. 112 113\item 114\begin{tmvcode} 115tmv::SymBandMatrix<T,DiagMajor> sb = SymTriDiagMatrix( 116 const Vector<T>& v1, const Vector<T>& v2) 117tmv::SymBandMatrix<T,DiagMajor> sb = SymTriDiagMatrix( 118 const Vector<T>& v1, const Vector<T>& v2) 119tmv::HermBandMatrix<T,DiagMajor> hb = HermTriDiagMatrix( 120 const Vector<T>& v1, const Vector<T>& v2, 121 UpLoType uplo) 122tmv::HermBandMatrix<T,DiagMajor> hb = HermTriDiagMatrix( 123 const Vector<T>& v1, const Vector<T>& v2, 124 UpLoType uplo) 125\end{tmvcode} 126\index{SymBandMatrix!Constructors!SymTriDiagMatrix} 127\index{SymBandMatrix!Constructors!HermTriDiagMatrix} 128Shorthand to create a symmetric tri-diagonal band matrix 129if you already have the \tt{Vector}s. 130The main diagonal is \tt{v1} and the off-diagonal is \tt{v2}. 131 132With a \tt{HermTriDiagMatrix}, \tt{v1} should be real, although 133it may be either a real-valued \tt{Vector} or a complex-valued 134\tt{Vector} whose imaginary components are all zero. 135Also, \tt{HermTriDiagMatrix} takes an extra parameter, \tt{uplo}, indicating 136whether \tt{v2} should be used as the upper or lower off-diagonal 137(since they differ by a conjugation). 138 139\item 140\begin{tmvcode} 141tmv::SymBandMatrix<T,A> sb1(const SymBandMatrix<T2,A2>& sb2) 142sb1 = sb2 143\end{tmvcode} 144Copy the \tt{SymBandMatrix m2}, which may be of any type \tt{T2} so long 145as values of type \tt{T2} are convertible into type \tt{T}. 146The assignment operator has the same flexibility. 147 148\item 149\begin{tmvcode} 150tmv::SymBandMatrixView<T,A> sb = 151 SymBandMatrixViewOf(MatrixView<T> m, UpLoType uplo, int nlo) 152tmv::SymBandMatrixView<T,A> sb = 153 SymBandMatrixViewOf(SymMatrixView<T> m, int nlo) 154tmv::SymBandMatrixView<T,A> sb = 155 SymBandMatrixViewOf(BandMatrixView<T> m, UpLoType uplo, int nlo) 156tmv::SymBandMatrixView<T,A> hb = 157 HermBandMatrixViewOf(MatrixView<T> m, UpLoType uplo, int nlo) 158tmv::SymBandMatrixView<T,A> hb = 159 HermBandMatrixViewOf(SymMatrixView<T> m, int nlo) 160tmv::SymBandMatrixView<T,A> hb = 161 HermBandMatrixViewOf(BandMatrixView<T> m, UpLoType uplo, int nlo) 162\end{tmvcode} 163\index{Matrix!View portion as SymBandMatrix or HermBandMatrix} 164\index{SymMatrix!View portion as SymBandMatrix or HermBandMatrix} 165\index{BandMatrix!View portion as SymBandMatrix or HermBandMatrix} 166Make an \tt{SymBandMatrixView} of the corresponding portion of \tt{m}. 167To view these as a hermitian band matrix, use the command, 168\tt{HermBandMatrixViewOf} instead. 169For the view of a \tt{BandMatrix}, the parameter \tt{nlo} may be 170omitted, in which case either \tt{m.nhi()} or \tt{m.nlo()} is used 171according to whether \tt{uplo} is \tt{Upper} or \tt{Lower} respectively. 172There are also \tt{ConstSymBandMatrixView} versions of these. 173 174\item 175\begin{tmvcode} 176tmv::SymBandMatrixView<T,A> sb = 177 tmv::SymBandMatrixViewOf(T* vv, int n, int nlo, 178 UpLoType uplo, StorageType stor) 179tmv::ConstSymBandMatrixView<T,A> sb = 180 tmv::SymBandMatrixViewOf(const T* vv, int n, int nlo, 181 UpLoType uplo, StorageType stor) 182tmv::SymBandMatrixView<T,A> hb = 183 tmv::HermBandMatrixViewOf(T* vv, int n, int nlo, 184 UpLoType uplo, StorageType stor) 185tmv::ConstSymBandMatrixView<T,A> hb = 186 tmv::HermBandMatrixViewOf(const T* vv, int n, int nlo, 187 UpLoType uplo, StorageType stor) 188\end{tmvcode} 189\index{SymBandMatrix!View of raw memory} 190Make a \tt{SymBandMatrixView} of the actual memory elements, \tt{vv}, in either the 191upper or lower band. 192The length of the data array should be 193\tt{BandStorageLength(stor,n,n,nlo,0)}. Also, as with the corresponding \tt{BandMatrixViewOf} functions, if \tt{uplo} is \tt{Lower} and \tt{stor} is \tt{DiagMajor} then \tt{vv} should be the memory address of \tt{b(nlo,0)}, not \tt{b(0,0)}. 194 195 196\item 197\begin{tmvcode} 198tmv::SymBandMatrixView<T,A> sb = 199 tmv::SymBandMatrixViewOf(T* vv, int n, int nlo, 200 UpLoType uplo, int stepi, int stepj) 201tmv::ConstSymBandMatrixView<T,A> sb = 202 tmv::SymBandMatrixViewOf(const T* vv, int n, int nlo, 203 UpLoType uplo, int stepi, int stepj) 204tmv::SymBandMatrixView<T,A> hb = 205 tmv::HermBandMatrixViewOf(T* vv, int n, int nlo, 206 UpLoType uplo, int stepi, int stepj) 207tmv::ConstSymBandMatrixView<T,A> hb = 208 tmv::HermBandMatrixViewOf(const T* vv, int n, int nlo, 209 UpLoType uplo, int stepi, int stepj) 210\end{tmvcode} 211\index{SymBandMatrix!View of raw memory} 212Make a \tt{SymBandMatrixView} of the actual memory elements, \tt{vv}, in either the 213upper or lower band. This allows for arbitrary steps through the data. 214 215\end{itemize} 216 217\subsection{Access} 218\index{SymBandMatrix!Access methods} 219\label{SymBandMatrix_Access} 220 221\begin{itemize} 222 223\item 224\begin{tmvcode} 225sb.nrows() = sb.ncols() = sb.colsize() = sb.rowsize() = sb.size() 226sb.nlo() = sb.nhi() 227sb.resize(int new_size, int new_nlo) 228sb(i,j) 229sb.cref(i,j) 230sb.ref(i,j) 231\end{tmvcode} 232\index{SymBandMatrix!Methods!nrows} 233\index{SymBandMatrix!Methods!ncols} 234\index{SymBandMatrix!Methods!rowsize} 235\index{SymBandMatrix!Methods!colsize} 236\index{SymBandMatrix!Methods!size} 237\index{SymBandMatrix!Methods!nlo} 238\index{SymBandMatrix!Methods!nhi} 239\index{SymBandMatrix!Methods!resize} 240\index{SymBandMatrix!Methods!operator()} 241\index{SymBandMatrix!Methods!cref} 242\index{SymBandMatrix!Methods!ref} 243As with a complex \tt{HermMatrix}, a complex \tt{HermBandMatrix} has a special reference type, since it needs to check whether its value is the conjugate of the value actually stored in memory. This will necessarily be true for values in either the upper or lower band. 244Also, for the mutable \tt{sb(i,j)} version, the position must fall within the 245band. If \tt{sb} is not mutable, then \tt{sb(i,j)} returns 0 for 246positions outside of the band. 247 248\item 249\begin{tmvcode} 250sb.row(int i, int j1, int j2) 251sb.col(int i, int j1, int j2) 252sb.diag() 253sb.diag(int i) 254sb.diag(int i, int k1, int k2) 255\end{tmvcode} 256\index{SymBandMatrix!Methods!row} 257\index{SymBandMatrix!Methods!col} 258\index{SymBandMatrix!Methods!diag} 259Again, the versions of \tt{row} and \tt{col} with only one argument are 260missing, since the full row or column isn't accessible as a \tt{VectorView}. 261You must specify a valid range within the row or column that you want, 262given the banded storage of \tt{sb}. And, like for \tt{SymMatrix}, a full row 263must be accessed in its two parts, one on each side of the diagonal. 264 265\item 266\begin{tmvcode} 267T* sb.ptr() 268const T* sb.cptr() const 269int sb.stepi() const 270int sb.stepj() const 271int sb.diagstep() const 272bool sb.isconj() const 273bool sb.issym() const 274bool sb.isherm() const 275bool sb.isupper() const 276bool sb.isrm() const 277bool sb.iscm() const 278bool sb.isdm() const 279\end{tmvcode} 280\index{SymBandMatrix!Methods!ptr} 281\index{SymBandMatrix!Methods!cptr} 282\index{SymBandMatrix!Methods!stepi} 283\index{SymBandMatrix!Methods!stepj} 284\index{SymBandMatrix!Methods!diagstep} 285\index{SymBandMatrix!Methods!isconj} 286\index{SymBandMatrix!Methods!issym} 287\index{SymBandMatrix!Methods!isherm} 288\index{SymBandMatrix!Methods!isupper} 289\index{SymBandMatrix!Methods!isrm} 290\index{SymBandMatrix!Methods!iscm} 291\index{SymBandMatrix!Methods!isdm} 292These methods allow for direct memory access of a \tt{SymBandMatrix}. 293 294\item 295\begin{tmvcode} 296sb.subVector(int i, int j, int istep, int jstep, int size) 297sb.subMatrix(int i1, int i2, int j1, int j2) 298sb.subMatrix(int i1, int i2, int j1, int j2, int istep, int jstep) 299sb.subBandMatrix(int i1, int i2, int j1, int j2) 300sb.subBandMatrix(int i1, int i2, int j1, int j2, int newnlo, int newhi) 301sb.subBandMatrix(int i1, int i2, int j1, int j2, int newnlo, int newhi, 302 int istep, int jstep) 303sb.diagRange(int k1, int k2) 304sb.upperBand() 305sb.lowerBand() 306sb.upperBandOff() 307sb.lowerBandOff() 308\end{tmvcode} 309\index{SymBandMatrix!Methods!subVector} 310\index{SymBandMatrix!Methods!subMatrix} 311\index{SymBandMatrix!Methods!subBandMatrix} 312\index{SymBandMatrix!Methods!diagRange} 313\index{SymBandMatrix!Methods!upperBand} 314\index{SymBandMatrix!Methods!lowerBand} 315\index{SymBandMatrix!Methods!upperBandOff} 316\index{SymBandMatrix!Methods!lowerBandOff} 317These work the same as for a \tt{BandMatrix} 318(See \ref{BandMatrix_Access}), 319except that the entire 320subvector or submatrix must be completely within the upper or lower band. 321 322\item 323\begin{tmvcode} 324sb.subSymMatrix(int i1, int i2) 325sb.subSymMatrix(int i1, int i2, int istep) 326sb.subSymBandMatrix(int i1, int i2, int newnlo=m.nlo()) 327sb.subSymBandMatrix(int i1, int i2, int newnlo, int istep) 328\end{tmvcode} 329\index{SymBandMatrix!Methods!subSymMatrix} 330\index{SymBandMatrix!Methods!subSymBandMatrix} 331These return a view of the \tt{SymMatrix} or \tt{SymBandMatrix} which runs 332from \tt{i1} to \tt{i2} along the diagonal with an optional step, 333and includes the off-diagonals in the same rows/cols. For the first two, 334the \tt{SymMatrix} must be completely with the band. 335 336\item 337\begin{tmvcode} 338sb.symDiagRange(int newnlo) 339\end{tmvcode} 340\index{SymBandMatrix!Methods!symDiagRange} 341Since \tt{diagRange} returns a regular \tt{BandMatrixView}, it must be completely 342within either the upper or lower band. This routine returns a \tt{SymBandMatrixView} 343which straddles the diagonal with \tt{newnlo} super- and sub-diagonals. 344 345\item 346\begin{tmvcode} 347sb.transpose() 348sb.conjugate() 349sb.adjoint() 350sb.view() 351sb.cView() 352sb.fView() 353sb.realPart() 354sb.imagPart() 355\end{tmvcode} 356\index{SymBandMatrix!Methods!transpose} 357\index{SymBandMatrix!Methods!conjugate} 358\index{SymBandMatrix!Methods!adjoint} 359\index{SymBandMatrix!Methods!view} 360\index{SymBandMatrix!Methods!cView} 361\index{SymBandMatrix!Methods!fView} 362\index{SymBandMatrix!Methods!realPart} 363\index{SymBandMatrix!Methods!imagPart} 364These return \tt{SymBandMatrixView}s. 365Note that the imaginary part of a complex hermitian band matrix is 366skew-symmetric, so \tt{sb.imagPart()} is illegal for a \tt{HermBandMatrix}. 367If you need to manipulate the imaginary part of a \tt{HermMatrix}, 368you could use 369\tt{sb.upperBandOff().imagPart()} 370(since all the diagonal elements are real). 371 372\end{itemize} 373 374Note that there are no iterators provided for \tt{SymBandMatrix} or \tt{HermBandMatrix}. The recommended way to iterate over their stored values is to use the \tt{upperBand()} or \tt{lowerBand()} methods and iterate over those portions of the matrix directly. 375 376\subsection{Functions} 377\index{SymBandMatrix!Functions of} 378\label{SymBandMatrix_Functions} 379 380\begin{tmvcode} 381RT sb.norm1() = Norm1(sb) 382RT sb.norm2() = Norm2(sb) 383RT sb.normInf() = NormInf(sb) 384RT sb.normF() = NormF(sb) = sb.norm() = Norm(sb) 385RT sb.normSq() = NormSq(sb) 386RT sb.normSq(RT scale) 387RT sb.maxAbsElement() = MaxAbsElement(sb) 388RT sb.maxAbs2Element() = MaxAbs2Element(sb) 389T sb.trace() = Trace(sb) 390T sb.sumElements() = SumElements(sb) 391RT sb.sumAbsElements() = SumAbsElements(sb) 392RT sb.sumAbs2Elements() = SumAbs2Elements(sb) 393T sb.det() = Det(sb) 394RT sb.logDet(T* sign=0) = LogDet(sb) 395sinv = sb.inverse() = Inverse(sb) 396bool sb.isSingular 397RT sb.condition() 398RT sb.doCondition() 399sb.makeInverse(Matrix<T>& minv) 400sb.makeInverse(SymMatrix<T>& sinv) 401sb.makeInverseATA(Matrix<T>& cov) 402\end{tmvcode} 403\index{SymBandMatrix!Functions of!Norm1} 404\index{SymBandMatrix!Functions of!Norm2} 405\index{SymBandMatrix!Functions of!NormInf} 406\index{SymBandMatrix!Functions of!MaxAbsElement} 407\index{SymBandMatrix!Functions of!MaxAbs2Element} 408\index{SymBandMatrix!Methods!norm1} 409\index{SymBandMatrix!Methods!norm2} 410\index{SymBandMatrix!Methods!normInf} 411\index{SymBandMatrix!Methods!maxAbsElement} 412\index{SymBandMatrix!Methods!maxAbs2Element} 413\index{SymBandMatrix!Functions of!Norm} 414\index{SymBandMatrix!Functions of!NormF} 415\index{SymBandMatrix!Functions of!NormSq} 416\index{SymBandMatrix!Functions of!Trace} 417\index{SymBandMatrix!Functions of!SumElements} 418\index{SymBandMatrix!Functions of!SumAbsElements} 419\index{SymBandMatrix!Functions of!SumAbs2Elements} 420\index{SymBandMatrix!Functions of!Det} 421\index{SymBandMatrix!Functions of!LogDet} 422\index{SymBandMatrix!Functions of!Inverse} 423\index{SymBandMatrix!Methods!norm} 424\index{SymBandMatrix!Methods!normF} 425\index{SymBandMatrix!Methods!normSq} 426\index{SymBandMatrix!Methods!trace} 427\index{SymBandMatrix!Methods!sumElements} 428\index{SymBandMatrix!Methods!sumAbsElements} 429\index{SymBandMatrix!Methods!sumAbs2Elements} 430\index{SymBandMatrix!Methods!det} 431\index{SymBandMatrix!Methods!logDet} 432\index{SymBandMatrix!Methods!isSingular} 433\index{SymBandMatrix!Methods!condition} 434\index{SymBandMatrix!Methods!doCondition} 435\index{SymBandMatrix!Methods!inverse} 436\index{SymBandMatrix!Methods!makeInverse} 437\index{SymBandMatrix!Methods!makeInverseATA} 438The inverse of a \tt{SymBandMatrix} is not (in general) banded. 439However, it is symmetric (or hermitian). 440So \tt{sb.inverse()} may be assigned to either a \tt{Matrix} or a \tt{SymMatrix}. 441 442\begin{tmvcode} 443sb.setZero() 444sb.setAllTo(T x) 445sb.addToAll(T x) 446sb.clip(RT thresh) 447sb.setToIdentity(T x = 1) 448sb.conjugateSelf() 449sb.transposeSelf() 450Swap(sb1,sb2) 451\end{tmvcode} 452\index{SymBandMatrix!Methods!setZero} 453\index{SymBandMatrix!Methods!setAllTo} 454\index{SymBandMatrix!Methods!addToAll} 455\index{SymBandMatrix!Methods!clip} 456\index{SymBandMatrix!Methods!setToIdentity} 457\index{SymBandMatrix!Methods!conjugateSelf} 458\index{SymBandMatrix!Methods!transposeSelf} 459\index{SymBandMatrix!Functions of!Swap} 460As with \tt{SymMatrix}, the method \tt{transposeSelf()} does nothing to a \tt{SymBandMatrix} and is equivalent to 461\tt{conjugateSelf()} for a \tt{HermBandMatrix}. 462 463\vspace{12pt} % I don't know why I need this. LaTex isn't putting the normal spacing here. 464 465\subsection{Arithmetic} 466\index{SymBandMatrix!Arithmetic} 467\label{SymBandMatrix_Arithmetic} 468 469In addition to \tt{x}, \tt{v}, \tt{m}, \tt{b} and \tt{s} from before, 470we now add \tt{sb} for a \tt{SymBandMatrix}. 471 472\begin{tmvcode} 473sb2 = -sb1 474sb2 = x * sb1 475sb2 = sb1 [*/] x 476sb3 = sb1 [+-] sb2 477m2 = m1 [+-] sb 478m2 = sb [+-] m1 479b2 = b1 [+-] sb 480b2 = sb [+-] b1 481s2 = s1 [+-] sb 482s2 = sb [+-] s1 483sb [*/]= x 484sb2 [+-]= sb1 485m [+-]= sb 486b [+-]= sb 487s [+-]= sb 488v2 = sb * v1 489v2 = v1 * sb 490v *= sb 491b = sb1 * sb2 492sb3 = ElemProd(sb1,sb2) 493m2 = sb * m1 494m2 = m1 * sb 495m *= sb 496b2 = sb * b1 497b2 = b1 * sb 498b *= sb 499m2 = sb * s1 500m2 = s1 * sb 501sb2 = sb1 [+-] x 502sb2 = x [+-] sb1 503sb [+-]= x 504sb = x 505\end{tmvcode} 506 507\subsection{Division} 508\index{SymBandMatrix!Arithmetic!division} 509\label{SymBandMatrix_Division} 510 511The division operations are: 512\begin{tmvcode} 513v2 = v1 [/%] sb 514m2 = m1 [/%] sb 515m2 = sb [/%] m1 516m = sb1 [/%] sb2 517s = x [/%] sb 518v [/%]= sb 519m [/%]= sb 520\end{tmvcode} 521\tt{SymBandMatrix} has three possible choices for the division decomposition: 522\begin{enumerate} 523\item 524\tt{m.divideUsing(tmv::LU)} actually does the \tt{BandMatrix} version of 525LU, rather than a Bunch-Kaufman algorithm like for \tt{SymMatrix}. The 526reason is that the pivots in the Bunch-Kaufman algorithm can arbitrarily 527expand the band width required to hold the information. The generic 528banded LU algorithm is limited to 3*\tt{nlo}+1 bands. 529 530To access this decomposition, use: 531\begin{tmvcode} 532bool sb.lud().isTrans() 533tmv::LowerTriMatrix<T,UnitDiag> sb.lud().getL() 534tmv::ConstBandMatrixView<T> sb.lud().getU() 535const Permutation& sb.lud().getP() 536\end{tmvcode} 537\index{SymBandMatrix!Methods!lud} 538\index{SymBandMatrix!LU decomposition} 539\index{LU decomposition!SymBandMatrix} 540The following should result in a matrix numerically very close to \tt{sb}. 541\begin{tmvcode} 542tmv::Matrix<T> m2(sb.nrows(),sb.ncols); 543tmv::MatrixView<T> m2v = 544 sb.lud().isTrans() ? m2.transpose() : m2.view(); 545m2v = sb.lud().getP() * sb.lud().getL() * sb.lud().getU(); 546\end{tmvcode} 547 548\item 549\tt{sb.divideUsing(tmv::CH)} will perform a Cholesky decomposition. 550\tt{sb} must be hermitian (or real symmetric) to use \tt{CH}, since that is the 551only kind of matrix that has a Cholesky decomposition. 552 553As with a regular \tt{SymMatrix}, 554the only real advantage of Cholesky over LU decomposition is speed. If you know your 555matrix is positive-definite, the Cholesky decomposition is the fastest way to 556do division. 557 558If \tt{sb} is tri-diagonal (i.e. \tt{nlo} = 1), then we use a slightly 559different algorithm, which avoids the square roots required for a 560Cholesky decomposition. 561Namely, we form the decomposition $sb = LDL^\dagger$, where $L$ is a 562unit-diagonal lower banded matrix with 1 sub-diagonal, and $D$ is diagonal. 563 564If \tt{sb} has \tt{nlo} $> 1$, then we just use a normal Cholesky algorithm 565where $sb = LL^\dagger$ and $L$ is lower banded with the same \tt{nlo} as 566\tt{sb}. 567 568Both versions of the algorithm are accessed with the same methods: 569\begin{tmvcode} 570BandMatrix<T> sb.chd().getL() 571DiagMatrix<T> sb.chd().getD() 572\end{tmvcode} 573\index{SymBandMatrix!Methods!chd} 574\index{SymBandMatrix!Cholesky decomposition} 575\index{Cholesky decomposition!SymBandMatrix} 576with $L$ being made unit-diagonal or $D$ being set to the identity matrix 577as appropriate. (Obviously, \tt{getL()} contains all of the information for the non-tridiagonal 578version.) 579 580The following should result in a matrix numerically very close to \tt{sb}. 581\begin{tmvcode} 582Matrix<T> m2 = sb.chd().getL() * sb.chd().getD() * 583 sb.chd().getL().adjoint() 584\end{tmvcode} 585 586\item 587\tt{sb.divideUsing(tmv::SV)} will perform either an eigenvalue decomposition 588(for hermitian band and real symmetric band matrices) or a regular singular value 589decomposition (for complex symmetric band matrices). 590 591To access this decomposition, use: 592\begin{tmvcode} 593ConstMatrixView<T> sb.svd().getU() 594DiagMatrix<RT> sb.svd().getS() 595Matrix<T> sb.svd().getVt() 596\end{tmvcode} 597\index{SymBandMatrix!Methods!svd} 598\index{SymBandMatrix!Singular value decomposition} 599\index{Singular value decomposition!SymBandMatrix} 600(As for \tt{SymMatrix}, a complex symmetric matrix needs to use the accessor 601\tt{symsvd()} instead, whose \tt{getS} and \tt{getVt} methods return Views 602rather than instantiated matrices.) 603 604The following should result in a matrix numerically very close to \tt{sb}. 605\begin{tmvcode} 606Matrix<T> m2 = sb.svd().getU() * sb.svd().getS() * sb.svd().getVt() 607\end{tmvcode} 608 609Both versions also have the same control and access routines as a regular SVD: 610(See \ref{Matrix_Division_Access}): 611\begin{tmvcode} 612sb.svd().thresh(RT thresh) 613sb.svd().top(int nsing) 614RT sb.svd().condition() 615int sb.svd().getKMax() 616\end{tmvcode} 617(Likewise for \tt{sb.symsvd()}.) 618 619\end{enumerate} 620The routines 621\begin{tmvcode} 622sb.saveDiv() 623sb.setDiv() 624sb.resetDiv() 625sb.unsetDiv() 626bool sb.divIsSet() 627sb.divideInPlace() 628\end{tmvcode} 629\index{SymBandMatrix!Methods!saveDiv} 630\index{SymBandMatrix!Methods!setDiv} 631\index{SymBandMatrix!Methods!resetDiv} 632\index{SymBandMatrix!Methods!unsetDiv} 633\index{SymBandMatrix!Methods!divIsSet} 634\index{SymBandMatrix!Methods!divideInPlace} 635work the same as for regular \tt{Matrix}es. 636(See \ref{Matrix_Division_Efficiency}.) However, \tt{divideInPlace} only actually works for the \tt{CH} algorithm. 637 638And just as for a regular \tt{Matrix}, the functions \tt{sb.det()}, \tt{sb.logDet()}, and \tt{sb.isSingular()} use whichever decomposition is currently set with \tt{sb.divideUsing(dt)}, 639unless \tt{sb}'s data type is an integer type, in which case Bareiss's algorithm for the determinant 640is used. 641\index{SymBandMatrix!Determinant} 642\index{SymBandMatrix|Methods!det} 643\index{SymBandMatrix|Methods!logDet} 644\index{SymBandMatrix|Methods!isSingular} 645 646 647\subsection{I/O} 648\index{SymBandMatrix!I/O} 649\label{SymBandMatrix_IO} 650 651The simplest I/O syntax is the usual: 652\begin{tmvcode} 653os << sb; 654is >> sb; 655\end{tmvcode} 656The output format is the same as for a \tt{Matrix}. 657(See \ref{Matrix_IO}.) On input, if the matrix read in is not symmetric (or Hermitian as appropriate), then a \tt{tmv::ReadError} is thrown. Likewise if any of the elements outside of the band structure 658are not 0. 659 660There is also a compact I/O style that puts all the elements in the lower band all on a single line and skips the parentheses. 661\begin{tmvcode} 662os << tmv::CompactIO() << sb; 663is >> tmv::CompactIO() >> sb; 664\end{tmvcode} 665\index{IOStyle!CompactIO} 666This has the extra advantage that it also outputs the number of off-diagonals, so the \tt{SymBandMatrix} can be resized correctly if it is not the right size already. The normal I/O style only includes the number of rows and columns, so the number of diagonals is assumed to be correct if the matrix needs to be resized. The compact I/O style can adjust both the size and the number of diagonals. 667 668One can also write small values as 0 with 669\begin{tmvcode} 670os << tmv::ThreshIO(thresh) << sb; 671os << tmv::CompactIO().setThresh(thresh) << sb; 672\end{tmvcode} 673\index{IOStyle!ThreshIO} 674 675See \S\ref{IOStyle} for more information about specifying custom I/O styles, including 676features like using brackets instead of parentheses, or putting commas between elements, 677or specifying an output precision. 678 679