So-Bogus
A c++ sparse block matrix library aimed at Second Order cone problems
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
CompressedSparseBlockIndex.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 COMPRESSED_SPARSE_BLOCK_INDEX_HPP
13 #define COMPRESSED_SPARSE_BLOCK_INDEX_HPP
14 
15 #include "SparseBlockIndex.hpp"
16 #include "../Utils/CppTools.hpp"
17 
18 namespace bogus
19 {
20 
22 template< typename Index_, typename BlockPtr_, template <typename> class ArrayType >
23 struct SparseBlockIndex< true, Index_, BlockPtr_, ArrayType > : public SparseBlockIndexBase< SparseBlockIndex< true, Index_, BlockPtr_, ArrayType > >
24 {
25  typedef Index_ Index ;
26  typedef BlockPtr_ BlockPtr ;
27 
29  typedef typename Base::InnerOffsetsType InnerOffsetsType ;
30  typedef typename Base::InnerIterator InnerIterator ;
31  using Base::valid ;
32 
33  typedef typename ArrayType< Index >::Type Inner ;
34  typedef typename ArrayType< Index >::Type Outer ;
35 
36  InnerOffsetsType innerOffsets ;
37 
39  Inner inner ;
41  Outer outer ;
42 
44  : Base()
45  {}
46 
47  void resizeOuter( Index size )
48  {
49  outer.assign( size+1, 0 ) ;
50  }
51  void reserve( Index nnz)
52  {
53  inner.reserve( nnz ) ;
54  }
55 
56  Index outerSize( ) const { return outer.size() - 1 ; }
57  Index nonZeros() const { return inner.size() ; }
58 
59 
60  const InnerOffsetsType& innerOffsetsArray() const { return innerOffsets ; }
61 
64  template < bool Ordered >
65  void insert( Index outIdx, Index inIdx, BlockPtr ptr )
66  {
67  BOGUS_STATIC_ASSERT( Ordered, UNORDERED_INSERTION_WITH_COMPRESSED_INDEX
68  ) ;
69 
70  valid &= ( ptr == (BlockPtr) ( inner.size() ) )
71  && ( 0 == outer[ outIdx+1 ] || inIdx > inner.back() ) ;
72  ++outer[ outIdx+1 ] ;
73  inner.push_back( inIdx ) ;
74  }
75  void insertBack( Index outIdx, Index inIdx, BlockPtr ptr )
76  { insert< true >( outIdx, inIdx, ptr ) ; }
77 
79 
85  void finalize()
86  {
87  for( unsigned i = 1 ; i < outer.size() ; ++i )
88  {
89  outer[i] += outer[i-1] ;
90  }
91  }
92 
93  void clear()
94  {
95  outer.assign( outer.size(), 0 ) ;
96  inner.clear() ;
97 
98  valid = true ;
99  }
100 
101  SparseBlockIndex &operator=( const SparseBlockIndex &compressed )
102  {
103  if( &compressed != this )
104  {
105  outer = compressed.outer ;
106  inner = compressed.inner ;
107  if( !compressed.innerOffsets.empty() )
108  innerOffsets = compressed.innerOffsets ;
109  valid = compressed.valid ;
110  }
111  return *this ;
112  }
113 
114  template < typename SourceDerived >
115  SparseBlockIndex &operator=( const SparseBlockIndexBase< SourceDerived > &source )
116  {
117  resizeOuter( source.outerSize() ) ;
118  reserve( source.nonZeros() ) ;
119 
120  inner.clear() ;
121  if( source.hasInnerOffsets() ) {
122  innerOffsets.resize( source.innerOffsetsArray().size() ) ;
123  std::copy( source.innerOffsetsArray().begin(), source.innerOffsetsArray().end(), innerOffsets.begin() ) ;
124  }
125  valid = source.valid ;
126 
127  for( typename SourceDerived::Index i = 0 ; i < source.outerSize() ; ++i )
128  {
129  for( typename SourceDerived::InnerIterator it( source.derived(), i ) ;
130  it ; ++ it )
131  {
132  insertBack( i, it.inner(), it.ptr() ) ;
133  }
134  }
135 
136  finalize() ;
137 
138  return *this ;
139  }
140 
141  SparseBlockIndex & move( SparseBlockIndex &compressed )
142  {
143  if( &compressed != this )
144  {
145  // Want to have fun with gcc 4.6.3 ? Just swap the following statements !
146  // Note: Swapping works perfectly with (at least) gcc 4.6.3 in non-optimized mode, gcc 4.8, gcc 4.2, clang 4.2
147  inner.swap( compressed.inner );
148  outer.swap( compressed.outer );
149 
150  if( !compressed.innerOffsets.empty() )
151  innerOffsets.swap( compressed.innerOffsets ) ;
152  valid = compressed.valid ;
153  compressed.valid = false ;
154 
155  }
156  return *this ;
157  }
158 
159  template < typename SourceDerived >
160  SparseBlockIndex &move( const SparseBlockIndexBase< SourceDerived > &source )
161  {
162  return ( *this = source ) ;
163  }
164 
165  Index size( const Index outerIdx ) const
166  {
167  return outer[ outerIdx + 1 ] - outer[ outerIdx ] ;
168  }
169 
170 
171  // MKL BSR
172  const Index* rowIndex() const { return data_pointer(outer) ; }
173  const Index* columns() const { return data_pointer(inner) ; }
174 
175  // Same with nicer names
176  const Index* outerIndexPtr() const { return data_pointer(outer) ; }
177  const Index* innerIndexPtr() const { return data_pointer(inner) ; }
178 
179 } ;
180 
181 template < typename Index_, typename BlockPtr_, template <typename> class ArrayType >
182 struct SparseBlockIndexTraits< SparseBlockIndex< true, Index_, BlockPtr_, ArrayType > >
183 {
184  typedef Index_ Index;
185  typedef BlockPtr_ BlockPtr;
186 
188 
190  struct InnerIterator
191  {
192  // Warning: This class does not implement the full RandomAccessIterator concept ;
193  // only the operations that are required by std::lower_bound are implemented
194  typedef std::random_access_iterator_tag iterator_category;
195  typedef Index value_type;
196  typedef ptrdiff_t difference_type;
197  typedef const Index* pointer;
198  typedef const Index& reference;
199 
200  InnerIterator( ) : m_inner( BOGUS_NULL_PTR(const Index) ) { }
201 
202  InnerIterator( const SparseBlockIndexType& index, Index outer )
203  : m_it( index.outer[ outer ] ), m_end( index.outer[ outer + 1] ),
204  m_inner( data_pointer( index.inner ) )
205  {
206  }
207 
208  operator bool() const
209  {
210  return m_it != m_end ;
211  }
212 
213  InnerIterator& operator++()
214  {
215  ++ m_it ;
216  return *this ;
217  }
218  InnerIterator& operator--()
219  {
220  -- m_it ;
221  return *this ;
222  }
223 
224  InnerIterator& operator+= ( const std::size_t n )
225  {
226  m_it = std::min( m_it + (Index) n, m_end ) ;
227  return *this ;
228  }
229 
230  difference_type operator- ( const InnerIterator& other ) const
231  {
232  return ( (difference_type) m_it ) - ( difference_type ) other.m_it ;
233  }
234 
235  Index operator* () const
236  {
237  return inner() ;
238  }
239 
240  InnerIterator end() const
241  {
242  return InnerIterator( *this ).toEnd() ;
243  }
244 
245  InnerIterator& toEnd()
246  {
247  m_it = m_end ;
248  return *this ;
249  }
250 
251  bool after( Index outer ) const
252  {
253  return inner() > outer ;
254  }
255 
256  Index inner() const { return m_inner[ m_it ] ; }
257  BlockPtr ptr() const { return m_it ; }
258 
259  BlockPtr rawIndex() const { return m_it ; }
260 
261  private:
262 
263  Index m_it ;
264  Index m_end ;
265  const Index* m_inner ;
266  } ;
267 } ;
268 
269 } //namespace bogus
270 
271 
272 #endif
Definition: SparseBlockIndex.hpp:29
Uncompressed sparse block index.
Definition: SparseBlockIndex.hpp:86
Outer outer
Vector encoding the start and end of inner vectors.
Definition: CompressedSparseBlockIndex.hpp:41
ArrayType< Inner >::Type Outer
Vector of inner vectors.
Definition: SparseBlockIndex.hpp:100
Definition: SparseBlockIndex.hpp:24
Compressed index, compatible with usual BSR/BSC formats.
Definition: CompressedSparseBlockIndex.hpp:23
bool valid
Whether this index is currently valid.
Definition: SparseBlockIndex.hpp:40
std::vector< Index > InnerOffsetsType
Type of the array encoding the size of each block of the inner dimension.
Definition: SparseBlockIndex.hpp:37
Inner inner
Vector of inner indices.
Definition: CompressedSparseBlockIndex.hpp:39
void finalize()
Finalizes the outer indices vector.
Definition: CompressedSparseBlockIndex.hpp:85
void insert(Index outIdx, Index inIdx, BlockPtr ptr)
Definition: CompressedSparseBlockIndex.hpp:65
std::vector< std::pair< Index, BlockPtr > > Inner
Vector of ( inner index ; block pointer ) tuples encoding an inner vector.
Definition: SparseBlockIndex.hpp:98