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