• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_MAPPED_SPARSEMATRIX_H
11 #define EIGEN_MAPPED_SPARSEMATRIX_H
12 
13 namespace Eigen {
14 
15 /** \class MappedSparseMatrix
16   *
17   * \brief Sparse matrix
18   *
19   * \param _Scalar the scalar type, i.e. the type of the coefficients
20   *
21   * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
22   *
23   */
24 namespace internal {
25 template<typename _Scalar, int _Flags, typename _Index>
26 struct traits<MappedSparseMatrix<_Scalar, _Flags, _Index> > : traits<SparseMatrix<_Scalar, _Flags, _Index> >
27 {};
28 }
29 
30 template<typename _Scalar, int _Flags, typename _Index>
31 class MappedSparseMatrix
32   : public SparseMatrixBase<MappedSparseMatrix<_Scalar, _Flags, _Index> >
33 {
34   public:
35     EIGEN_SPARSE_PUBLIC_INTERFACE(MappedSparseMatrix)
36     enum { IsRowMajor = Base::IsRowMajor };
37 
38   protected:
39 
40     Index   m_outerSize;
41     Index   m_innerSize;
42     Index   m_nnz;
43     Index*  m_outerIndex;
44     Index*  m_innerIndices;
45     Scalar* m_values;
46 
47   public:
48 
49     inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
50     inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
51     inline Index innerSize() const { return m_innerSize; }
52     inline Index outerSize() const { return m_outerSize; }
53 
54     bool isCompressed() const { return true; }
55 
56     //----------------------------------------
57     // direct access interface
58     inline const Scalar* valuePtr() const { return m_values; }
59     inline Scalar* valuePtr() { return m_values; }
60 
61     inline const Index* innerIndexPtr() const { return m_innerIndices; }
62     inline Index* innerIndexPtr() { return m_innerIndices; }
63 
64     inline const Index* outerIndexPtr() const { return m_outerIndex; }
65     inline Index* outerIndexPtr() { return m_outerIndex; }
66     //----------------------------------------
67 
68     inline Scalar coeff(Index row, Index col) const
69     {
70       const Index outer = IsRowMajor ? row : col;
71       const Index inner = IsRowMajor ? col : row;
72 
73       Index start = m_outerIndex[outer];
74       Index end = m_outerIndex[outer+1];
75       if (start==end)
76         return Scalar(0);
77       else if (end>0 && inner==m_innerIndices[end-1])
78         return m_values[end-1];
79       // ^^  optimization: let's first check if it is the last coefficient
80       // (very common in high level algorithms)
81 
82       const Index* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner);
83       const Index id = r-&m_innerIndices[0];
84       return ((*r==inner) && (id<end)) ? m_values[id] : Scalar(0);
85     }
86 
87     inline Scalar& coeffRef(Index row, Index col)
88     {
89       const Index outer = IsRowMajor ? row : col;
90       const Index inner = IsRowMajor ? col : row;
91 
92       Index start = m_outerIndex[outer];
93       Index end = m_outerIndex[outer+1];
94       eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
95       eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient");
96       Index* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end],inner);
97       const Index id = r-&m_innerIndices[0];
98       eigen_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
99       return m_values[id];
100     }
101 
102     class InnerIterator;
103     class ReverseInnerIterator;
104 
105     /** \returns the number of non zero coefficients */
106     inline Index nonZeros() const  { return m_nnz; }
107 
108     inline MappedSparseMatrix(Index rows, Index cols, Index nnz, Index* outerIndexPtr, Index* innerIndexPtr, Scalar* valuePtr)
109       : m_outerSize(IsRowMajor?rows:cols), m_innerSize(IsRowMajor?cols:rows), m_nnz(nnz), m_outerIndex(outerIndexPtr),
110         m_innerIndices(innerIndexPtr), m_values(valuePtr)
111     {}
112 
113     /** Empty destructor */
114     inline ~MappedSparseMatrix() {}
115 };
116 
117 template<typename Scalar, int _Flags, typename _Index>
118 class MappedSparseMatrix<Scalar,_Flags,_Index>::InnerIterator
119 {
120   public:
121     InnerIterator(const MappedSparseMatrix& mat, Index outer)
122       : m_matrix(mat),
123         m_outer(outer),
124         m_id(mat.outerIndexPtr()[outer]),
125         m_start(m_id),
126         m_end(mat.outerIndexPtr()[outer+1])
127     {}
128 
129     inline InnerIterator& operator++() { m_id++; return *this; }
130 
131     inline Scalar value() const { return m_matrix.valuePtr()[m_id]; }
132     inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_id]); }
133 
134     inline Index index() const { return m_matrix.innerIndexPtr()[m_id]; }
135     inline Index row() const { return IsRowMajor ? m_outer : index(); }
136     inline Index col() const { return IsRowMajor ? index() : m_outer; }
137 
138     inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
139 
140   protected:
141     const MappedSparseMatrix& m_matrix;
142     const Index m_outer;
143     Index m_id;
144     const Index m_start;
145     const Index m_end;
146 };
147 
148 template<typename Scalar, int _Flags, typename _Index>
149 class MappedSparseMatrix<Scalar,_Flags,_Index>::ReverseInnerIterator
150 {
151   public:
152     ReverseInnerIterator(const MappedSparseMatrix& mat, Index outer)
153       : m_matrix(mat),
154         m_outer(outer),
155         m_id(mat.outerIndexPtr()[outer+1]),
156         m_start(mat.outerIndexPtr()[outer]),
157         m_end(m_id)
158     {}
159 
160     inline ReverseInnerIterator& operator--() { m_id--; return *this; }
161 
162     inline Scalar value() const { return m_matrix.valuePtr()[m_id-1]; }
163     inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_id-1]); }
164 
165     inline Index index() const { return m_matrix.innerIndexPtr()[m_id-1]; }
166     inline Index row() const { return IsRowMajor ? m_outer : index(); }
167     inline Index col() const { return IsRowMajor ? index() : m_outer; }
168 
169     inline operator bool() const { return (m_id <= m_end) && (m_id>m_start); }
170 
171   protected:
172     const MappedSparseMatrix& m_matrix;
173     const Index m_outer;
174     Index m_id;
175     const Index m_start;
176     const Index m_end;
177 };
178 
179 } // end namespace Eigen
180 
181 #endif // EIGEN_MAPPED_SPARSEMATRIX_H
182