SkylineProduct.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2009 Guillaume Saupin <guillaume.saupin@cea.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_SKYLINEPRODUCT_H
11 #define EIGEN_SKYLINEPRODUCT_H
12 
13 #include "./InternalHeaderCheck.h"
14 
15 namespace Eigen {
16 
17 template<typename Lhs, typename Rhs, int ProductMode>
19  typedef const typename internal::nested_eval<Lhs, Rhs::RowsAtCompileTime>::type LhsNested;
20  typedef const typename internal::nested_eval<Rhs, Lhs::RowsAtCompileTime>::type RhsNested;
21 
23 };
24 
25 template<typename LhsNested, typename RhsNested, int ProductMode>
26 struct internal::traits<SkylineProduct<LhsNested, RhsNested, ProductMode> > {
27  // clean the nested types:
28  typedef internal::remove_all_t<LhsNested> LhsNested_;
29  typedef internal::remove_all_t<RhsNested> RhsNested_;
30  typedef typename LhsNested_::Scalar Scalar;
31 
32  enum {
33  LhsCoeffReadCost = LhsNested_::CoeffReadCost,
34  RhsCoeffReadCost = RhsNested_::CoeffReadCost,
35  LhsFlags = LhsNested_::Flags,
36  RhsFlags = RhsNested_::Flags,
37 
38  RowsAtCompileTime = LhsNested_::RowsAtCompileTime,
39  ColsAtCompileTime = RhsNested_::ColsAtCompileTime,
40  InnerSize = internal::min_size_prefer_fixed(LhsNested_::ColsAtCompileTime, RhsNested_::RowsAtCompileTime),
41 
42  MaxRowsAtCompileTime = LhsNested_::MaxRowsAtCompileTime,
43  MaxColsAtCompileTime = RhsNested_::MaxColsAtCompileTime,
44 
45  EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit),
46  ResultIsSkyline = ProductMode == SkylineTimeSkylineProduct,
47 
48  RemovedBits = ~((EvalToRowMajor ? 0 : RowMajorBit) | (ResultIsSkyline ? 0 : SkylineBit)),
49 
50  Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
53 
54  CoeffReadCost = HugeCost
55  };
56 
57  typedef std::conditional_t<ResultIsSkyline,
58  SkylineMatrixBase<SkylineProduct<LhsNested, RhsNested, ProductMode> >,
59  MatrixBase<SkylineProduct<LhsNested, RhsNested, ProductMode> > > Base;
60 };
61 
62 namespace internal {
63 template<typename LhsNested, typename RhsNested, int ProductMode>
64 class SkylineProduct : no_assignment_operator,
65 public traits<SkylineProduct<LhsNested, RhsNested, ProductMode> >::Base {
66 public:
67 
68  EIGEN_GENERIC_PUBLIC_INTERFACE(SkylineProduct)
69 
70 private:
71 
72  typedef typename traits<SkylineProduct>::LhsNested_ LhsNested_;
73  typedef typename traits<SkylineProduct>::RhsNested_ RhsNested_;
74 
75 public:
76 
77  template<typename Lhs, typename Rhs>
78  EIGEN_STRONG_INLINE SkylineProduct(const Lhs& lhs, const Rhs& rhs)
79  : m_lhs(lhs), m_rhs(rhs) {
80  eigen_assert(lhs.cols() == rhs.rows());
81 
82  enum {
83  ProductIsValid = LhsNested_::ColsAtCompileTime == Dynamic
84  || RhsNested_::RowsAtCompileTime == Dynamic
85  || int(LhsNested_::ColsAtCompileTime) == int(RhsNested_::RowsAtCompileTime),
86  AreVectors = LhsNested_::IsVectorAtCompileTime && RhsNested_::IsVectorAtCompileTime,
87  SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(LhsNested_, RhsNested_)
88  };
89  // note to the lost user:
90  // * for a dot product use: v1.dot(v2)
91  // * for a coeff-wise product use: v1.cwise()*v2
92  EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
93  INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
94  EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
95  INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
96  EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
97  }
98 
99  EIGEN_STRONG_INLINE Index rows() const {
100  return m_lhs.rows();
101  }
102 
103  EIGEN_STRONG_INLINE Index cols() const {
104  return m_rhs.cols();
105  }
106 
107  EIGEN_STRONG_INLINE const LhsNested_& lhs() const {
108  return m_lhs;
109  }
110 
111  EIGEN_STRONG_INLINE const RhsNested_& rhs() const {
112  return m_rhs;
113  }
114 
115 protected:
116  LhsNested m_lhs;
117  RhsNested m_rhs;
118 };
119 
120 // dense = skyline * dense
121 // Note that here we force no inlining and separate the setZero() because GCC messes up otherwise
122 
123 template<typename Lhs, typename Rhs, typename Dest>
124 EIGEN_DONT_INLINE void skyline_row_major_time_dense_product(const Lhs& lhs, const Rhs& rhs, Dest& dst) {
125  typedef remove_all_t<Lhs> Lhs_;
126  typedef remove_all_t<Rhs> Rhs_;
127  typedef typename traits<Lhs>::Scalar Scalar;
128 
129  enum {
130  LhsIsRowMajor = (Lhs_::Flags & RowMajorBit) == RowMajorBit,
131  LhsIsSelfAdjoint = (Lhs_::Flags & SelfAdjointBit) == SelfAdjointBit,
132  ProcessFirstHalf = LhsIsSelfAdjoint
133  && (((Lhs_::Flags & (UpperTriangularBit | LowerTriangularBit)) == 0)
134  || ((Lhs_::Flags & UpperTriangularBit) && !LhsIsRowMajor)
135  || ((Lhs_::Flags & LowerTriangularBit) && LhsIsRowMajor)),
136  ProcessSecondHalf = LhsIsSelfAdjoint && (!ProcessFirstHalf)
137  };
138 
139  //Use matrix diagonal part <- Improvement : use inner iterator on dense matrix.
140  for (Index col = 0; col < rhs.cols(); col++) {
141  for (Index row = 0; row < lhs.rows(); row++) {
142  dst(row, col) = lhs.coeffDiag(row) * rhs(row, col);
143  }
144  }
145  //Use matrix lower triangular part
146  for (Index row = 0; row < lhs.rows(); row++) {
147  typename Lhs_::InnerLowerIterator lIt(lhs, row);
148  const Index stop = lIt.col() + lIt.size();
149  for (Index col = 0; col < rhs.cols(); col++) {
150 
151  Index k = lIt.col();
152  Scalar tmp = 0;
153  while (k < stop) {
154  tmp +=
155  lIt.value() *
156  rhs(k++, col);
157  ++lIt;
158  }
159  dst(row, col) += tmp;
160  lIt += -lIt.size();
161  }
162 
163  }
164 
165  //Use matrix upper triangular part
166  for (Index lhscol = 0; lhscol < lhs.cols(); lhscol++) {
167  typename Lhs_::InnerUpperIterator uIt(lhs, lhscol);
168  const Index stop = uIt.size() + uIt.row();
169  for (Index rhscol = 0; rhscol < rhs.cols(); rhscol++) {
170 
171 
172  const Scalar rhsCoeff = rhs.coeff(lhscol, rhscol);
173  Index k = uIt.row();
174  while (k < stop) {
175  dst(k++, rhscol) +=
176  uIt.value() *
177  rhsCoeff;
178  ++uIt;
179  }
180  uIt += -uIt.size();
181  }
182  }
183 
184 }
185 
186 template<typename Lhs, typename Rhs, typename Dest>
187 EIGEN_DONT_INLINE void skyline_col_major_time_dense_product(const Lhs& lhs, const Rhs& rhs, Dest& dst) {
188  typedef remove_all_t<Lhs> Lhs_;
189  typedef remove_all_t<Rhs> Rhs_;
190  typedef typename traits<Lhs>::Scalar Scalar;
191 
192  enum {
193  LhsIsRowMajor = (Lhs_::Flags & RowMajorBit) == RowMajorBit,
194  LhsIsSelfAdjoint = (Lhs_::Flags & SelfAdjointBit) == SelfAdjointBit,
195  ProcessFirstHalf = LhsIsSelfAdjoint
196  && (((Lhs_::Flags & (UpperTriangularBit | LowerTriangularBit)) == 0)
197  || ((Lhs_::Flags & UpperTriangularBit) && !LhsIsRowMajor)
198  || ((Lhs_::Flags & LowerTriangularBit) && LhsIsRowMajor)),
199  ProcessSecondHalf = LhsIsSelfAdjoint && (!ProcessFirstHalf)
200  };
201 
202  //Use matrix diagonal part <- Improvement : use inner iterator on dense matrix.
203  for (Index col = 0; col < rhs.cols(); col++) {
204  for (Index row = 0; row < lhs.rows(); row++) {
205  dst(row, col) = lhs.coeffDiag(row) * rhs(row, col);
206  }
207  }
208 
209  //Use matrix upper triangular part
210  for (Index row = 0; row < lhs.rows(); row++) {
211  typename Lhs_::InnerUpperIterator uIt(lhs, row);
212  const Index stop = uIt.col() + uIt.size();
213  for (Index col = 0; col < rhs.cols(); col++) {
214 
215  Index k = uIt.col();
216  Scalar tmp = 0;
217  while (k < stop) {
218  tmp +=
219  uIt.value() *
220  rhs(k++, col);
221  ++uIt;
222  }
223 
224 
225  dst(row, col) += tmp;
226  uIt += -uIt.size();
227  }
228  }
229 
230  //Use matrix lower triangular part
231  for (Index lhscol = 0; lhscol < lhs.cols(); lhscol++) {
232  typename Lhs_::InnerLowerIterator lIt(lhs, lhscol);
233  const Index stop = lIt.size() + lIt.row();
234  for (Index rhscol = 0; rhscol < rhs.cols(); rhscol++) {
235 
236  const Scalar rhsCoeff = rhs.coeff(lhscol, rhscol);
237  Index k = lIt.row();
238  while (k < stop) {
239  dst(k++, rhscol) +=
240  lIt.value() *
241  rhsCoeff;
242  ++lIt;
243  }
244  lIt += -lIt.size();
245  }
246  }
247 
248 }
249 
250 template<typename Lhs, typename Rhs, typename ResultType,
251  int LhsStorageOrder = traits<Lhs>::Flags&RowMajorBit>
252  struct skyline_product_selector;
253 
254 template<typename Lhs, typename Rhs, typename ResultType>
255 struct skyline_product_selector<Lhs, Rhs, ResultType, RowMajor> {
256  typedef typename traits<remove_all_t<Lhs>>::Scalar Scalar;
257 
258  static void run(const Lhs& lhs, const Rhs& rhs, ResultType & res) {
259  skyline_row_major_time_dense_product<Lhs, Rhs, ResultType > (lhs, rhs, res);
260  }
261 };
262 
263 template<typename Lhs, typename Rhs, typename ResultType>
264 struct skyline_product_selector<Lhs, Rhs, ResultType, ColMajor> {
265  typedef typename traits<remove_all_t<Lhs>>::Scalar Scalar;
266 
267  static void run(const Lhs& lhs, const Rhs& rhs, ResultType & res) {
268  skyline_col_major_time_dense_product<Lhs, Rhs, ResultType > (lhs, rhs, res);
269  }
270 };
271 
272 } // end namespace internal
273 
274 // template<typename Derived>
275 // template<typename Lhs, typename Rhs >
276 // Derived & MatrixBase<Derived>::lazyAssign(const SkylineProduct<Lhs, Rhs, SkylineTimeDenseProduct>& product) {
277 // typedef internal::remove_all_t<Lhs> Lhs_;
278 // internal::skyline_product_selector<internal::remove_all_t<Lhs>,
279 // internal::remove_all_t<Rhs>,
280 // Derived>::run(product.lhs(), product.rhs(), derived());
281 //
282 // return derived();
283 // }
284 
285 // skyline * dense
286 
287 template<typename Derived>
288 template<typename OtherDerived >
289 EIGEN_STRONG_INLINE const typename SkylineProductReturnType<Derived, OtherDerived>::Type
291 
292  return typename SkylineProductReturnType<Derived, OtherDerived>::Type(derived(), other.derived());
293 }
294 
295 } // end namespace Eigen
296 
297 #endif // EIGEN_SKYLINEPRODUCT_H
RowXpr row(Index i) const
ColXpr col(Index i) const
#define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived)
#define EIGEN_DONT_INLINE
#define eigen_assert(x)
#define EIGEN_STATIC_ASSERT(X, MSG)
#define EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0, TYPE1)
const SkylineProductReturnType< Derived, OtherDerived >::Type operator*(const MatrixBase< OtherDerived > &other) const
EIGEN_DEPRECATED const unsigned int EvalBeforeAssigningBit
const unsigned int EvalBeforeNestingBit
const unsigned int RowMajorBit
EIGEN_DONT_INLINE void skyline_row_major_time_dense_product(const Lhs &lhs, const Rhs &rhs, Dest &dst)
constexpr int min_size_prefer_fixed(A a, B b)
typename remove_all< T >::type remove_all_t
EIGEN_DONT_INLINE void skyline_col_major_time_dense_product(const Lhs &lhs, const Rhs &rhs, Dest &dst)
: TensorContractionSycl.h, provides various tensor contraction kernel for SYCL backend
@ SkylineTimeSkylineProduct
Definition: SkylineUtil.h:25
const unsigned int HereditaryBits
const int HugeCost
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
const unsigned int SkylineBit
Definition: SkylineUtil.h:23
const int Dynamic
Derived::Index cols
Derived::Index rows
SkylineProduct< LhsNested, RhsNested, ProductMode > Type
const internal::nested_eval< Lhs, Rhs::RowsAtCompileTime >::type LhsNested
const internal::nested_eval< Rhs, Lhs::RowsAtCompileTime >::type RhsNested