Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits > Class Template Reference

The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access. More...

Classes

struct  ScalarWrapper
 

Public Member Functions

Index nonZeros () const
 
Scalaroperator() (Index row, Index col)
 
 RandomSetter (SparseMatrixType &target)
 
 ~RandomSetter ()
 

Protected Attributes

HashMapTypem_hashmaps
 
unsigned char m_keyBitsOffset
 
Index m_outerPackets
 
SparseMatrixType * mp_target
 

Private Types

enum  {
  SwapStorage ,
  TargetRowMajor ,
  SetterRowMajor
}
 
typedef MapTraits< ScalarWrapper >::Type HashMapType
 
typedef MapTraits< ScalarWrapper >::KeyType KeyType
 
typedef SparseMatrixType::Scalar Scalar
 
typedef SparseMatrixType::StorageIndex StorageIndex
 

Static Private Attributes

static constexpr int OuterPacketMask
 

Detailed Description

template<typename SparseMatrixType, template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
class Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >

The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access.

Template Parameters
SparseMatrixTypethe type of the sparse matrix we are updating
MapTraitsa traits class representing the map implementation used for the temporary sparse storage. Its default value depends on the system.
OuterPacketBitsdefines the number of rows (or columns) manage by a single map object as a power of two exponent.

This class temporarily represents a sparse matrix object using a generic map implementation allowing for efficient random access. The conversion from the compressed representation to a hash_map object is performed in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy suggest the use of nested blocks as in this example:

{
RandomSetter<SparseMatrix<double> > w(m);
// don't use m but w instead with read/write random access to the coefficients:
for(;;)
w(rand(),rand()) = rand;
}
// when w is deleted, the data are copied back to m
// and m is ready to use.
Matrix3f m
RowVector3d w

Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order. To reach optimal performance, this value should be adjusted according to the average number of nonzeros per rows/columns.

The possible values for the template parameter MapTraits are:

  • StdMapTraits: corresponds to std::map. (does not perform very well)
  • StdUnorderedMapTraits: corresponds to std::unordered_map
  • GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory consumption)
  • GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good performance)

The default map implementation depends on the availability, and the preferred order is: GoogleSparseHashMapTraits, StdUnorderedMapTraits, and finally StdMapTraits.

For performance and memory consumption reasons it is highly recommended to use one of Google's hash_map implementations. To enable the support for them, you must define EIGEN_GOOGLEHASH_SUPPORT. This will include both <google/dense_hash_map> and <google/sparse_hash_map> for you.

See also
https://github.com/sparsehash/sparsehash

Definition at line 162 of file RandomSetter.h.

Member Typedef Documentation

◆ HashMapType

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
typedef MapTraits<ScalarWrapper>::Type Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::HashMapType
private

Definition at line 173 of file RandomSetter.h.

◆ KeyType

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
typedef MapTraits<ScalarWrapper>::KeyType Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::KeyType
private

Definition at line 172 of file RandomSetter.h.

◆ Scalar

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
typedef SparseMatrixType::Scalar Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::Scalar
private

Definition at line 164 of file RandomSetter.h.

◆ StorageIndex

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
typedef SparseMatrixType::StorageIndex Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::StorageIndex
private

Definition at line 165 of file RandomSetter.h.

Member Enumeration Documentation

◆ anonymous enum

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
anonymous enum
private
Enumerator
SwapStorage 
TargetRowMajor 
SetterRowMajor 

Definition at line 175 of file RandomSetter.h.

175  {
176  SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
177  TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
179  };
const unsigned int RowMajorBit

Constructor & Destructor Documentation

◆ RandomSetter()

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::RandomSetter ( SparseMatrixType &  target)
inline

Constructs a random setter object from the sparse matrix target

Note that the initial value of target are imported. If you want to re-set a sparse matrix from scratch, then you must set it to zero first using the setZero() function.

Definition at line 189 of file RandomSetter.h.

190  : mp_target(&target)
191  {
192  const Index outerSize = SwapStorage ? target.innerSize() : target.outerSize();
193  const Index innerSize = SwapStorage ? target.outerSize() : target.innerSize();
194  m_outerPackets = outerSize >> OuterPacketBits;
195  if (outerSize&OuterPacketMask)
196  m_outerPackets += 1;
198  // compute number of bits needed to store inner indices
199  Index aux = innerSize - 1;
200  m_keyBitsOffset = 0;
201  while (aux)
202  {
203  ++m_keyBitsOffset;
204  aux = aux >> 1;
205  }
206  KeyType ik = (1<<(OuterPacketBits+m_keyBitsOffset));
207  for (Index k=0; k<m_outerPackets; ++k)
208  MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k],ik);
209 
210  // insert current coeffs
211  for (Index j=0; j<mp_target->outerSize(); ++j)
212  for (typename SparseMatrixType::InnerIterator it(*mp_target,j); it; ++it)
213  (*this)(TargetRowMajor?j:it.index(), TargetRowMajor?it.index():j) = it.value();
214  }
MapTraits< ScalarWrapper >::KeyType KeyType
Definition: RandomSetter.h:172
unsigned char m_keyBitsOffset
Definition: RandomSetter.h:330
MapTraits< ScalarWrapper >::Type HashMapType
Definition: RandomSetter.h:173
HashMapType * m_hashmaps
Definition: RandomSetter.h:327
static constexpr int OuterPacketMask
Definition: RandomSetter.h:174
SparseMatrixType * mp_target
Definition: RandomSetter.h:328
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
std::ptrdiff_t j

◆ ~RandomSetter()

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::~RandomSetter ( )
inline

Destructor updating back the sparse matrix target

Definition at line 217 of file RandomSetter.h.

218  {
219  KeyType keyBitsMask = (1<<m_keyBitsOffset)-1;
220  if (!SwapStorage) // also means the map is sorted
221  {
222  mp_target->setZero();
223  mp_target->makeCompressed();
224  mp_target->reserve(nonZeros());
225  Index prevOuter = -1;
226  for (Index k=0; k<m_outerPackets; ++k)
227  {
228  const Index outerOffset = (1<<OuterPacketBits) * k;
229  typename HashMapType::iterator end = m_hashmaps[k].end();
230  for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
231  {
232  const Index outer = (it->first >> m_keyBitsOffset) + outerOffset;
233  const Index inner = it->first & keyBitsMask;
234  if (prevOuter!=outer)
235  {
236  for (Index j=prevOuter+1;j<=outer;++j)
237  mp_target->startVec(j);
238  prevOuter = outer;
239  }
240  mp_target->insertBackByOuterInner(outer, inner) = it->second.value;
241  }
242  }
243  mp_target->finalize();
244  }
245  else
246  {
247  VectorXi positions(mp_target->outerSize());
248  positions.setZero();
249  // pass 1
250  for (Index k=0; k<m_outerPackets; ++k)
251  {
252  typename HashMapType::iterator end = m_hashmaps[k].end();
253  for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
254  {
255  const Index outer = it->first & keyBitsMask;
256  ++positions[outer];
257  }
258  }
259  // prefix sum
260  StorageIndex count = 0;
261  for (Index j=0; j<mp_target->outerSize(); ++j)
262  {
263  StorageIndex tmp = positions[j];
264  mp_target->outerIndexPtr()[j] = count;
265  positions[j] = count;
266  count += tmp;
267  }
268  mp_target->makeCompressed();
269  mp_target->outerIndexPtr()[mp_target->outerSize()] = count;
270  mp_target->resizeNonZeros(count);
271  // pass 2
272  for (Index k=0; k<m_outerPackets; ++k)
273  {
274  const Index outerOffset = (1<<OuterPacketBits) * k;
275  typename HashMapType::iterator end = m_hashmaps[k].end();
276  for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
277  {
278  const Index inner = (it->first >> m_keyBitsOffset) + outerOffset;
279  const Index outer = it->first & keyBitsMask;
280  // sorted insertion
281  // Note that we have to deal with at most 2^OuterPacketBits unsorted coefficients,
282  // moreover those 2^OuterPacketBits coeffs are likely to be sparse, an so only a
283  // small fraction of them have to be sorted, whence the following simple procedure:
284  Index posStart = mp_target->outerIndexPtr()[outer];
285  Index i = (positions[outer]++) - 1;
286  while ( (i >= posStart) && (mp_target->innerIndexPtr()[i] > inner) )
287  {
288  mp_target->valuePtr()[i+1] = mp_target->valuePtr()[i];
289  mp_target->innerIndexPtr()[i+1] = mp_target->innerIndexPtr()[i];
290  --i;
291  }
292  mp_target->innerIndexPtr()[i+1] = internal::convert_index<StorageIndex>(inner);
293  mp_target->valuePtr()[i+1] = it->second.value;
294  }
295  }
296  }
297  delete[] m_hashmaps;
298  }
int i
SparseMatrixType::StorageIndex StorageIndex
Definition: RandomSetter.h:165
Index nonZeros() const
Definition: RandomSetter.h:316
static const lastp1_t end
Matrix< int, Dynamic, 1 > VectorXi

Member Function Documentation

◆ nonZeros()

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
Index Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::nonZeros ( ) const
inline
Returns
the number of non zero coefficients
Note
According to the underlying map/hash_map implementation, this function might be quite expensive.

Definition at line 316 of file RandomSetter.h.

317  {
318  Index nz = 0;
319  for (Index k=0; k<m_outerPackets; ++k)
320  nz += static_cast<Index>(m_hashmaps[k].size());
321  return nz;
322  }
SparseMat::Index size

◆ operator()()

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
Scalar& Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::operator() ( Index  row,
Index  col 
)
inline
Returns
a reference to the coefficient at given coordinates row, col

Definition at line 301 of file RandomSetter.h.

302  {
303  const Index outer = SetterRowMajor ? row : col;
304  const Index inner = SetterRowMajor ? col : row;
305  const Index outerMajor = outer >> OuterPacketBits; // index of the packet/map
306  const Index outerMinor = outer & OuterPacketMask; // index of the inner vector in the packet
307  const KeyType key = internal::convert_index<KeyType>((outerMinor<<m_keyBitsOffset) | inner);
308  return m_hashmaps[outerMajor][key].value;
309  }
RowXpr row(Index i) const
ColXpr col(Index i) const

Member Data Documentation

◆ m_hashmaps

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
HashMapType* Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::m_hashmaps
protected

Definition at line 327 of file RandomSetter.h.

◆ m_keyBitsOffset

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
unsigned char Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::m_keyBitsOffset
protected

Definition at line 330 of file RandomSetter.h.

◆ m_outerPackets

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
Index Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::m_outerPackets
protected

Definition at line 329 of file RandomSetter.h.

◆ mp_target

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
SparseMatrixType* Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::mp_target
protected

Definition at line 328 of file RandomSetter.h.

◆ OuterPacketMask

template<typename SparseMatrixType , template< typename T > class MapTraits = StdUnorderedMapTraits, int OuterPacketBits = 6>
constexpr int Eigen::RandomSetter< SparseMatrixType, MapTraits, OuterPacketBits >::OuterPacketMask
staticconstexprprivate

Definition at line 174 of file RandomSetter.h.


The documentation for this class was generated from the following file: