So-Bogus
A c++ sparse block matrix library aimed at Second Order cone problems
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
SparseConversions.hpp
1 /*
2  * This file is part of bogus, a C++ sparse block matrix library.
3  *
4  * Copyright 2013 Gilles Daviet <gdaviet@gmail.com>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
10 
11 
12 #ifndef BOGUS_EIGEN_SPARSE_CONVERSIONS_HPP
13 #define BOGUS_EIGEN_SPARSE_CONVERSIONS_HPP
14 
15 #include "SparseHeader.hpp"
16 
17 #include "../Block/SparseBlockMatrix.hpp"
18 #include "../Block/Access.hpp"
19 #include "../Block/SparseBlockIndexComputer.hpp"
20 
21 #include <map>
22 
23 // Conversions to Sparse Matrix
24 namespace bogus
25 {
26 
27 template< typename EigenDerived, typename BogusDerived >
28 void convert( const Eigen::SparseMatrixBase< EigenDerived >& source,
29  SparseBlockMatrixBase< BogusDerived >& dest,
30  int destRowsPerBlock = 0, int destColsPerBlock = 0
31  )
32 {
33  typedef BlockMatrixTraits< BogusDerived > Traits ;
34  typedef typename Traits::Index Index ;
35  typedef typename Traits::BlockPtr BlockPtr ;
36 
37  const Index RowsPerBlock = destRowsPerBlock
38  ? (Index) destRowsPerBlock
39  : (Index) Traits::RowsPerBlock ;
40  const Index ColsPerBlock = destColsPerBlock
41  ? (Index) destColsPerBlock
42  : (Index) Traits::ColsPerBlock ;
43 
44  assert( RowsPerBlock != (Index) -1 ) ;
45  assert( ColsPerBlock != (Index) -1 ) ;
46 
47  BOGUS_STATIC_ASSERT(
48  ( ( (bool) Eigen::SparseMatrixBase< EigenDerived >::IsRowMajor )
49  ^ ( (bool) Traits::is_col_major ) ),
50  MATRICES_ORDERING_IS_INCONSISTENT ) ;
51 
52  assert( 0 == ( source.rows() % RowsPerBlock ) ) ;
53  assert( 0 == ( source.cols() % ColsPerBlock ) ) ;
54 
55  dest.clear() ;
56  dest.setRows( source.rows() / RowsPerBlock, RowsPerBlock ) ;
57  dest.setCols( source.cols() / ColsPerBlock, ColsPerBlock ) ;
58 
59  const Index blockSize = Traits::is_col_major ? ColsPerBlock : RowsPerBlock ;
60  for( Index outer = 0 ; outer < dest.majorIndex().outerSize() ; ++outer )
61  {
62  // I - compute non-zero blocks
63  std::map < Index, BlockPtr > nzBlocks ;
64 
65  for( Index i = 0 ; i < blockSize ; ++i )
66  {
67  for( typename EigenDerived::InnerIterator innerIt( source.derived(), outer*blockSize + i ) ;
68  innerIt ; ++innerIt )
69  {
70  const Index blockId = (Index) ( innerIt.index() ) / blockSize ;
71  if( Traits::is_symmetric && blockId > outer ) break ;
72  nzBlocks[ blockId ] = 0 ;
73  }
74  }
75 
76  // II - Insert them in block mat
77  for( typename std::map< Index, BlockPtr >::iterator bIt = nzBlocks.begin() ; bIt != nzBlocks.end() ; ++bIt )
78  {
79  bIt->second = (BlockPtr) dest.nBlocks() ;
80  dest.template insertByOuterInner< true >( outer, bIt->first ).setZero( RowsPerBlock, ColsPerBlock ) ;
81  }
82 
83  // III - copy values
84  for( Index i = 0 ; i < blockSize ; ++i )
85  {
86  for( typename EigenDerived::InnerIterator innerIt( source.derived(), outer*blockSize + i ) ;
87  innerIt ; ++innerIt )
88  {
89  const Index blockId = (Index) ( innerIt.index() ) / blockSize ;
90  if( Traits::is_symmetric && blockId > outer ) break ;
91  const Index binn = innerIt.index() - blockId * blockSize ;
92  const Index brow = Traits::is_col_major ? binn : i ;
93  const Index bcol = Traits::is_col_major ? i : binn ;
94 
95  dest.block( nzBlocks[ blockId ] ) ( brow, bcol ) = innerIt.value() ;
96  }
97  }
98 
99  // IV - Symmetrify diagonal block if required
100  if( Traits::is_symmetric )
101  {
102  typename std::map< Index, BlockPtr >::const_iterator diagPtr = nzBlocks.find( outer ) ;
103  if( diagPtr != nzBlocks.end() )
104  {
105  const typename Traits::BlockType diagBlock = dest.block( diagPtr->second ) ;
106  dest.block( diagPtr->second ) = .5 * ( diagBlock + TransposeIf< Traits::is_symmetric >::get( diagBlock ) ) ;
107  }
108  }
109 
110  }
111 
112  dest.finalize() ;
113 
114 }
115 
116 template< typename BogusDerived, typename EigenScalar, int EigenOptions, typename EigenIndex >
117 void convert( const SparseBlockMatrixBase< BogusDerived >& source,
118  Eigen::SparseMatrix< EigenScalar, EigenOptions, EigenIndex >& dest )
119 {
120  typedef BlockMatrixTraits< BogusDerived > Traits ;
121  typedef typename Traits::Index Index ;
122 
123  typedef Eigen::SparseMatrix< EigenScalar, EigenOptions, EigenIndex > EigenMatrixType ;
124 
125  typedef SparseBlockIndexGetter< BogusDerived, Traits::is_symmetric ||
126  ( (bool) EigenMatrixType::IsRowMajor ) != ( (bool) Traits::is_col_major ) > IndexGetter ;
127 
128  dest.setZero() ;
129  dest.resize( source.rows(), source.cols() ) ;
130 
131  typename BogusDerived::UncompressedIndexType auxIndex ;
132  const typename IndexGetter::ReturnType& index = IndexGetter::getOrCompute( source, auxIndex ) ;
133 
134  const std::vector< Index > &outerOffsets =
135  ( (bool) EigenMatrixType::IsRowMajor ) == ( (bool) Traits::is_col_major )
136  ? source.majorIndex().innerOffsets : source.minorIndex().innerOffsets ;
137 
138  for( Index outerBlock = 0 ; outerBlock < index.outerSize() ; ++outerBlock )
139  {
140  for( Index outer = outerOffsets[ outerBlock ] ; outer < outerOffsets[ outerBlock+1 ] ; ++outer )
141  {
142  dest.startVec( outer ) ;
143  for( typename IndexGetter::ReturnType::InnerIterator it( index, outerBlock ) ;
144  it ; ++it )
145  {
146  for( Index inner = index.innerOffsets[ it.inner() ] ; inner < index.innerOffsets[ it.inner()+1 ] ; ++inner )
147  {
148  if( Traits::is_symmetric && inner > outer ) break ;
149 
150  const Index bout = outer - outerOffsets[ outerBlock ] ;
151  const Index binn = inner - index.innerOffsets[ it.inner() ] ;
152  const Index bcol = EigenMatrixType::IsRowMajor ? binn : bout ;
153  const Index brow = EigenMatrixType::IsRowMajor ? bout : binn ;
154  const EigenScalar val = source.block( it.ptr() )( brow, bcol ) ;
155 
156  dest.insertBackByOuterInner( outer, inner ) = val;
157  }
158  }
159  }
160 
161  }
162 
163 }
164 
165 } // naemspace bogus
166 
167 
168 #endif