So-Bogus
A c++ sparse block matrix library aimed at Second Order cone problems
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
SparseBlockIndex.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_SPARSEBLOCKINDEX_HPP
13 #define BOGUS_SPARSEBLOCKINDEX_HPP
14 
15 
16 #include <vector>
17 #include <cassert>
18 #include <algorithm>
19 
20 namespace bogus
21 {
22 
23 template< typename Derived >
25 {
26 } ;
27 
28 template< typename Derived >
30 {
32  typedef typename Traits::Index Index ;
33  typedef typename Traits::InnerIterator InnerIterator ;
34 
36 
37  typedef std::vector< Index > InnerOffsetsType ;
38 
40  bool valid ;
41 
42  SparseBlockIndexBase( bool _valid = true ) : valid( _valid )
43  {}
44 
45  Derived& derived() ;
46  const Derived& derived() const ;
47 
49 
50  Index outerSize( ) const ;
52 
53  Index innerSize( ) const ;
54 
56  bool hasInnerOffsets() const;
58  const InnerOffsetsType& innerOffsetsArray() const ;
59 
61 
62  Index nonZeros() const { return derived().nonZeros() ; }
63 
65  const Index* innerOffsetsData() const
66  {
67  assert( hasInnerOffsets() ) ;
68  // innerOffsetsArray() guaranteed to not be empty, we can dereference its first elt
69  return & innerOffsetsArray()[0] ;
70  }
71 
73  Index size( const Index outerIdx ) const ;
75  InnerIterator begin( const Index outerIdx ) const ;
77  InnerIterator last( const Index outerIdx ) const ;
79  InnerIterator end( const Index outerIdx ) const ;
80 
81 } ;
82 
84 template < bool Compressed, typename Index_, typename BlockPtr_ = Index_,
85  template <typename> class ArrayType = ResizableSequenceContainer >
86 struct SparseBlockIndex : public SparseBlockIndexBase< SparseBlockIndex< Compressed, Index_, BlockPtr_, ArrayType > >
87 {
88 
89  typedef Index_ Index ;
90  typedef BlockPtr_ BlockPtr ;
91 
93  typedef typename Base::InnerOffsetsType InnerOffsetsType ;
94  typedef typename Base::InnerIterator InnerIterator ;
95  using Base::valid ;
96 
98  typedef std::vector < std::pair< Index, BlockPtr > > Inner ;
100  typedef typename ArrayType< Inner >::Type Outer ;
101 
102  InnerOffsetsType innerOffsets ;
103  Outer outer ;
104 
105  bool ordered;
106 
107  SparseBlockIndex() : Base( ), ordered( true )
108  {}
109 
110  void resizeOuter( Index size )
111  {
112  outer.resize( size ) ;
113  }
114  void reserve( Index /*nnz*/)
115  {
116  }
117 
118  Index outerSize( ) const { return outer.size() ; }
119  const InnerOffsetsType& innerOffsetsArray() const { return innerOffsets ; }
120 
121  template < bool Ordered >
122  void insert( Index outIdx, Index inIdx, BlockPtr ptr )
123  {
124  outer[ outIdx ].push_back( std::make_pair( inIdx, ptr ) ) ;
125  ordered &= Ordered ;
126  }
127  void insertBack( Index outIdx, Index inIdx, BlockPtr ptr )
128  { insert< true >( outIdx, inIdx, ptr ) ; }
129 
130  void finalize()
131  {
132  if( ordered ) return ;
133 
134 #ifndef BOGUS_DONT_PARALLELIZE
135 #pragma omp parallel for
136 #endif
137  for( int i = 0 ; i < (Index) outer.size() ; ++i )
138  {
139  std::sort( outer[i].begin(), outer[i].end() ) ;
140  }
141  }
142 
143  void clear()
144  {
145  std::vector< Inner >( outer.size() ).swap( outer ) ;
146  valid = true ;
147  ordered = true ;
148  }
149 
150  SparseBlockIndex &operator=( const SparseBlockIndex &o )
151  {
152  if( &o != this )
153  {
154  outer = o.outer ;
155  valid = o.valid ;
156  if( !o.innerOffsets.empty() )
157  innerOffsets = o.innerOffsets ;
158  }
159  return *this ;
160  }
161 
162  template < typename SourceDerived >
163  SparseBlockIndex &operator=( const SparseBlockIndexBase< SourceDerived > &source ) ;
164 
165  SparseBlockIndex & move( SparseBlockIndex &uncompressed )
166  {
167  if( &uncompressed != this )
168  {
169  outer.swap( uncompressed.outer ) ;
170  if( !uncompressed.innerOffsets.empty() )
171  innerOffsets.swap( uncompressed.innerOffsets ) ;
172  valid = uncompressed.valid ;
173  uncompressed.valid = false ;
174  }
175  return *this ;
176  }
177 
178  template < typename SourceDerived >
179  SparseBlockIndex &move( const SparseBlockIndexBase< SourceDerived > &source )
180  {
181  return ( *this = source ) ;
182  }
183 
184  template < bool Symmetric, typename SourceDerived >
185  SparseBlockIndex& setToTranspose( const SparseBlockIndexBase< SourceDerived > &source )
186  {
187  clear() ;
188  resizeOuter( source.innerSize() ) ;
189  valid = source.valid ;
190 
191  for( typename SourceDerived::Index i = 0 ; i < source.outerSize() ; ++i )
192  {
193  // For a symmetric matrix, do not store diagonal block in col-major index
194  for( typename SourceDerived::InnerIterator it( source.derived(), i ) ;
195  it && ( !Symmetric || it.inner() < i ) ; ++ it )
196  {
197  insertBack( it.inner(), i, it.ptr() ) ;
198  }
199  }
200  finalize() ;
201 
202  return *this ;
203  }
204 
205  Index size( const Index outerIdx ) const
206  {
207  return outer[ outerIdx ].size() ;
208  }
209 
210  Index nonZeros() const
211  {
212  Index nnz = 0 ;
213  for( unsigned i = 0 ; i < outer.size() ; ++i )
214  nnz += outer[i].size() ;
215 
216  return nnz ;
217  }
218 
219  void changePtr( const InnerIterator& it, BlockPtr ptr )
220  {
221  const_cast< BlockPtr& >( it.asStdIterator()->second ) = ptr ;
222  }
223 
224 } ;
225 
226 template < bool Compressed, typename Index_, typename BlockPtr_, template <typename> class ArrayType >
227 struct SparseBlockIndexTraits< SparseBlockIndex< Compressed, Index_, BlockPtr_, ArrayType > >
228 {
229  typedef Index_ Index;
230  typedef BlockPtr_ BlockPtr;
231 
233 
235  struct InnerIterator
236  {
237  // Warning: This class does not implement the full RandomAccessIterator concept ;
238  // only the operations that are required by std::lower_bound are implemented
239  typedef std::random_access_iterator_tag iterator_category;
240  typedef Index value_type;
241  typedef std::ptrdiff_t difference_type;
242  typedef const Index* pointer;
243  typedef const Index& reference;
244 
245  InnerIterator() {}
246 
247  InnerIterator( const SparseBlockIndexType& index, Index outer )
248  : m_it( index.outer[ outer ].begin() ), m_end( index.outer[ outer ].end() )
249  {
250  }
251 
252  operator bool() const
253  {
254  return m_it != m_end ;
255  }
256 
257  InnerIterator& operator++()
258  {
259  ++ m_it ;
260  return *this ;
261  }
262  InnerIterator& operator--()
263  {
264  -- m_it ;
265  return *this ;
266  }
267 
268  InnerIterator& operator+= ( const std::size_t n )
269  {
270  m_it += n ;
271  return *this ;
272  }
273 
274  difference_type operator- ( const InnerIterator& other ) const
275  {
276  return m_it - other.m_it ;
277  }
278 
279  Index operator* () const
280  {
281  return inner() ;
282  }
283 
284  InnerIterator end() const
285  {
286  return InnerIterator( *this ).toEnd() ;
287  }
288 
289  InnerIterator& toEnd()
290  {
291  m_it = m_end ;
292  return *this ;
293  }
294 
295  bool after( Index outer ) const
296  {
297  return inner() > outer ;
298  }
299 
300  Index inner() const { return m_it->first ; }
301  BlockPtr ptr() const { return m_it->second ; }
302 
303 
304  typename SparseBlockIndexType::Inner::const_iterator asStdIterator() const { return m_it ; }
305  private:
306 
307  typename SparseBlockIndexType::Inner::const_iterator m_it ;
308  typename SparseBlockIndexType::Inner::const_iterator m_end ;
309  } ;
310 } ;
311 
312 
313 
314 }
315 
316 
317 #endif // SPARSEBLOCKINDEX_HPP
Definition: SparseBlockIndex.hpp:29
Uncompressed sparse block index.
Definition: SparseBlockIndex.hpp:86
Index size(const Index outerIdx) const
Returns the number of blocks at the outer index outerIdx.
const Index * innerOffsetsData() const
Same as innerOffsetsArray, but returns a pointer instead. Assumes hasInnerOffsets() ...
Definition: SparseBlockIndex.hpp:65
const InnerOffsetsType & innerOffsetsArray() const
ArrayType< Inner >::Type Outer
Vector of inner vectors.
Definition: SparseBlockIndex.hpp:100
InnerIterator end(const Index outerIdx) const
Returns an iterator to the end of outerIdx.
Definition: SparseBlockIndex.hpp:24
bool valid
Whether this index is currently valid.
Definition: SparseBlockIndex.hpp:40
InnerIterator last(const Index outerIdx) const
Returns an iterator to the last non-empty block of outerIdx.
Index nonZeros() const
Returns the total number of nonZeros in this index.
Definition: SparseBlockIndex.hpp:62
std::vector< Index > InnerOffsetsType
Type of the array encoding the size of each block of the inner dimension.
Definition: SparseBlockIndex.hpp:37
Index outerSize() const
Number of elemnts of the major indexing direction.
bool hasInnerOffsets() const
Returns whether the innerOffsetsArray() has been filled.
Index innerSize() const
Number of elements of the minor indexing direction.
InnerIterator begin(const Index outerIdx) const
Returns an iterator to the first non-empty block of outerIdx.
std::vector< std::pair< Index, BlockPtr > > Inner
Vector of ( inner index ; block pointer ) tuples encoding an inner vector.
Definition: SparseBlockIndex.hpp:98