Eigen-unsupported  5.0.1-dev+284dcc12
 
Loading...
Searching...
No Matches
RandomSetter.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008 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_RANDOMSETTER_H
11#define EIGEN_RANDOMSETTER_H
12
13#if defined(EIGEN_GOOGLEHASH_SUPPORT)
14// Ensure the ::google namespace exists, required for checking existence of
15// ::google::dense_hash_map and ::google::sparse_hash_map.
16namespace google {}
17#endif
18
19// IWYU pragma: private
20#include "./InternalHeaderCheck.h"
21
22namespace Eigen {
23
28template <typename Scalar>
30 typedef int KeyType;
31 typedef std::map<KeyType, Scalar> Type;
32 enum { IsSorted = 1 };
33
34 static void setInvalidKey(Type&, const KeyType&) {}
35};
36
40template <typename Scalar>
42 typedef int KeyType;
43 typedef std::unordered_map<KeyType, Scalar> Type;
44 enum { IsSorted = 0 };
45
46 static void setInvalidKey(Type&, const KeyType&) {}
47};
48
49#if defined(EIGEN_GOOGLEHASH_SUPPORT)
50
51namespace google {
52
53// Namespace work-around, since sometimes dense_hash_map and sparse_hash_map
54// are in the global namespace, and other times they are under ::google.
55using namespace ::google;
56
57template <typename KeyType, typename Scalar>
58struct DenseHashMap {
59 typedef dense_hash_map<KeyType, Scalar> type;
60};
61
62template <typename KeyType, typename Scalar>
63struct SparseHashMap {
64 typedef sparse_hash_map<KeyType, Scalar> type;
65};
66
67} // namespace google
68
73template <typename Scalar>
74struct GoogleDenseHashMapTraits {
75 typedef int KeyType;
76 typedef typename google::DenseHashMap<KeyType, Scalar>::type Type;
77 enum { IsSorted = 0 };
78
79 static void setInvalidKey(Type& map, const KeyType& k) { map.set_empty_key(k); }
80};
81
86template <typename Scalar>
87struct GoogleSparseHashMapTraits {
88 typedef int KeyType;
89 typedef typename google::SparseHashMap<KeyType, Scalar>::type Type;
90 enum { IsSorted = 0 };
91
92 static void setInvalidKey(Type&, const KeyType&) {}
93};
94#endif
95
147template <typename SparseMatrixType,
148 template <typename T> class MapTraits =
149#if defined(EIGEN_GOOGLEHASH_SUPPORT)
150 GoogleDenseHashMapTraits
151#else
153#endif
154 ,
155 int OuterPacketBits = 6>
157 typedef typename SparseMatrixType::Scalar Scalar;
158 typedef typename SparseMatrixType::StorageIndex StorageIndex;
159
160 struct ScalarWrapper {
161 ScalarWrapper() : value(0) {}
162 Scalar value;
163 };
164 typedef typename MapTraits<ScalarWrapper>::KeyType KeyType;
165 typedef typename MapTraits<ScalarWrapper>::Type HashMapType;
166 static constexpr int OuterPacketMask = (1 << OuterPacketBits) - 1;
167 enum {
168 SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
169 TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
170 SetterRowMajor = SwapStorage ? 1 - TargetRowMajor : TargetRowMajor
171 };
172
173 public:
180 inline RandomSetter(SparseMatrixType& target) : mp_target(&target) {
181 const Index outerSize = SwapStorage ? target.innerSize() : target.outerSize();
182 const Index innerSize = SwapStorage ? target.outerSize() : target.innerSize();
183 m_outerPackets = outerSize >> OuterPacketBits;
184 if (outerSize & OuterPacketMask) m_outerPackets += 1;
185 m_hashmaps = new HashMapType[m_outerPackets];
186 // compute number of bits needed to store inner indices
187 Index aux = innerSize - 1;
188 m_keyBitsOffset = 0;
189 while (aux) {
190 ++m_keyBitsOffset;
191 aux = aux >> 1;
192 }
193 KeyType ik = (1 << (OuterPacketBits + m_keyBitsOffset));
194 for (Index k = 0; k < m_outerPackets; ++k) MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k], ik);
195
196 // insert current coeffs
197 for (Index j = 0; j < mp_target->outerSize(); ++j)
198 for (typename SparseMatrixType::InnerIterator it(*mp_target, j); it; ++it)
199 (*this)(TargetRowMajor ? j : it.index(), TargetRowMajor ? it.index() : j) = it.value();
200 }
201
204 KeyType keyBitsMask = (1 << m_keyBitsOffset) - 1;
205 if (!SwapStorage) // also means the map is sorted
206 {
207 mp_target->setZero();
208 mp_target->makeCompressed();
209 mp_target->reserve(nonZeros());
210 Index prevOuter = -1;
211 for (Index k = 0; k < m_outerPackets; ++k) {
212 const Index outerOffset = (1 << OuterPacketBits) * k;
213 typename HashMapType::iterator end = m_hashmaps[k].end();
214 for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
215 const Index outer = (it->first >> m_keyBitsOffset) + outerOffset;
216 const Index inner = it->first & keyBitsMask;
217 if (prevOuter != outer) {
218 for (Index j = prevOuter + 1; j <= outer; ++j) mp_target->startVec(j);
219 prevOuter = outer;
220 }
221 mp_target->insertBackByOuterInner(outer, inner) = it->second.value;
222 }
223 }
224 mp_target->finalize();
225 } else {
226 VectorXi positions(mp_target->outerSize());
227 positions.setZero();
228 // pass 1
229 for (Index k = 0; k < m_outerPackets; ++k) {
230 typename HashMapType::iterator end = m_hashmaps[k].end();
231 for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
232 const Index outer = it->first & keyBitsMask;
233 ++positions[outer];
234 }
235 }
236 // prefix sum
237 StorageIndex count = 0;
238 for (Index j = 0; j < mp_target->outerSize(); ++j) {
239 StorageIndex tmp = positions[j];
240 mp_target->outerIndexPtr()[j] = count;
241 positions[j] = count;
242 count += tmp;
243 }
244 mp_target->makeCompressed();
245 mp_target->outerIndexPtr()[mp_target->outerSize()] = count;
246 mp_target->resizeNonZeros(count);
247 // pass 2
248 for (Index k = 0; k < m_outerPackets; ++k) {
249 const Index outerOffset = (1 << OuterPacketBits) * k;
250 typename HashMapType::iterator end = m_hashmaps[k].end();
251 for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
252 const Index inner = (it->first >> m_keyBitsOffset) + outerOffset;
253 const Index outer = it->first & keyBitsMask;
254 // sorted insertion
255 // Note that we have to deal with at most 2^OuterPacketBits unsorted coefficients,
256 // moreover those 2^OuterPacketBits coeffs are likely to be sparse, an so only a
257 // small fraction of them have to be sorted, whence the following simple procedure:
258 Index posStart = mp_target->outerIndexPtr()[outer];
259 Index i = (positions[outer]++) - 1;
260 while ((i >= posStart) && (mp_target->innerIndexPtr()[i] > inner)) {
261 mp_target->valuePtr()[i + 1] = mp_target->valuePtr()[i];
262 mp_target->innerIndexPtr()[i + 1] = mp_target->innerIndexPtr()[i];
263 --i;
264 }
265 mp_target->innerIndexPtr()[i + 1] = internal::convert_index<StorageIndex>(inner);
266 mp_target->valuePtr()[i + 1] = it->second.value;
267 }
268 }
269 }
270 delete[] m_hashmaps;
271 }
272
274 Scalar& operator()(Index row, Index col) {
275 const Index outer = SetterRowMajor ? row : col;
276 const Index inner = SetterRowMajor ? col : row;
277 const Index outerMajor = outer >> OuterPacketBits; // index of the packet/map
278 const Index outerMinor = outer & OuterPacketMask; // index of the inner vector in the packet
279 const KeyType key = internal::convert_index<KeyType>((outerMinor << m_keyBitsOffset) | inner);
280 return m_hashmaps[outerMajor][key].value;
281 }
282
288 Index nonZeros() const {
289 Index nz = 0;
290 for (Index k = 0; k < m_outerPackets; ++k) nz += static_cast<Index>(m_hashmaps[k].size());
291 return nz;
292 }
293
294 protected:
295 HashMapType* m_hashmaps;
296 SparseMatrixType* mp_target;
297 Index m_outerPackets;
298 unsigned char m_keyBitsOffset;
299};
300
301} // end namespace Eigen
302
303#endif // EIGEN_RANDOMSETTER_H
Derived & setZero(Index rows, Index cols)
~RandomSetter()
Definition RandomSetter.h:203
RandomSetter(SparseMatrixType &target)
Definition RandomSetter.h:180
Scalar & operator()(Index row, Index col)
Definition RandomSetter.h:274
Index nonZeros() const
Definition RandomSetter.h:288
const unsigned int RowMajorBit
Matrix< int, Dynamic, 1 > VectorXi
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
Definition RandomSetter.h:29
Definition RandomSetter.h:41