1
// This file is part of Eigen, a lightweight C++ template library
2
// for linear algebra. Eigen itself is part of the KDE project.
4
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
7
// Eigen is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU Lesser General Public
9
// License as published by the Free Software Foundation; either
10
// version 3 of the License, or (at your option) any later version.
12
// Alternatively, you can redistribute it and/or
13
// modify it under the terms of the GNU General Public License as
14
// published by the Free Software Foundation; either version 2 of
15
// the License, or (at your option) any later version.
17
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20
// GNU General Public License for more details.
22
// You should have received a copy of the GNU Lesser General Public
23
// License and a copy of the GNU General Public License along with
24
// Eigen. If not, see <http://www.gnu.org/licenses/>.
32
* \brief Expression of a triangular matrix extracted from a given matrix
34
* \param MatrixType the type of the object in which we are taking the triangular part
35
* \param Mode the kind of triangular matrix expression to construct. Can be UpperTriangular, StrictlyUpperTriangular,
36
* UnitUpperTriangular, LowerTriangular, StrictlyLowerTriangular, UnitLowerTriangular. This is in fact a bit field; it must have either
37
* UpperTriangularBit or LowerTriangularBit, and additionnaly it may have either ZeroDiagBit or
40
* This class represents an expression of the upper or lower triangular part of
41
* a square matrix, possibly with a further assumption on the diagonal. It is the return type
42
* of MatrixBase::part() and most of the time this is the only way it is used.
44
* \sa MatrixBase::part()
46
template<typename MatrixType, unsigned int Mode>
47
struct ei_traits<Part<MatrixType, Mode> > : ei_traits<MatrixType>
49
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
50
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
52
Flags = (_MatrixTypeNested::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode,
53
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
57
template<typename MatrixType, unsigned int Mode> class Part
58
: public MatrixBase<Part<MatrixType, Mode> >
62
EIGEN_GENERIC_PUBLIC_INTERFACE(Part)
64
inline Part(const MatrixType& matrix) : m_matrix(matrix)
65
{ ei_assert(ei_are_flags_consistent<Mode>::ret); }
67
/** \sa MatrixBase::operator+=() */
68
template<typename Other> Part& operator+=(const Other& other);
69
/** \sa MatrixBase::operator-=() */
70
template<typename Other> Part& operator-=(const Other& other);
71
/** \sa MatrixBase::operator*=() */
72
Part& operator*=(const typename ei_traits<MatrixType>::Scalar& other);
73
/** \sa MatrixBase::operator/=() */
74
Part& operator/=(const typename ei_traits<MatrixType>::Scalar& other);
76
/** \sa operator=(), MatrixBase::lazyAssign() */
77
template<typename Other> void lazyAssign(const Other& other);
78
/** \sa MatrixBase::operator=() */
79
template<typename Other> Part& operator=(const Other& other);
81
inline int rows() const { return m_matrix.rows(); }
82
inline int cols() const { return m_matrix.cols(); }
83
inline int stride() const { return m_matrix.stride(); }
85
inline Scalar coeff(int row, int col) const
87
// SelfAdjointBit doesn't play any role here: just because a matrix is selfadjoint doesn't say anything about
88
// each individual coefficient, except for the not-very-useful-here fact that diagonal coefficients are real.
89
if( ((Flags & LowerTriangularBit) && (col>row)) || ((Flags & UpperTriangularBit) && (row>col)) )
91
if(Flags & UnitDiagBit)
92
return col==row ? (Scalar)1 : m_matrix.coeff(row, col);
93
else if(Flags & ZeroDiagBit)
94
return col==row ? (Scalar)0 : m_matrix.coeff(row, col);
96
return m_matrix.coeff(row, col);
99
inline Scalar& coeffRef(int row, int col)
101
EIGEN_STATIC_ASSERT(!(Flags & UnitDiagBit), WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED)
102
EIGEN_STATIC_ASSERT(!(Flags & SelfAdjointBit), COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED)
103
ei_assert( (Mode==UpperTriangular && col>=row)
104
|| (Mode==LowerTriangular && col<=row)
105
|| (Mode==StrictlyUpperTriangular && col>row)
106
|| (Mode==StrictlyLowerTriangular && col<row));
107
return m_matrix.const_cast_derived().coeffRef(row, col);
111
const MatrixType& _expression() const { return m_matrix; }
113
/** discard any writes to a row */
114
const Block<Part, 1, ColsAtCompileTime> row(int i) { return Base::row(i); }
115
const Block<Part, 1, ColsAtCompileTime> row(int i) const { return Base::row(i); }
116
/** discard any writes to a column */
117
const Block<Part, RowsAtCompileTime, 1> col(int i) { return Base::col(i); }
118
const Block<Part, RowsAtCompileTime, 1> col(int i) const { return Base::col(i); }
120
template<typename OtherDerived>
121
void swap(const MatrixBase<OtherDerived>& other)
123
Part<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
127
const typename MatrixType::Nested m_matrix;
130
Part& operator=(const Part&);
134
* \returns an expression of a triangular matrix extracted from the current matrix
136
* The parameter \a Mode can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c UnitUpperTriangular,
137
* \c LowerTriangular, \c StrictlyLowerTriangular, \c UnitLowerTriangular.
139
* \addexample PartExample \label How to extract a triangular part of an arbitrary matrix
141
* Example: \include MatrixBase_extract.cpp
142
* Output: \verbinclude MatrixBase_extract.out
144
* \sa class Part, part(), marked()
146
template<typename Derived>
147
template<unsigned int Mode>
148
const Part<Derived, Mode> MatrixBase<Derived>::part() const
153
template<typename MatrixType, unsigned int Mode>
154
template<typename Other>
155
inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator=(const Other& other)
157
if(Other::Flags & EvalBeforeAssigningBit)
159
typename MatrixBase<Other>::PlainMatrixType other_evaluated(other.rows(), other.cols());
160
other_evaluated.template part<Mode>().lazyAssign(other);
161
lazyAssign(other_evaluated);
164
lazyAssign(other.derived());
168
template<typename Derived1, typename Derived2, unsigned int Mode, int UnrollCount>
169
struct ei_part_assignment_impl
172
col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
173
row = (UnrollCount-1) % Derived1::RowsAtCompileTime
176
inline static void run(Derived1 &dst, const Derived2 &src)
178
ei_part_assignment_impl<Derived1, Derived2, Mode, UnrollCount-1>::run(dst, src);
180
if(Mode == SelfAdjoint)
183
dst.coeffRef(row, col) = ei_real(src.coeff(row, col));
185
dst.coeffRef(col, row) = ei_conj(dst.coeffRef(row, col) = src.coeff(row, col));
189
ei_assert(Mode == UpperTriangular || Mode == LowerTriangular || Mode == StrictlyUpperTriangular || Mode == StrictlyLowerTriangular);
190
if((Mode == UpperTriangular && row <= col)
191
|| (Mode == LowerTriangular && row >= col)
192
|| (Mode == StrictlyUpperTriangular && row < col)
193
|| (Mode == StrictlyLowerTriangular && row > col))
194
dst.copyCoeff(row, col, src);
199
template<typename Derived1, typename Derived2, unsigned int Mode>
200
struct ei_part_assignment_impl<Derived1, Derived2, Mode, 1>
202
inline static void run(Derived1 &dst, const Derived2 &src)
204
if(!(Mode & ZeroDiagBit))
205
dst.copyCoeff(0, 0, src);
209
// prevent buggy user code from causing an infinite recursion
210
template<typename Derived1, typename Derived2, unsigned int Mode>
211
struct ei_part_assignment_impl<Derived1, Derived2, Mode, 0>
213
inline static void run(Derived1 &, const Derived2 &) {}
216
template<typename Derived1, typename Derived2>
217
struct ei_part_assignment_impl<Derived1, Derived2, UpperTriangular, Dynamic>
219
inline static void run(Derived1 &dst, const Derived2 &src)
221
for(int j = 0; j < dst.cols(); ++j)
222
for(int i = 0; i <= j; ++i)
223
dst.copyCoeff(i, j, src);
227
template<typename Derived1, typename Derived2>
228
struct ei_part_assignment_impl<Derived1, Derived2, LowerTriangular, Dynamic>
230
inline static void run(Derived1 &dst, const Derived2 &src)
232
for(int j = 0; j < dst.cols(); ++j)
233
for(int i = j; i < dst.rows(); ++i)
234
dst.copyCoeff(i, j, src);
238
template<typename Derived1, typename Derived2>
239
struct ei_part_assignment_impl<Derived1, Derived2, StrictlyUpperTriangular, Dynamic>
241
inline static void run(Derived1 &dst, const Derived2 &src)
243
for(int j = 0; j < dst.cols(); ++j)
244
for(int i = 0; i < j; ++i)
245
dst.copyCoeff(i, j, src);
248
template<typename Derived1, typename Derived2>
249
struct ei_part_assignment_impl<Derived1, Derived2, StrictlyLowerTriangular, Dynamic>
251
inline static void run(Derived1 &dst, const Derived2 &src)
253
for(int j = 0; j < dst.cols(); ++j)
254
for(int i = j+1; i < dst.rows(); ++i)
255
dst.copyCoeff(i, j, src);
258
template<typename Derived1, typename Derived2>
259
struct ei_part_assignment_impl<Derived1, Derived2, SelfAdjoint, Dynamic>
261
inline static void run(Derived1 &dst, const Derived2 &src)
263
for(int j = 0; j < dst.cols(); ++j)
265
for(int i = 0; i < j; ++i)
266
dst.coeffRef(j, i) = ei_conj(dst.coeffRef(i, j) = src.coeff(i, j));
267
dst.coeffRef(j, j) = ei_real(src.coeff(j, j));
272
template<typename MatrixType, unsigned int Mode>
273
template<typename Other>
274
void Part<MatrixType, Mode>::lazyAssign(const Other& other)
276
const bool unroll = MatrixType::SizeAtCompileTime * Other::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT;
277
ei_assert(m_matrix.rows() == other.rows() && m_matrix.cols() == other.cols());
279
ei_part_assignment_impl
280
<MatrixType, Other, Mode,
281
unroll ? int(MatrixType::SizeAtCompileTime) : Dynamic
282
>::run(m_matrix.const_cast_derived(), other.derived());
286
* \returns a lvalue pseudo-expression allowing to perform special operations on \c *this.
288
* The \a Mode parameter can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c LowerTriangular,
289
* \c StrictlyLowerTriangular, \c SelfAdjoint.
291
* \addexample PartExample \label How to write to a triangular part of a matrix
293
* Example: \include MatrixBase_part.cpp
294
* Output: \verbinclude MatrixBase_part.out
296
* \sa class Part, MatrixBase::extract(), MatrixBase::marked()
298
template<typename Derived>
299
template<unsigned int Mode>
300
inline Part<Derived, Mode> MatrixBase<Derived>::part()
302
return Part<Derived, Mode>(derived());
305
/** \returns true if *this is approximately equal to an upper triangular matrix,
306
* within the precision given by \a prec.
308
* \sa isLowerTriangular(), extract(), part(), marked()
310
template<typename Derived>
311
bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
313
if(cols() != rows()) return false;
314
RealScalar maxAbsOnUpperTriangularPart = static_cast<RealScalar>(-1);
315
for(int j = 0; j < cols(); ++j)
316
for(int i = 0; i <= j; ++i)
318
RealScalar absValue = ei_abs(coeff(i,j));
319
if(absValue > maxAbsOnUpperTriangularPart) maxAbsOnUpperTriangularPart = absValue;
321
for(int j = 0; j < cols()-1; ++j)
322
for(int i = j+1; i < rows(); ++i)
323
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnUpperTriangularPart, prec)) return false;
327
/** \returns true if *this is approximately equal to a lower triangular matrix,
328
* within the precision given by \a prec.
330
* \sa isUpperTriangular(), extract(), part(), marked()
332
template<typename Derived>
333
bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
335
if(cols() != rows()) return false;
336
RealScalar maxAbsOnLowerTriangularPart = static_cast<RealScalar>(-1);
337
for(int j = 0; j < cols(); ++j)
338
for(int i = j; i < rows(); ++i)
340
RealScalar absValue = ei_abs(coeff(i,j));
341
if(absValue > maxAbsOnLowerTriangularPart) maxAbsOnLowerTriangularPart = absValue;
343
for(int j = 1; j < cols(); ++j)
344
for(int i = 0; i < j; ++i)
345
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnLowerTriangularPart, prec)) return false;
349
template<typename MatrixType, unsigned int Mode>
350
template<typename Other>
351
inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator+=(const Other& other)
353
return *this = m_matrix + other;
356
template<typename MatrixType, unsigned int Mode>
357
template<typename Other>
358
inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator-=(const Other& other)
360
return *this = m_matrix - other;
363
template<typename MatrixType, unsigned int Mode>
364
inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator*=
365
(const typename ei_traits<MatrixType>::Scalar& other)
367
return *this = m_matrix * other;
370
template<typename MatrixType, unsigned int Mode>
371
inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator/=
372
(const typename ei_traits<MatrixType>::Scalar& other)
374
return *this = m_matrix / other;
377
#endif // EIGEN_PART_H