00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_RANDOMSETTER_H
00026 #define EIGEN_RANDOMSETTER_H
00027
00032 template<typename Scalar> struct StdMapTraits
00033 {
00034 typedef int KeyType;
00035 typedef std::map<KeyType,Scalar> Type;
00036 enum {
00037 IsSorted = 1
00038 };
00039
00040 static void setInvalidKey(Type&, const KeyType&) {}
00041 };
00042
00043 #ifdef EIGEN_UNORDERED_MAP_SUPPORT
00044
00060 template<typename Scalar> struct StdUnorderedMapTraits
00061 {
00062 typedef int KeyType;
00063 typedef std::unordered_map<KeyType,Scalar> Type;
00064 enum {
00065 IsSorted = 0
00066 };
00067
00068 static void setInvalidKey(Type&, const KeyType&) {}
00069 };
00070 #endif // EIGEN_UNORDERED_MAP_SUPPORT
00071
00072 #ifdef _DENSE_HASH_MAP_H_
00073
00077 template<typename Scalar> struct GoogleDenseHashMapTraits
00078 {
00079 typedef int KeyType;
00080 typedef google::dense_hash_map<KeyType,Scalar> Type;
00081 enum {
00082 IsSorted = 0
00083 };
00084
00085 static void setInvalidKey(Type& map, const KeyType& k)
00086 { map.set_empty_key(k); }
00087 };
00088 #endif
00089
00090 #ifdef _SPARSE_HASH_MAP_H_
00091
00095 template<typename Scalar> struct GoogleSparseHashMapTraits
00096 {
00097 typedef int KeyType;
00098 typedef google::sparse_hash_map<KeyType,Scalar> Type;
00099 enum {
00100 IsSorted = 0
00101 };
00102
00103 static void setInvalidKey(Type&, const KeyType&) {}
00104 };
00105 #endif
00106
00157 template<typename SparseMatrixType,
00158 template <typename T> class MapTraits =
00159 #if defined _DENSE_HASH_MAP_H_
00160 GoogleDenseHashMapTraits
00161 #elif defined _HASH_MAP
00162 GnuHashMapTraits
00163 #else
00164 StdMapTraits
00165 #endif
00166 ,int OuterPacketBits = 6>
00167 class RandomSetter
00168 {
00169 typedef typename ei_traits<SparseMatrixType>::Scalar Scalar;
00170 struct ScalarWrapper
00171 {
00172 ScalarWrapper() : value(0) {}
00173 Scalar value;
00174 };
00175 typedef typename MapTraits<ScalarWrapper>::KeyType KeyType;
00176 typedef typename MapTraits<ScalarWrapper>::Type HashMapType;
00177 static const int OuterPacketMask = (1 << OuterPacketBits) - 1;
00178 enum {
00179 SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
00180 TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
00181 SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor,
00182 IsUpperTriangular = SparseMatrixType::Flags & UpperTriangularBit,
00183 IsLowerTriangular = SparseMatrixType::Flags & LowerTriangularBit
00184 };
00185
00186 public:
00187
00194 inline RandomSetter(SparseMatrixType& target)
00195 : mp_target(&target)
00196 {
00197 const int outerSize = SwapStorage ? target.innerSize() : target.outerSize();
00198 const int innerSize = SwapStorage ? target.outerSize() : target.innerSize();
00199 m_outerPackets = outerSize >> OuterPacketBits;
00200 if (outerSize&OuterPacketMask)
00201 m_outerPackets += 1;
00202 m_hashmaps = new HashMapType[m_outerPackets];
00203
00204 int aux = innerSize - 1;
00205 m_keyBitsOffset = 0;
00206 while (aux)
00207 {
00208 ++m_keyBitsOffset;
00209 aux = aux >> 1;
00210 }
00211 KeyType ik = (1<<(OuterPacketBits+m_keyBitsOffset));
00212 for (int k=0; k<m_outerPackets; ++k)
00213 MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k],ik);
00214
00215
00216 for (int j=0; j<mp_target->outerSize(); ++j)
00217 for (typename SparseMatrixType::InnerIterator it(*mp_target,j); it; ++it)
00218 (*this)(TargetRowMajor?j:it.index(), TargetRowMajor?it.index():j) = it.value();
00219 }
00220
00222 ~RandomSetter()
00223 {
00224 KeyType keyBitsMask = (1<<m_keyBitsOffset)-1;
00225 if (!SwapStorage)
00226 {
00227 mp_target->startFill(nonZeros());
00228 for (int k=0; k<m_outerPackets; ++k)
00229 {
00230 const int outerOffset = (1<<OuterPacketBits) * k;
00231 typename HashMapType::iterator end = m_hashmaps[k].end();
00232 for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
00233 {
00234 const int outer = (it->first >> m_keyBitsOffset) + outerOffset;
00235 const int inner = it->first & keyBitsMask;
00236 mp_target->fill(TargetRowMajor ? outer : inner, TargetRowMajor ? inner : outer) = it->second.value;
00237 }
00238 }
00239 mp_target->endFill();
00240 }
00241 else
00242 {
00243 VectorXi positions(mp_target->outerSize());
00244 positions.setZero();
00245
00246 for (int k=0; k<m_outerPackets; ++k)
00247 {
00248 typename HashMapType::iterator end = m_hashmaps[k].end();
00249 for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
00250 {
00251 const int outer = it->first & keyBitsMask;
00252 ++positions[outer];
00253 }
00254 }
00255
00256 int count = 0;
00257 for (int j=0; j<mp_target->outerSize(); ++j)
00258 {
00259 int tmp = positions[j];
00260 mp_target->_outerIndexPtr()[j] = count;
00261 positions[j] = count;
00262 count += tmp;
00263 }
00264 mp_target->_outerIndexPtr()[mp_target->outerSize()] = count;
00265 mp_target->resizeNonZeros(count);
00266
00267 for (int k=0; k<m_outerPackets; ++k)
00268 {
00269 const int outerOffset = (1<<OuterPacketBits) * k;
00270 typename HashMapType::iterator end = m_hashmaps[k].end();
00271 for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
00272 {
00273 const int inner = (it->first >> m_keyBitsOffset) + outerOffset;
00274 const int outer = it->first & keyBitsMask;
00275
00276
00277
00278
00279 int posStart = mp_target->_outerIndexPtr()[outer];
00280 int i = (positions[outer]++) - 1;
00281 while ( (i >= posStart) && (mp_target->_innerIndexPtr()[i] > inner) )
00282 {
00283 mp_target->_valuePtr()[i+1] = mp_target->_valuePtr()[i];
00284 mp_target->_innerIndexPtr()[i+1] = mp_target->_innerIndexPtr()[i];
00285 --i;
00286 }
00287 mp_target->_innerIndexPtr()[i+1] = inner;
00288 mp_target->_valuePtr()[i+1] = it->second.value;
00289 }
00290 }
00291 }
00292 delete[] m_hashmaps;
00293 }
00294
00296 Scalar& operator() (int row, int col)
00297 {
00298 ei_assert(((!IsUpperTriangular) || (row<=col)) && "Invalid access to an upper triangular matrix");
00299 ei_assert(((!IsLowerTriangular) || (col<=row)) && "Invalid access to an upper triangular matrix");
00300 const int outer = SetterRowMajor ? row : col;
00301 const int inner = SetterRowMajor ? col : row;
00302 const int outerMajor = outer >> OuterPacketBits;
00303 const int outerMinor = outer & OuterPacketMask;
00304 const KeyType key = (KeyType(outerMinor)<<m_keyBitsOffset) | inner;
00305 return m_hashmaps[outerMajor][key].value;
00306 }
00307
00313 int nonZeros() const
00314 {
00315 int nz = 0;
00316 for (int k=0; k<m_outerPackets; ++k)
00317 nz += m_hashmaps[k].size();
00318 return nz;
00319 }
00320
00321
00322 protected:
00323
00324 HashMapType* m_hashmaps;
00325 SparseMatrixType* mp_target;
00326 int m_outerPackets;
00327 unsigned char m_keyBitsOffset;
00328 };
00329
00330 #endif // EIGEN_RANDOMSETTER_H