1%%%%%%%%%%%%%%%%%%% 2% XLiFE++ is an extended library of finite elements written in C++ 3% Copyright (C) 2014 Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin 4% 5% This program is free software: you can redistribute it and/or modify 6% it under the terms of the GNU General Public License as published by 7% the Free Software Foundation, either version 3 of the License, or 8% (at your option) any later version. 9% This program is distributed in the hope that it will be useful, 10% but WITHOUT ANY WARRANTY; without even the implied warranty of 11% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12% GNU General Public License for more details. 13% You should have received a copy of the GNU General Public License 14% along with this program. If not, see <http://www.gnu.org/licenses/>. 15%%%%%%%%%%%%%%%%%%% 16 17\section{Compressed sparse storages} 18 19Compressed sparse storages are designed to store only non zero values of a matrix. It exists several methods to do it. The well known CSR/CSC storage being the most common one, we chose it. It consists in storing non zero values of a row (resp. column) in a compressed vector and their column indices (resp. row indices) in a compressed vector. A vector of addresses where begin rows (resp. columns) is also required. More precisely, for a $m\times n$ matrix 20\begin{itemize} 21\item row compressed storage is defined by the three vectors : \\ 22\mbox{}\hspace{10 mm}values = (0,$A_{1\mathcal{C}_1}$, ..., $A_{i\mathcal{C}_i}$, ..., $A_{m\mathcal{C}_m}$)\\ 23\mbox{}\hspace{10 mm}colIndex = ($\mathcal{C}_1$, ..., $\mathcal{C}_i$, ..., $\mathcal{C}_m$)\\ 24\mbox{}\hspace{10 mm}rowPointer = ($p_1$,...,$p_i$,...$,p_m$, $p_{m+1}$)\\ 25where $\mathcal{C}_i$ is the set of index $j$ where $A_{ij}\ne 0$ and $p_i$ is the position in vector colIndex of the first entry of row $i\le m$; $p_{m+1}$ gives the number of non zero values. By convention, all the indices begins at 0 and first entry of values vector is always 0! \\ 26For instance, the following $5\times 6$ non symmetric matrix 27\[ 28A=\left[ 29\begin{array}{cccccc} 3011 & 12 & 0 & 14 & 0 & 16\\ 310 & 22 & 23 & 0 & 0 & 26 \\ 3231 & 32 & 33 & 0 & 0 & 0 \\ 330 & 0 & 43 & 44 & 0 & 0 \\ 3451 & 0 & 53 & 54 & 55 & 0 35\end{array} 36\right] 37\] 38has the row compressed storage vectors: \\ \\ 39\mbox{}\hspace{10 mm}values = ( 0 11 12 14 16\ \ 22 23 26\ \ 31 32 33\ \ 43 44\ \ 51 53 54 55 ) \\ 40\mbox{}\hspace{10 mm}colIndex = ( 0 1 3 5\ \ 1 2 5\ \ 0 1 2\ \ 2 3\ \ 0 2 3 4 )\\ 41\mbox{}\hspace{10 mm}rowPointer = ( 0 4 7 10 12 16) \\ 42\item row compressed storage is defined by the three vectors : \\ 43\mbox{}\hspace{10 mm}values = (0,$A_{\mathcal{R}_11}$, ..., $A_{\mathcal{R}_jj}$, ..., $A_{\mathcal{R}_nn}$)\\ 44\mbox{}\hspace{10 mm}rowIndex = ($\mathcal{R}_1$, ..., $\mathcal{R}_j$, ..., $\mathcal{R}_n$)\\ 45\mbox{}\hspace{10 mm}colPointer = ($p_1$,...,$p_j$,...$,p_n$, $p_{n+1}$)\\ 46where $\mathcal{R}_j$ is the set of index $i$ where $A_{ij}\ne 0$ and $p_j$ is the position in rowIndex vector of the first entry of column $j\le n$; $p_{n+1}$ gives the number of non zero values. By convention, all the indices begins at 0 and first entry of values vector is always 0! \\ 47For instance, the previous $5\times 6$ non symmetric matrix $A$ has the column compress storage vectors: \\ 48\mbox{}\hspace{10 mm}values = ( 0 11 31 51\ \ 12 22 32\ \ 23 33 43 53\ \ 55\ \ 16 26 ) \\ 49\mbox{}\hspace{10 mm}rowIndex = ( 0 2 4\ \ 0 1 2\ \ 1 2 3 4\ \ 0 3 4\ \ 4\ \ 0 1)\\ 50\mbox{}\hspace{10 mm}colPointer = ( 0 4 7 10 12 16) \\ 51\item dual compressed storage is defined by the five vectors : \\ 52\mbox{}\hspace{10 mm}values = (0,\text{diag}(A), $A_{\mathcal{C}_11}$, ..., $A_{\mathcal{C}_ii}$, ..., $A_{\mathcal{C}_mm}$, $A_{\mathcal{R}_11}$, ..., $A_{\mathcal{R}_jj}$, ..., $A_{\mathcal{R}_nn}$)\\ 53\mbox{}\hspace{10 mm}colIndex = ($\mathcal{C}_1$, ..., $\mathcal{C}_i$, ..., $\mathcal{C}_m$)\\ 54\mbox{}\hspace{10 mm}rowPointer = ($p_1$,...,$p_i$,...$,p_m$, $p_{m+1}$)\\ 55\mbox{}\hspace{10 mm}rowIndex = ($\mathcal{R}_1$, ..., $\mathcal{R}_j$, ..., $\mathcal{R}_n$)\\ 56\mbox{}\hspace{10 mm}colPointer = ($q_1$,...,$q_j$,...$,q_n$, $q_{n+1}$)\\ 57where $\mathcal{C}_i$ is the set of index $j$ where $A_{ij}\ne 0$ and $j\le\min(i-1,n)$, 58$\mathcal{R}_j$ is the set of index $i$ where $A_{ij}\ne 0$ and $i\le\min(j-1,m)$, $p_i$ (resp. $q_j$) is the position in colIndex (resp. rowIndex) vector of the first entry of row $i\le m$ (resp. column $j\le n$). The colIndex and rowPointer vectors describes the row compressed storage of the strict lower part of matrix while the rowIndex and colPointer vectors describes the column compressed storage of the strict upper part of matrix. In this storage, all the diagonal entries of matrix are always first stored even the null entries!\\ 59For instance, the previous $5\times 6$ non symmetric matrix $A$ has the column compress storage vectors: \\ 60\mbox{}\hspace{10 mm}values = ( 0 11 22 33 44 55\ \ 31 32\ \ 43\ \ 51 53 54 \ \ 23 \ \ 14 44 \ \ 16 26 ) \\ 61\mbox{}\hspace{10 mm}colIndex = (0 1\ \ 2\ \ 0 2 3)\\ 62\mbox{}\hspace{10 mm}rowPointer = (0 0 0 2 3 6)\\ 63\mbox{}\hspace{10 mm}rowIndex = (0\ \ 1\ \ 0\ \ 0 1)\\ 64\mbox{}\hspace{10 mm}colPointer = ( 0 0 1 2 2 3 5) \\ 65Note that for an empty row $i$ (resp. column $j$), rowPointer($i$)=rowPointer($i-1$) (resp. colPointer($j$)=colPointer($j-1$)). By the way, rowPointer($i$)-rowPointer($i-1$) gives the number of stored entries on row $i-1$. 66\item symmetric compressed storage is devoted to square matrix with symmetric storage, the matrix may be not symmetric.. In that case, only the storage of lower triangular part of matrix is described by the three vectors (those of row part of dual storage): \\ 67\mbox{}\hspace{10 mm}values = (0,\text{diag}(A), $A_{\mathcal{C}_11}$, ..., $A_{\mathcal{C}_ii}$, ..., $A_{\mathcal{C}_mm}$) if $A$ has a symmetry property\\ 68\mbox{}\hspace{10 mm}values = (0,\text{diag}(A), $A_{\mathcal{C}_11}$, ..., $A_{\mathcal{C}_ii}$, ..., $A_{\mathcal{C}_mm}$,$A_{\mathcal{C}_11}$, ..., $A_{\mathcal{C}_jj}$, ..., $A_{\mathcal{C}_mm}$) if $A$ has no symmetry property\\ 69\mbox{}\hspace{10 mm}colIndex = ($\mathcal{C}_1$, ..., $\mathcal{C}_i$, ..., $\mathcal{C}_m$)\\ 70\mbox{}\hspace{10 mm}rowPointer = ($p_1$,...,$p_i$,...$,p_m$, $p_{m+1}$)\\ 71where the meaning of $\mathcal{C}_i$ and $p_i$ is the same as dual storage.\\ 72For instance, the $5\times 5$ non symmetric matrix with symmetric storage 73\[ 74B=\left[ 75\begin{array}{ccccc} 7611 & 0 & 13 & 0 & 15 \\ 770 & 22 & 23 & 0 & 0 \\ 7831 & 32 & 33 & 34 & 35\\ 790 & 0 & 43 & 44 & 45 \\ 8051 & 0 & 53 & 54 & 55 81\end{array} 82\right] 83\] 84has the symmetric compressed storage vectors: \\ 85\mbox{}\hspace{10 mm}values = ( 0 11 22 33 44 55\ \ 31 32\ \ 43\ \ 51 53 54\ \ 13 23\ \ 34\ \ 15 35 45) \\ 86\mbox{}\hspace{10 mm}colIndex = (0 1\ \ 2\ \ 0 2 3)\\ 87\mbox{}\hspace{10 mm}rowPointer = (0 0 0 2 3 6)\\ 88\end{itemize} 89\textdbend \ \ Be care with the fact that actual matrix values begins at adress 1 in values vector defined outside the storage stuff. 90 91\subsection{The {\classtitle CsStorage} class} 92 93The {\class CsStorage} class has no member attribute. There are some basic constructors just calling {\class MatrixStorage} constructors: 94\vspace{.1cm} 95\begin{lstlisting}[] 96class CsStorage : public MatrixStorage 97{public : 98 CsStorage(AccessType = _dual); 99 CsStorage(Number, AccessType = _dual); 100 CsStorage(Number, Number, AccessType = _dual); 101 virtual ~CsStorage() {} 102 protected : 103 void buildCsStorage(const std::vector<std::vector<Number> >&, 104 std::vector<Number>&, std::vector<Number>&); 105\end{lstlisting} 106\vspace{.1cm} 107The \verb?buildCsStorage? is a general member function building storage vectors from lists of column indices by row. It is used by any child class of {\class CsStorage} class. 108{\class CsStorage} objects do not have to be instantiated. This class acts as an interface to particular compressed storages and gathers all common functionalities of dense storages, some being virtuals (some template line declaration are omitted): 109\vspace{.1cm} 110\begin{lstlisting}[] 111virtual Number size() const = 0; 112virtual Number lowerPartSize() const; 113virtual Number upperPartSize() const; 114template<typename Iterator> 115 void printEntriesAll(StrucType, Iterator& , const std::vector<Number>&, 116 const std::vector<Number>&, Number, Number, Number, 117 const String&, Number, std::ostream&) const; 118 void printEntriesTriangularPart(StrucType, Iterator&, Iterator&, 119 const std::vector<Number>&, const std::vector<Number>&, 120 Number, Number, Number, const String&, Number, 121 std::ostream&) const; 122 void printCooTriangularPart(std::ostream&, Iterator&, const std::vector<Number>&, 123 const std::vector<Number>&, bool, 124 SymType sym = _noSymmetry) const; 125 void printCooDiagonalPart(std::ostream&, Iterator&, Number) const; 126 127template <typename T> 128 void loadCsFromFileDense(std::istream&, std::vector<T>&, std::vector<Number>&, 129 std::vector<Number>&, SymType, bool); 130 void loadCsFromFileCoo(std::istream&, std::vector<T>&, std::vector<Number>&, 131 std::vector<Number>&, SymType, bool); 132 void loadCsFromFileDense(std::istream&, std::vector<T>&, std::vector<Number>&, 133 std::vector<Number>&, std::vector<Number>&, 134 std::vector<Number>&, SymType, bool); 135 void loadCsFromFileCoo(std::istream&, std::vector<T>&, std::vector<Number>&, 136 std::vector<Number>&, std::vector<Number>&, 137 std::vector<Number>&, SymType, bool); 138\end{lstlisting} 139\vspace{.2cm} 140The {\class CsStorage} class provides the real code of product of matrix and vector, using iterators as arguments to by-pass the template type of matrix values. For dual and symmetric storage, the computation is performed by splitting the matrix in its diagonal, lower and upper part (template line are omitted): 141\vspace{.1cm} 142\begin{lstlisting}[] 143template<typename MatIterator, typename VecIterator, typename ResIterator> 144 void diagonalMatrixVector(MatIterator&, VecIterator&, ResIterator&, 145 ResIterator&) const; 146 void lowerMatrixVector(const std::vector<Number>&, const std::vector<Number>&, 147 MatIterator&, VecIterator&, ResIterator&, SymType sym) const; 148 void upperMatrixVector(const std::vector<Number>&, const std::vector<Number>&, 149 MatIterator&, VecIterator&, ResIterator&, SymType) const; 150 void rowMatrixVector(const std::vector<Number>&, const std::vector<Number>&, 151 MatIterator&, VecIterator&, ResIterator&) const; 152 void columnMatrixVector(const std::vector<Number>&, const std::vector<Number>&, 153 MatIterator&, VecIterator&, ResIterator&) const; 154 void diagonalVectorMatrix(MatIterator&, VecIterator&, ResIterator&, 155 ResIterator&) const; 156 void lowerVectorMatrix(const std::vector<Number>&, const std::vector<Number>&, 157 MatIterator&, VecIterator&, ResIterator&, SymType sym) const; 158 void upperVectorMatrix(const std::vector<Number>&, const std::vector<Number>&, 159 MatIterator&, VecIterator&, ResIterator&, SymType) const; 160 void rowVectorMatrix(const std::vector<Number>&, const std::vector<Number>&, 161 MatIterator&, VecIterator&, ResIterator&) const; 162 void columnVectorMatrix(const std::vector<Number>&, const std::vector<Number>&, 163 MatIterator&, VecIterator&, ResIterator&) const; 164\end{lstlisting} 165\vspace{.1cm} 166Besides the product of matrix and vector, the {\class CsStorage} provides solvers for matrix in its diagonal, lower and upper part 167\vspace{.1cm} 168\begin{lstlisting}[] 169 template<typename MatIterator, typename VecIterator, typename ResIterator> 170 void bzSorDiagonalMatrixVector(MatIterator& itd, const VecIterator& itvb, 171 ResIterator& itrb, const Real w) const; 172 173 template<typename MatIterator, typename VecIterator, typename XIterator> 174 void bzSorLowerSolver(const MatIterator&, const MatIterator&, 175 VecIterator&, XIterator&, XIterator&, 176 const std::vector<Number>&, const std::vector<Number>&, const Real) const; 177 178 template<typename MatIterator, typename VecIterator, typename XIterator> 179 void bzSorDiagonalSolver(const MatIterator& itdb, VecIterator& itbb, 180 XIterator& itxb, XIterator& itxe, const Real w) const; 181 182 template<typename MatRevIterator, typename VecRevIterator, typename XRevIterator> 183 void bzSorUpperSolver(const MatRevIterator&, const MatRevIterator&, 184 VecRevIterator&, XRevIterator&, XRevIterator&, 185 const std::vector<Number>&, const std::vector<Number>&, const Real) const; 186\end{lstlisting} 187\vspace{.1cm} 188Addition of two matrices are implemented by 189\vspace{.1cm} 190\begin{lstlisting}[] 191 template<typename Mat1Iterator, typename Mat2Iterator, typename ResIterator> 192 void sumMatrixMatrix(Mat1Iterator&, Mat2Iterator&, ResIterator&, ResIterator&) const; 193\end{lstlisting} 194\vspace{.1cm} 195\displayInfos{library=largeMatrix, header=CsStorage.hpp, implementation=CsStorage.cpp, test={test\_LargeMatrixCstorage.cpp}, header dep={MatrixStorage.hpp, config.h, utils.h}} 196 197\subsection{{\classtitle RowCsStorage} and {\classtitle ColCsStorage} classes} 198 199As mentioned before, row compressed storage are based on the column indices vector and the row pointers vector. So the {\class RowCsStorage} class carries this two vectors: 200\vspace{.1cm} 201\begin{lstlisting} 202class RowCsStorage : public CsStorage 203{protected : 204 std::vector<Number> colIndex_; //vector of column index of non zero value 205 std::vector<Number> rowPointer_; //vector of positions of begining of rows 206 ... 207\end{lstlisting} 208\vspace{.2cm} 209The class provides a default constructor with no construction of storage vectors and constructors from a list of $(i,j)$ index (coordinates) or a lists of column indices by row, constructing the compressed storage vectors: 210\vspace{.1cm} 211\begin{lstlisting}[] 212RowCsStorage(Number nr=0, Number nc=0); 213RowCsStorage(Number, Number, const std::vector< std::vector<Number> >&, 214 const std::vector< std::vector<Number> >&); 215RowCsStorage(Number, Number, const std::vector< std::vector<Number> >&); 216~RowCsStorage() {}; 217\end{lstlisting} 218\vspace{.2cm} 219The class provides most of the virtual methods declared in {\class MatrixStorage} class. For sake of simplicity, we report here only function with \verb?Real? type but versions with \verb?Complex?, \verb?Matrix<Real>?, \verb?Matrix<Complex>? and mixed types are also provided. Some template line declarations are also omitted. 220\vspace{.1cm} 221\begin{lstlisting}[] 222Number size() const; 223Number pos(Number i, Number j, SymType s=_noSymmetry) const; 224void positions(const std::vector<Number>&, const std::vector<Number>&, 225 std::vector<Number>&, bool errorOn=true, 226 SymType s=_noSymmetry) const; 227void printEntries(std::ostream&, const std::vector<Real>&, Number, SymType) const; 228void printCooMatrix(std::ostream&, const std::vector<Real>&, 229 SymType s=_noSymmetry) const; 230void loadFromFileDense(std::istream&, std::vector<Real>&, SymType, bool ); 231void loadFromFileCoo(std::istream& , std::vector<Real>&, SymType, bool); 232template<typename M, typename V, typename R> 233 void multMatrixVector(const std::vector<M>&, const std::vector<V>&, 234 std::vector<R>&) const; 235 void multVectorMatrix(const std::vector<M>&, const std::vector<V>&, 236 std::vector<R>&) const; 237 void multMatrixVector(const std::vector<Real>&, const std::vector<Real>&, 238 std::vector<Real>&, SymType) const; 239 void multVectorMatrix(const std::vector<Real>&, const std::vector<Real>&, 240 std::vector<Real>&, SymType) const; 241template<typename M1, typename M2, typename R> 242 void addMatrixMatrix(const std::vector<M1>&, const std::vector<M2>&, std::vector<R>&) const; //!< templated row dense Matrix + Matrix 243 void addMatrixMatrix(const std::vector<Real>& m, const std::vector<Real>& v, std::vector<Real>& rv) const 244 { addMatrixMatrix<>(m, v, rv);} 245\end{lstlisting} 246\vspace{.1cm} 247There is no \verb?printDenseMatrix? function because the general one defined in {\class MatrixStorage} class is sufficiently efficient. \\ 248\\ 249The {\class ColCsStorage} class is very similar to the {\class RowCsStorage} class, except that it manages a row indices vector and a column pointers vector: 250\vspace{.1cm} 251\begin{lstlisting} 252class ColCsStorage : public CsStorage 253{protected : 254 std::vector<Number> rowIndex_; //!< vector of row index of non zero value 255 std::vector<Number> colPointer_; //!< vector of positions of begining of cols 256 ... 257\end{lstlisting} 258\vspace{.2cm} 259Its constructors have a similar structure (same arguments) and all prototypes of member functions are the same as {\class ColCsStorage} member functions. We do not repeat them. 260\vspace{.1cm} 261XXX=Row or Col 262\displayInfos{library=largeMatrix, header=XXXCsStorage.hpp, implementation=XXXCsStorage.cpp, test={test\_LargeMatrixCsStorage.cpp}, header dep={CsStorage.hpp, MatrixStorage.hpp, config.h, utils.h}} 263 264\subsection{{\classtitle DualCsStorage} and {\classtitle SymCsStorage} classes} 265 266Dual compressed storage travels the matrix as diagonal, strict lower and upper parts. Column indices and row pointers vectors are attached to strict lower part and row indices and column pointers vectors are attached to strict upper part: 267\vspace{.1cm} 268\begin{lstlisting} 269class DualCsStorage : public CsStorage 270{protected : 271 std::vector<Number> colIndex_; //vector of column index of non zero value 272 std::vector<Number> rowPointer_; //vector of positions of begining of rows 273 std::vector<Number> rowIndex_; //vector of row index of non zero value 274 std::vector<Number> colPointer_; //vector of positions of begining of cols 275 ... 276\end{lstlisting} 277\vspace{.2cm} 278{\class DualCsStorage} class provides basic constructor (no construction of storage vectors), constructor from a pair of global numbering vectors or list of column indices by rows. 279Both of them create the compressed storage vector using the auxiliary function \verb?buildStorage?: 280\vspace{.1cm} 281\begin{lstlisting} 282DualCsStorage(Number nr=0, Number nc=0); 283DualCsStorage(Number, Number, const std::vector< std::vector<Number> >&, 284 const std::vector< std::vector<Number> >&); 285DualCsStorage(Number, Number, const std::vector<std::vector<Number> >&); 286void buildStorage(const std::vector<std::vector<Number> >&); 287~DualCsStorage() {}; 288\end{lstlisting} 289\vspace{.2cm} 290The class provides most of the virtual methods declared in {\class MatrixStorage} class. For sake of simplicity, we report here only function with \verb?Real? type but versions with \verb?Complex?, \verb?Matrix<Real>?, \verb?Matrix<Complex>? and mixed types are also provided. Some template line declarations are also omitted. 291\vspace{.1cm} 292\begin{lstlisting}[] 293Number size() const; 294Number lowerPartSize() const ; 295 Number upperPartSize() const; 296Number pos(Number i, Number j, SymType s=_noSymmetry) const; 297void positions(const std::vector<Number>&, const std::vector<Number>&, 298 std::vector<Number>&, bool errorOn=true, 299 SymType s=_noSymmetry) const; 300void printEntries(std::ostream&, const std::vector<Real>&, Number, SymType) const; 301void printCooMatrix(std::ostream&, const std::vector<Real>&, 302 SymType s=_noSymmetry) const; 303void loadFromFileDense(std::istream&, std::vector<Real>&, SymType, bool ); 304void loadFromFileCoo(std::istream& , std::vector<Real>&, SymType, bool); 305template<typename M, typename V, typename R> 306 void multMatrixVector(const std::vector<M>&, const std::vector<V>&, 307 std::vector<R>&) const; 308 void multVectorMatrix(const std::vector<M>&, const std::vector<V>&, 309 std::vector<R>&) const; 310 void multMatrixVector(const std::vector<Real>&, const std::vector<Real>&, 311 std::vector<Real>&, SymType) const; 312 void multVectorMatrix(const std::vector<Real>&, const std::vector<Real>&, 313 std::vector<Real>&, SymType) const; 314template<typename M1, typename M2, typename R> 315 void addMatrixMatrix(const std::vector<M1>&, const std::vector<M2>&, std::vector<R>&) const; 316 void addMatrixMatrix(const std::vector<Real>& m, const std::vector<Real>& v, std::vector<Real>& rv) const 317 { addMatrixMatrix<>(m, v, rv);} 318\end{lstlisting} 319\vspace{.2cm} 320 321The {\class SymCsStorage} class is very similar to the {\class DualCsStorage} class, except that it addresses only square matrix with symmetric storage and, 322thus, does not manage row indices vector and column pointers vectors because the upper part has same storage as lower part (transposed). Note that matrix may be have no symmetry property but a symmetric storage. In that case, the upper part is stored. 323\vspace{.1cm} 324\begin{lstlisting} 325class SymCsStorage : public CsStorage 326{protected : 327 std::vector<Number> colndex_; //!< vector of row index of non zero value 328 std::vector<Number> rowPointer_; //!< vector of positions of begining of cols 329 ... 330\end{lstlisting} 331\vspace{.1cm} 332Contrary to the row compressed storage, in the SymCsStorage, the diagonal is first stored then the lower part of the matrix. \\ 333Its constructors have a similar structure (same arguments) to the {\class DualCsStorage} constructors and all prototypes of member functions are the same as {\class DualCsStorage} member functions. We do not repeat them. 334 335Different from other {\class CsStorage} classes, the {\class SymCsStorage} class provides some functions to deal with the {\class SorSolver} class and {\class SsorSolver} class. Only specialized functions with \verb?Real? are listed in the following 336\vspace{.1cm} 337\begin{lstlisting}[deletekeywords={[3] x}] 338void sorDiagonalMatrixVector(const std::vector<Real>& m, const std::vector<Real>& v, std::vector<Real>& rv, const Real w) const 339{ sorDiagonalMatrixVector<>(m, v, rv, w); } 340void sorLowerMatrixVector(const std::vector<Real>& m, const std::vector<Real>& v, std::vector<Real>& rv, const Real w, const SymType sym) const 341{ sorLowerMatrixVector<>(m, v, rv, w, sym); } 342void sorUpperMatrixVector(const std::vector<Real>& m, const std::vector<Real>& v, std::vector<Real>& rv, const Real w, const SymType sym) const 343{ sorUpperMatrixVector<>(m, v, rv, w, sym); } 344void sorDiagonalSolve(const std::vector<Real>& m, const std::vector<Real>& b, std::vector<Real>& x, const Real w) const 345{ sorDiagonalSolve<>(m, b, x, w); } 346void sorLowerSolve(const std::vector<Real>& m, const std::vector<Real>& b, std::vector<Real>& x, const Real w) const 347{ sorLowerSolve<>(m, b, x, w); } 348void sorUpperSolve(const std::vector<Real>& m, const std::vector<Real>& b, std::vector<Real>& x, const Real w, const SymType sym) const 349{ sorUpperSolve<>(m, b, x, w, sym); } 350\end{lstlisting} 351\vspace{.1cm} 352XXX=Dual or Sym 353 354\displayInfos{library=largeMatrix, header=XXXCsStorage.hpp, implementation=XXXCsStorage.cpp, test={test\_LargeMatrixCsStorage.cpp}, header dep={CsStorage.hpp, MatrixStorage.hpp, config.h, utils.h}} 355