~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// This file is part of Eigen, a lightweight C++ template library
 
2
// for linear algebra.
 
3
//
 
4
// Copyright (C) 2009 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_SPARSE_SELFADJOINTVIEW_H
 
11
#define EIGEN_SPARSE_SELFADJOINTVIEW_H
 
12
 
 
13
namespace Eigen { 
 
14
 
 
15
/** \ingroup SparseCore_Module
 
16
  * \class SparseSelfAdjointView
 
17
  *
 
18
  * \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
 
19
  *
 
20
  * \param MatrixType the type of the dense matrix storing the coefficients
 
21
  * \param UpLo can be either \c #Lower or \c #Upper
 
22
  *
 
23
  * This class is an expression of a sefladjoint matrix from a triangular part of a matrix
 
24
  * with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
 
25
  * and most of the time this is the only way that it is used.
 
26
  *
 
27
  * \sa SparseMatrixBase::selfadjointView()
 
28
  */
 
29
template<typename Lhs, typename Rhs, int UpLo>
 
30
class SparseSelfAdjointTimeDenseProduct;
 
31
 
 
32
template<typename Lhs, typename Rhs, int UpLo>
 
33
class DenseTimeSparseSelfAdjointProduct;
 
34
 
 
35
namespace internal {
 
36
  
 
37
template<typename MatrixType, unsigned int UpLo>
 
38
struct traits<SparseSelfAdjointView<MatrixType,UpLo> > : traits<MatrixType> {
 
39
};
 
40
 
 
41
template<int SrcUpLo,int DstUpLo,typename MatrixType,int DestOrder>
 
42
void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm = 0);
 
43
 
 
44
template<int UpLo,typename MatrixType,int DestOrder>
 
45
void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm = 0);
 
46
 
 
47
}
 
48
 
 
49
template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
 
50
  : public EigenBase<SparseSelfAdjointView<MatrixType,UpLo> >
 
51
{
 
52
  public:
 
53
 
 
54
    typedef typename MatrixType::Scalar Scalar;
 
55
    typedef typename MatrixType::Index Index;
 
56
    typedef Matrix<Index,Dynamic,1> VectorI;
 
57
    typedef typename MatrixType::Nested MatrixTypeNested;
 
58
    typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
 
59
 
 
60
    inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix)
 
61
    {
 
62
      eigen_assert(rows()==cols() && "SelfAdjointView is only for squared matrices");
 
63
    }
 
64
 
 
65
    inline Index rows() const { return m_matrix.rows(); }
 
66
    inline Index cols() const { return m_matrix.cols(); }
 
67
 
 
68
    /** \internal \returns a reference to the nested matrix */
 
69
    const _MatrixTypeNested& matrix() const { return m_matrix; }
 
70
    _MatrixTypeNested& matrix() { return m_matrix.const_cast_derived(); }
 
71
 
 
72
    /** Efficient sparse self-adjoint matrix times dense vector/matrix product */
 
73
    template<typename OtherDerived>
 
74
    SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>
 
75
    operator*(const MatrixBase<OtherDerived>& rhs) const
 
76
    {
 
77
      return SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>(m_matrix, rhs.derived());
 
78
    }
 
79
 
 
80
    /** Efficient dense vector/matrix times sparse self-adjoint matrix product */
 
81
    template<typename OtherDerived> friend
 
82
    DenseTimeSparseSelfAdjointProduct<OtherDerived,MatrixType,UpLo>
 
83
    operator*(const MatrixBase<OtherDerived>& lhs, const SparseSelfAdjointView& rhs)
 
84
    {
 
85
      return DenseTimeSparseSelfAdjointProduct<OtherDerived,_MatrixTypeNested,UpLo>(lhs.derived(), rhs.m_matrix);
 
86
    }
 
87
 
 
88
    /** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
 
89
      * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
 
90
      *
 
91
      * \returns a reference to \c *this
 
92
      *
 
93
      * To perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply
 
94
      * call this function with u.adjoint().
 
95
      */
 
96
    template<typename DerivedU>
 
97
    SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
 
98
    
 
99
    /** \internal triggered by sparse_matrix = SparseSelfadjointView; */
 
100
    template<typename DestScalar,int StorageOrder> void evalTo(SparseMatrix<DestScalar,StorageOrder,Index>& _dest) const
 
101
    {
 
102
      internal::permute_symm_to_fullsymm<UpLo>(m_matrix, _dest);
 
103
    }
 
104
    
 
105
    template<typename DestScalar> void evalTo(DynamicSparseMatrix<DestScalar,ColMajor,Index>& _dest) const
 
106
    {
 
107
      // TODO directly evaluate into _dest;
 
108
      SparseMatrix<DestScalar,ColMajor,Index> tmp(_dest.rows(),_dest.cols());
 
109
      internal::permute_symm_to_fullsymm<UpLo>(m_matrix, tmp);
 
110
      _dest = tmp;
 
111
    }
 
112
    
 
113
    /** \returns an expression of P H P^-1 */
 
114
    SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo> twistedBy(const PermutationMatrix<Dynamic,Dynamic,Index>& perm) const
 
115
    {
 
116
      return SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo>(m_matrix, perm);
 
117
    }
 
118
    
 
119
    template<typename SrcMatrixType,int SrcUpLo>
 
120
    SparseSelfAdjointView& operator=(const SparseSymmetricPermutationProduct<SrcMatrixType,SrcUpLo>& permutedMatrix)
 
121
    {
 
122
      permutedMatrix.evalTo(*this);
 
123
      return *this;
 
124
    }
 
125
 
 
126
 
 
127
    SparseSelfAdjointView& operator=(const SparseSelfAdjointView& src)
 
128
    {
 
129
      PermutationMatrix<Dynamic> pnull;
 
130
      return *this = src.twistedBy(pnull);
 
131
    }
 
132
 
 
133
    template<typename SrcMatrixType,unsigned int SrcUpLo>
 
134
    SparseSelfAdjointView& operator=(const SparseSelfAdjointView<SrcMatrixType,SrcUpLo>& src)
 
135
    {
 
136
      PermutationMatrix<Dynamic> pnull;
 
137
      return *this = src.twistedBy(pnull);
 
138
    }
 
139
    
 
140
 
 
141
    // const SparseLLT<PlainObject, UpLo> llt() const;
 
142
    // const SparseLDLT<PlainObject, UpLo> ldlt() const;
 
143
 
 
144
  protected:
 
145
 
 
146
    typename MatrixType::Nested m_matrix;
 
147
    mutable VectorI m_countPerRow;
 
148
    mutable VectorI m_countPerCol;
 
149
};
 
150
 
 
151
/***************************************************************************
 
152
* Implementation of SparseMatrixBase methods
 
153
***************************************************************************/
 
154
 
 
155
template<typename Derived>
 
156
template<unsigned int UpLo>
 
157
const SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView() const
 
158
{
 
159
  return derived();
 
160
}
 
161
 
 
162
template<typename Derived>
 
163
template<unsigned int UpLo>
 
164
SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView()
 
165
{
 
166
  return derived();
 
167
}
 
168
 
 
169
/***************************************************************************
 
170
* Implementation of SparseSelfAdjointView methods
 
171
***************************************************************************/
 
172
 
 
173
template<typename MatrixType, unsigned int UpLo>
 
174
template<typename DerivedU>
 
175
SparseSelfAdjointView<MatrixType,UpLo>&
 
176
SparseSelfAdjointView<MatrixType,UpLo>::rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha)
 
177
{
 
178
  SparseMatrix<Scalar,MatrixType::Flags&RowMajorBit?RowMajor:ColMajor> tmp = u * u.adjoint();
 
179
  if(alpha==Scalar(0))
 
180
    m_matrix.const_cast_derived() = tmp.template triangularView<UpLo>();
 
181
  else
 
182
    m_matrix.const_cast_derived() += alpha * tmp.template triangularView<UpLo>();
 
183
 
 
184
  return *this;
 
185
}
 
186
 
 
187
/***************************************************************************
 
188
* Implementation of sparse self-adjoint time dense matrix
 
189
***************************************************************************/
 
190
 
 
191
namespace internal {
 
192
template<typename Lhs, typename Rhs, int UpLo>
 
193
struct traits<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo> >
 
194
 : traits<ProductBase<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo>, Lhs, Rhs> >
 
195
{
 
196
  typedef Dense StorageKind;
 
197
};
 
198
}
 
199
 
 
200
template<typename Lhs, typename Rhs, int UpLo>
 
201
class SparseSelfAdjointTimeDenseProduct
 
202
  : public ProductBase<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo>, Lhs, Rhs>
 
203
{
 
204
  public:
 
205
    EIGEN_PRODUCT_PUBLIC_INTERFACE(SparseSelfAdjointTimeDenseProduct)
 
206
 
 
207
    SparseSelfAdjointTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
 
208
    {}
 
209
 
 
210
    template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
 
211
    {
 
212
      // TODO use alpha
 
213
      eigen_assert(alpha==Scalar(1) && "alpha != 1 is not implemented yet, sorry");
 
214
      typedef typename internal::remove_all<Lhs>::type _Lhs;
 
215
      typedef typename internal::remove_all<Rhs>::type _Rhs;
 
216
      typedef typename _Lhs::InnerIterator LhsInnerIterator;
 
217
      enum {
 
218
        LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit,
 
219
        ProcessFirstHalf =
 
220
                 ((UpLo&(Upper|Lower))==(Upper|Lower))
 
221
              || ( (UpLo&Upper) && !LhsIsRowMajor)
 
222
              || ( (UpLo&Lower) && LhsIsRowMajor),
 
223
        ProcessSecondHalf = !ProcessFirstHalf
 
224
      };
 
225
      for (Index j=0; j<m_lhs.outerSize(); ++j)
 
226
      {
 
227
        LhsInnerIterator i(m_lhs,j);
 
228
        if (ProcessSecondHalf)
 
229
        {
 
230
          while (i && i.index()<j) ++i;
 
231
          if(i && i.index()==j)
 
232
          {
 
233
            dest.row(j) += i.value() * m_rhs.row(j);
 
234
            ++i;
 
235
          }
 
236
        }
 
237
        for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i)
 
238
        {
 
239
          Index a = LhsIsRowMajor ? j : i.index();
 
240
          Index b = LhsIsRowMajor ? i.index() : j;
 
241
          typename Lhs::Scalar v = i.value();
 
242
          dest.row(a) += (v) * m_rhs.row(b);
 
243
          dest.row(b) += internal::conj(v) * m_rhs.row(a);
 
244
        }
 
245
        if (ProcessFirstHalf && i && (i.index()==j))
 
246
          dest.row(j) += i.value() * m_rhs.row(j);
 
247
      }
 
248
    }
 
249
 
 
250
  private:
 
251
    SparseSelfAdjointTimeDenseProduct& operator=(const SparseSelfAdjointTimeDenseProduct&);
 
252
};
 
253
 
 
254
namespace internal {
 
255
template<typename Lhs, typename Rhs, int UpLo>
 
256
struct traits<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo> >
 
257
 : traits<ProductBase<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo>, Lhs, Rhs> >
 
258
{};
 
259
}
 
260
 
 
261
template<typename Lhs, typename Rhs, int UpLo>
 
262
class DenseTimeSparseSelfAdjointProduct
 
263
  : public ProductBase<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo>, Lhs, Rhs>
 
264
{
 
265
  public:
 
266
    EIGEN_PRODUCT_PUBLIC_INTERFACE(DenseTimeSparseSelfAdjointProduct)
 
267
 
 
268
    DenseTimeSparseSelfAdjointProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
 
269
    {}
 
270
 
 
271
    template<typename Dest> void scaleAndAddTo(Dest& /*dest*/, Scalar /*alpha*/) const
 
272
    {
 
273
      // TODO
 
274
    }
 
275
 
 
276
  private:
 
277
    DenseTimeSparseSelfAdjointProduct& operator=(const DenseTimeSparseSelfAdjointProduct&);
 
278
};
 
279
 
 
280
/***************************************************************************
 
281
* Implementation of symmetric copies and permutations
 
282
***************************************************************************/
 
283
namespace internal {
 
284
  
 
285
template<typename MatrixType, int UpLo>
 
286
struct traits<SparseSymmetricPermutationProduct<MatrixType,UpLo> > : traits<MatrixType> {
 
287
};
 
288
 
 
289
template<int UpLo,typename MatrixType,int DestOrder>
 
290
void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm)
 
291
{
 
292
  typedef typename MatrixType::Index Index;
 
293
  typedef typename MatrixType::Scalar Scalar;
 
294
  typedef SparseMatrix<Scalar,DestOrder,Index> Dest;
 
295
  typedef Matrix<Index,Dynamic,1> VectorI;
 
296
  
 
297
  Dest& dest(_dest.derived());
 
298
  enum {
 
299
    StorageOrderMatch = int(Dest::IsRowMajor) == int(MatrixType::IsRowMajor)
 
300
  };
 
301
  
 
302
  Index size = mat.rows();
 
303
  VectorI count;
 
304
  count.resize(size);
 
305
  count.setZero();
 
306
  dest.resize(size,size);
 
307
  for(Index j = 0; j<size; ++j)
 
308
  {
 
309
    Index jp = perm ? perm[j] : j;
 
310
    for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
 
311
    {
 
312
      Index i = it.index();
 
313
      Index r = it.row();
 
314
      Index c = it.col();
 
315
      Index ip = perm ? perm[i] : i;
 
316
      if(UpLo==(Upper|Lower))
 
317
        count[StorageOrderMatch ? jp : ip]++;
 
318
      else if(r==c)
 
319
        count[ip]++;
 
320
      else if(( UpLo==Lower && r>c) || ( UpLo==Upper && r<c))
 
321
      {
 
322
        count[ip]++;
 
323
        count[jp]++;
 
324
      }
 
325
    }
 
326
  }
 
327
  Index nnz = count.sum();
 
328
  
 
329
  // reserve space
 
330
  dest.resizeNonZeros(nnz);
 
331
  dest.outerIndexPtr()[0] = 0;
 
332
  for(Index j=0; j<size; ++j)
 
333
    dest.outerIndexPtr()[j+1] = dest.outerIndexPtr()[j] + count[j];
 
334
  for(Index j=0; j<size; ++j)
 
335
    count[j] = dest.outerIndexPtr()[j];
 
336
  
 
337
  // copy data
 
338
  for(Index j = 0; j<size; ++j)
 
339
  {
 
340
    for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
 
341
    {
 
342
      Index i = it.index();
 
343
      Index r = it.row();
 
344
      Index c = it.col();
 
345
      
 
346
      Index jp = perm ? perm[j] : j;
 
347
      Index ip = perm ? perm[i] : i;
 
348
      
 
349
      if(UpLo==(Upper|Lower))
 
350
      {
 
351
        Index k = count[StorageOrderMatch ? jp : ip]++;
 
352
        dest.innerIndexPtr()[k] = StorageOrderMatch ? ip : jp;
 
353
        dest.valuePtr()[k] = it.value();
 
354
      }
 
355
      else if(r==c)
 
356
      {
 
357
        Index k = count[ip]++;
 
358
        dest.innerIndexPtr()[k] = ip;
 
359
        dest.valuePtr()[k] = it.value();
 
360
      }
 
361
      else if(( (UpLo&Lower)==Lower && r>c) || ( (UpLo&Upper)==Upper && r<c))
 
362
      {
 
363
        if(!StorageOrderMatch)
 
364
          std::swap(ip,jp);
 
365
        Index k = count[jp]++;
 
366
        dest.innerIndexPtr()[k] = ip;
 
367
        dest.valuePtr()[k] = it.value();
 
368
        k = count[ip]++;
 
369
        dest.innerIndexPtr()[k] = jp;
 
370
        dest.valuePtr()[k] = internal::conj(it.value());
 
371
      }
 
372
    }
 
373
  }
 
374
}
 
375
 
 
376
template<int _SrcUpLo,int _DstUpLo,typename MatrixType,int DstOrder>
 
377
void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DstOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm)
 
378
{
 
379
  typedef typename MatrixType::Index Index;
 
380
  typedef typename MatrixType::Scalar Scalar;
 
381
  SparseMatrix<Scalar,DstOrder,Index>& dest(_dest.derived());
 
382
  typedef Matrix<Index,Dynamic,1> VectorI;
 
383
  enum {
 
384
    SrcOrder = MatrixType::IsRowMajor ? RowMajor : ColMajor,
 
385
    StorageOrderMatch = int(SrcOrder) == int(DstOrder),
 
386
    DstUpLo = DstOrder==RowMajor ? (_DstUpLo==Upper ? Lower : Upper) : _DstUpLo,
 
387
    SrcUpLo = SrcOrder==RowMajor ? (_SrcUpLo==Upper ? Lower : Upper) : _SrcUpLo
 
388
  };
 
389
  
 
390
  Index size = mat.rows();
 
391
  VectorI count(size);
 
392
  count.setZero();
 
393
  dest.resize(size,size);
 
394
  for(Index j = 0; j<size; ++j)
 
395
  {
 
396
    Index jp = perm ? perm[j] : j;
 
397
    for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
 
398
    {
 
399
      Index i = it.index();
 
400
      if((int(SrcUpLo)==int(Lower) && i<j) || (int(SrcUpLo)==int(Upper) && i>j))
 
401
        continue;
 
402
                  
 
403
      Index ip = perm ? perm[i] : i;
 
404
      count[int(DstUpLo)==int(Lower) ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
 
405
    }
 
406
  }
 
407
  dest.outerIndexPtr()[0] = 0;
 
408
  for(Index j=0; j<size; ++j)
 
409
    dest.outerIndexPtr()[j+1] = dest.outerIndexPtr()[j] + count[j];
 
410
  dest.resizeNonZeros(dest.outerIndexPtr()[size]);
 
411
  for(Index j=0; j<size; ++j)
 
412
    count[j] = dest.outerIndexPtr()[j];
 
413
  
 
414
  for(Index j = 0; j<size; ++j)
 
415
  {
 
416
    
 
417
    for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
 
418
    {
 
419
      Index i = it.index();
 
420
      if((int(SrcUpLo)==int(Lower) && i<j) || (int(SrcUpLo)==int(Upper) && i>j))
 
421
        continue;
 
422
                  
 
423
      Index jp = perm ? perm[j] : j;
 
424
      Index ip = perm? perm[i] : i;
 
425
      
 
426
      Index k = count[int(DstUpLo)==int(Lower) ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
 
427
      dest.innerIndexPtr()[k] = int(DstUpLo)==int(Lower) ? (std::max)(ip,jp) : (std::min)(ip,jp);
 
428
      
 
429
      if(!StorageOrderMatch) std::swap(ip,jp);
 
430
      if( ((int(DstUpLo)==int(Lower) && ip<jp) || (int(DstUpLo)==int(Upper) && ip>jp)))
 
431
        dest.valuePtr()[k] = conj(it.value());
 
432
      else
 
433
        dest.valuePtr()[k] = it.value();
 
434
    }
 
435
  }
 
436
}
 
437
 
 
438
}
 
439
 
 
440
template<typename MatrixType,int UpLo>
 
441
class SparseSymmetricPermutationProduct
 
442
  : public EigenBase<SparseSymmetricPermutationProduct<MatrixType,UpLo> >
 
443
{
 
444
  public:
 
445
    typedef typename MatrixType::Scalar Scalar;
 
446
    typedef typename MatrixType::Index Index;
 
447
  protected:
 
448
    typedef PermutationMatrix<Dynamic,Dynamic,Index> Perm;
 
449
  public:
 
450
    typedef Matrix<Index,Dynamic,1> VectorI;
 
451
    typedef typename MatrixType::Nested MatrixTypeNested;
 
452
    typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
 
453
    
 
454
    SparseSymmetricPermutationProduct(const MatrixType& mat, const Perm& perm)
 
455
      : m_matrix(mat), m_perm(perm)
 
456
    {}
 
457
    
 
458
    inline Index rows() const { return m_matrix.rows(); }
 
459
    inline Index cols() const { return m_matrix.cols(); }
 
460
    
 
461
    template<typename DestScalar, int Options, typename DstIndex>
 
462
    void evalTo(SparseMatrix<DestScalar,Options,DstIndex>& _dest) const
 
463
    {
 
464
      internal::permute_symm_to_fullsymm<UpLo>(m_matrix,_dest,m_perm.indices().data());
 
465
    }
 
466
    
 
467
    template<typename DestType,unsigned int DestUpLo> void evalTo(SparseSelfAdjointView<DestType,DestUpLo>& dest) const
 
468
    {
 
469
      internal::permute_symm_to_symm<UpLo,DestUpLo>(m_matrix,dest.matrix(),m_perm.indices().data());
 
470
    }
 
471
    
 
472
  protected:
 
473
    MatrixTypeNested m_matrix;
 
474
    const Perm& m_perm;
 
475
 
 
476
};
 
477
 
 
478
} // end namespace Eigen
 
479
 
 
480
#endif // EIGEN_SPARSE_SELFADJOINTVIEW_H