1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2015 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_SPARSE_REF_H 11 #define EIGEN_SPARSE_REF_H 12 13 namespace Eigen { 14 15 enum { 16 StandardCompressedFormat = 2 /**< used by Ref<SparseMatrix> to specify whether the input storage must be in standard compressed form */ 17 }; 18 19 namespace internal { 20 21 template<typename Derived> class SparseRefBase; 22 23 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> 24 struct traits<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > 25 : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> > 26 { 27 typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType; 28 enum { 29 Options = _Options, 30 Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit 31 }; 32 33 template<typename Derived> struct match { 34 enum { 35 StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), 36 MatchAtCompileTime = (Derived::Flags&CompressedAccessBit) && StorageOrderMatch 37 }; 38 typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; 39 }; 40 41 }; 42 43 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> 44 struct traits<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > 45 : public traits<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > 46 { 47 enum { 48 Flags = (traits<SparseMatrix<MatScalar,MatOptions,MatIndex> >::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit 49 }; 50 }; 51 52 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> 53 struct traits<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > 54 : public traits<SparseVector<MatScalar,MatOptions,MatIndex> > 55 { 56 typedef SparseVector<MatScalar,MatOptions,MatIndex> PlainObjectType; 57 enum { 58 Options = _Options, 59 Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit 60 }; 61 62 template<typename Derived> struct match { 63 enum { 64 MatchAtCompileTime = (Derived::Flags&CompressedAccessBit) && Derived::IsVectorAtCompileTime 65 }; 66 typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; 67 }; 68 69 }; 70 71 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> 72 struct traits<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > 73 : public traits<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > 74 { 75 enum { 76 Flags = (traits<SparseVector<MatScalar,MatOptions,MatIndex> >::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit 77 }; 78 }; 79 80 template<typename Derived> 81 struct traits<SparseRefBase<Derived> > : public traits<Derived> {}; 82 83 template<typename Derived> class SparseRefBase 84 : public SparseMapBase<Derived> 85 { 86 public: 87 88 typedef SparseMapBase<Derived> Base; 89 EIGEN_SPARSE_PUBLIC_INTERFACE(SparseRefBase) 90 91 SparseRefBase() 92 : Base(RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime, 0, 0, 0, 0, 0) 93 {} 94 95 protected: 96 97 template<typename Expression> 98 void construct(Expression& expr) 99 { 100 if(expr.outerIndexPtr()==0) 101 ::new (static_cast<Base*>(this)) Base(expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr()); 102 else 103 ::new (static_cast<Base*>(this)) Base(expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(), expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr()); 104 } 105 }; 106 107 } // namespace internal 108 109 110 /** 111 * \ingroup SparseCore_Module 112 * 113 * \brief A sparse matrix expression referencing an existing sparse expression 114 * 115 * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of class SparseMatrix. 116 * \tparam Options specifies whether the a standard compressed format is required \c Options is \c #StandardCompressedFormat, or \c 0. 117 * The default is \c 0. 118 * 119 * \sa class Ref 120 */ 121 #ifndef EIGEN_PARSED_BY_DOXYGEN 122 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 123 class Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType > 124 : public internal::SparseRefBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType > > 125 #else 126 template<typename SparseMatrixType, int Options> 127 class Ref<SparseMatrixType, Options> 128 : public SparseMapBase<Derived,WriteAccessors> // yes, that's weird to use Derived here, but that works! 129 #endif 130 { 131 typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType; 132 typedef internal::traits<Ref> Traits; 133 template<int OtherOptions> 134 inline Ref(const SparseMatrix<MatScalar,OtherOptions,MatIndex>& expr); 135 template<int OtherOptions> 136 inline Ref(const MappedSparseMatrix<MatScalar,OtherOptions,MatIndex>& expr); 137 public: 138 139 typedef internal::SparseRefBase<Ref> Base; 140 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) 141 142 143 #ifndef EIGEN_PARSED_BY_DOXYGEN 144 template<int OtherOptions> 145 inline Ref(SparseMatrix<MatScalar,OtherOptions,MatIndex>& expr) 146 { 147 EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseMatrix<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 148 eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); 149 Base::construct(expr.derived()); 150 } 151 152 template<int OtherOptions> 153 inline Ref(MappedSparseMatrix<MatScalar,OtherOptions,MatIndex>& expr) 154 { 155 EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseMatrix<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 156 eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); 157 Base::construct(expr.derived()); 158 } 159 160 template<typename Derived> 161 inline Ref(const SparseCompressedBase<Derived>& expr) 162 #else 163 /** Implicit constructor from any sparse expression (2D matrix or 1D vector) */ 164 template<typename Derived> 165 inline Ref(SparseCompressedBase<Derived>& expr) 166 #endif 167 { 168 EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); 169 EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 170 eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); 171 Base::construct(expr.const_cast_derived()); 172 } 173 }; 174 175 // this is the const ref version 176 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 177 class Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> 178 : public internal::SparseRefBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > 179 { 180 typedef SparseMatrix<MatScalar,MatOptions,MatIndex> TPlainObjectType; 181 typedef internal::traits<Ref> Traits; 182 public: 183 184 typedef internal::SparseRefBase<Ref> Base; 185 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) 186 187 template<typename Derived> 188 inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) 189 { 190 construct(expr.derived(), typename Traits::template match<Derived>::type()); 191 } 192 193 inline Ref(const Ref& other) : Base(other), m_hasCopy(false) { 194 // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy 195 } 196 197 template<typename OtherRef> 198 inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) { 199 construct(other.derived(), typename Traits::template match<OtherRef>::type()); 200 } 201 202 ~Ref() { 203 if(m_hasCopy) { 204 TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); 205 obj->~TPlainObjectType(); 206 } 207 } 208 209 protected: 210 211 template<typename Expression> 212 void construct(const Expression& expr,internal::true_type) 213 { 214 if((Options & int(StandardCompressedFormat)) && (!expr.isCompressed())) 215 { 216 TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); 217 ::new (obj) TPlainObjectType(expr); 218 m_hasCopy = true; 219 Base::construct(*obj); 220 } 221 else 222 { 223 Base::construct(expr); 224 } 225 } 226 227 template<typename Expression> 228 void construct(const Expression& expr, internal::false_type) 229 { 230 TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); 231 ::new (obj) TPlainObjectType(expr); 232 m_hasCopy = true; 233 Base::construct(*obj); 234 } 235 236 protected: 237 char m_object_bytes[sizeof(TPlainObjectType)]; 238 bool m_hasCopy; 239 }; 240 241 242 243 /** 244 * \ingroup SparseCore_Module 245 * 246 * \brief A sparse vector expression referencing an existing sparse vector expression 247 * 248 * \tparam SparseVectorType the equivalent sparse vector type of the referenced data, it must be a template instance of class SparseVector. 249 * 250 * \sa class Ref 251 */ 252 #ifndef EIGEN_PARSED_BY_DOXYGEN 253 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 254 class Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType > 255 : public internal::SparseRefBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType > > 256 #else 257 template<typename SparseVectorType> 258 class Ref<SparseVectorType> 259 : public SparseMapBase<Derived,WriteAccessors> 260 #endif 261 { 262 typedef SparseVector<MatScalar,MatOptions,MatIndex> PlainObjectType; 263 typedef internal::traits<Ref> Traits; 264 template<int OtherOptions> 265 inline Ref(const SparseVector<MatScalar,OtherOptions,MatIndex>& expr); 266 public: 267 268 typedef internal::SparseRefBase<Ref> Base; 269 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) 270 271 #ifndef EIGEN_PARSED_BY_DOXYGEN 272 template<int OtherOptions> 273 inline Ref(SparseVector<MatScalar,OtherOptions,MatIndex>& expr) 274 { 275 EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseVector<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 276 Base::construct(expr.derived()); 277 } 278 279 template<typename Derived> 280 inline Ref(const SparseCompressedBase<Derived>& expr) 281 #else 282 /** Implicit constructor from any 1D sparse vector expression */ 283 template<typename Derived> 284 inline Ref(SparseCompressedBase<Derived>& expr) 285 #endif 286 { 287 EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); 288 EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); 289 Base::construct(expr.const_cast_derived()); 290 } 291 }; 292 293 // this is the const ref version 294 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 295 class Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> 296 : public internal::SparseRefBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > 297 { 298 typedef SparseVector<MatScalar,MatOptions,MatIndex> TPlainObjectType; 299 typedef internal::traits<Ref> Traits; 300 public: 301 302 typedef internal::SparseRefBase<Ref> Base; 303 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) 304 305 template<typename Derived> 306 inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) 307 { 308 construct(expr.derived(), typename Traits::template match<Derived>::type()); 309 } 310 311 inline Ref(const Ref& other) : Base(other), m_hasCopy(false) { 312 // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy 313 } 314 315 template<typename OtherRef> 316 inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) { 317 construct(other.derived(), typename Traits::template match<OtherRef>::type()); 318 } 319 320 ~Ref() { 321 if(m_hasCopy) { 322 TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); 323 obj->~TPlainObjectType(); 324 } 325 } 326 327 protected: 328 329 template<typename Expression> 330 void construct(const Expression& expr,internal::true_type) 331 { 332 Base::construct(expr); 333 } 334 335 template<typename Expression> 336 void construct(const Expression& expr, internal::false_type) 337 { 338 TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); 339 ::new (obj) TPlainObjectType(expr); 340 m_hasCopy = true; 341 Base::construct(*obj); 342 } 343 344 protected: 345 char m_object_bytes[sizeof(TPlainObjectType)]; 346 bool m_hasCopy; 347 }; 348 349 namespace internal { 350 351 // FIXME shall we introduce a general evaluatior_ref that we can specialize for any sparse object once, and thus remove this copy-pasta thing... 352 353 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 354 struct evaluator<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > 355 : evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > 356 { 357 typedef evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; 358 typedef Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; 359 evaluator() : Base() {} 360 explicit evaluator(const XprType &mat) : Base(mat) {} 361 }; 362 363 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 364 struct evaluator<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > 365 : evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > 366 { 367 typedef evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; 368 typedef Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; 369 evaluator() : Base() {} 370 explicit evaluator(const XprType &mat) : Base(mat) {} 371 }; 372 373 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 374 struct evaluator<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > 375 : evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > 376 { 377 typedef evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; 378 typedef Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; 379 evaluator() : Base() {} 380 explicit evaluator(const XprType &mat) : Base(mat) {} 381 }; 382 383 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> 384 struct evaluator<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > 385 : evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > 386 { 387 typedef evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; 388 typedef Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; 389 evaluator() : Base() {} 390 explicit evaluator(const XprType &mat) : Base(mat) {} 391 }; 392 393 } 394 395 } // end namespace Eigen 396 397 #endif // EIGEN_SPARSE_REF_H 398