Eigen-Contrib  5.0.1
 
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_RANDOMSETTER_H
12#define EIGEN_RANDOMSETTER_H
13
14#if defined(EIGEN_GOOGLEHASH_SUPPORT)
15// Ensure the ::google namespace exists, required for checking existence of
16// ::google::dense_hash_map and ::google::sparse_hash_map.
17namespace google {}
18#endif
19
20// IWYU pragma: private
21#include "./InternalHeaderCheck.h"
22
23namespace Eigen {
24
29template <typename Scalar>
31 typedef int KeyType;
32 typedef std::map<KeyType, Scalar> Type;
33 enum { IsSorted = 1 };
34
35 static void setInvalidKey(Type&, const KeyType&) {}
36};
37
41template <typename Scalar>
43 typedef int KeyType;
44 typedef std::unordered_map<KeyType, Scalar> Type;
45 enum { IsSorted = 0 };
46
47 static void setInvalidKey(Type&, const KeyType&) {}
48};
49
50#if defined(EIGEN_GOOGLEHASH_SUPPORT)
51
52namespace google {
53
54// Namespace work-around, since sometimes dense_hash_map and sparse_hash_map
55// are in the global namespace, and other times they are under ::google.
56using namespace ::google;
57
58template <typename KeyType, typename Scalar>
59struct DenseHashMap {
60 typedef dense_hash_map<KeyType, Scalar> type;
61};
62
63template <typename KeyType, typename Scalar>
64struct SparseHashMap {
65 typedef sparse_hash_map<KeyType, Scalar> type;
66};
67
68} // namespace google
69
74template <typename Scalar>
75struct GoogleDenseHashMapTraits {
76 typedef int KeyType;
77 typedef typename google::DenseHashMap<KeyType, Scalar>::type Type;
78 enum { IsSorted = 0 };
79
80 static void setInvalidKey(Type& map, const KeyType& k) { map.set_empty_key(k); }
81};
82
87template <typename Scalar>
88struct GoogleSparseHashMapTraits {
89 typedef int KeyType;
90 typedef typename google::SparseHashMap<KeyType, Scalar>::type Type;
91 enum { IsSorted = 0 };
92
93 static void setInvalidKey(Type&, const KeyType&) {}
94};
95#endif
96
148template <typename SparseMatrixType,
149 template <typename T> class MapTraits =
150#if defined(EIGEN_GOOGLEHASH_SUPPORT)
151 GoogleDenseHashMapTraits
152#else
154#endif
155 ,
156 int OuterPacketBits = 6>
158 typedef typename SparseMatrixType::Scalar Scalar;
159 typedef typename SparseMatrixType::StorageIndex StorageIndex;
160
161 struct ScalarWrapper {
162 Scalar value = Scalar(0);
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) : m_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 < m_target->outerSize(); ++j)
198 for (typename SparseMatrixType::InnerIterator it(*m_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 m_target->setZero();
208 m_target->makeCompressed();
209 m_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) m_target->startVec(j);
219 prevOuter = outer;
220 }
221 m_target->insertBackByOuterInner(outer, inner) = it->second.value;
222 }
223 }
224 m_target->finalize();
225 } else {
226 VectorXi positions(m_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 < m_target->outerSize(); ++j) {
239 StorageIndex tmp = positions[j];
240 m_target->outerIndexPtr()[j] = count;
241 positions[j] = count;
242 count += tmp;
243 }
244 m_target->makeCompressed();
245 m_target->outerIndexPtr()[m_target->outerSize()] = count;
246 m_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, and so only a
257 // small fraction of them have to be sorted, whence the following simple procedure:
258 Index posStart = m_target->outerIndexPtr()[outer];
259 Index i = (positions[outer]++) - 1;
260 while ((i >= posStart) && (m_target->innerIndexPtr()[i] > inner)) {
261 m_target->valuePtr()[i + 1] = m_target->valuePtr()[i];
262 m_target->innerIndexPtr()[i + 1] = m_target->innerIndexPtr()[i];
263 --i;
264 }
265 m_target->innerIndexPtr()[i + 1] = internal::convert_index<StorageIndex>(inner);
266 m_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
283#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
285 Scalar& operator[](Index row, Index col) { return operator()(row, col); }
286#endif
287
293 Index nonZeros() const {
294 Index nz = 0;
295 for (Index k = 0; k < m_outerPackets; ++k) nz += static_cast<Index>(m_hashmaps[k].size());
296 return nz;
297 }
298
299 protected:
300 HashMapType* m_hashmaps;
301 SparseMatrixType* m_target;
302 Index m_outerPackets;
303 unsigned char m_keyBitsOffset;
304};
305
306} // end namespace Eigen
307
308#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:293
constexpr unsigned int RowMajorBit
Matrix< int, Dynamic, 1 > VectorXi
Namespace containing all symbols from the Eigen library.
Definition RandomSetter.h:30
Definition RandomSetter.h:42