Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
Product.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2011 Gael Guennebaud <[email protected]>
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_PRODUCT_H
11#define EIGEN_PRODUCT_H
12
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17
18template <typename Lhs, typename Rhs, int Option, typename StorageKind>
19class ProductImpl;
20
21namespace internal {
22
23template <typename Lhs, typename Rhs, int Option>
24struct traits<Product<Lhs, Rhs, Option>> {
25 typedef remove_all_t<Lhs> LhsCleaned;
26 typedef remove_all_t<Rhs> RhsCleaned;
27 typedef traits<LhsCleaned> LhsTraits;
28 typedef traits<RhsCleaned> RhsTraits;
29
30 typedef MatrixXpr XprKind;
31
32 typedef typename ScalarBinaryOpTraits<typename traits<LhsCleaned>::Scalar,
33 typename traits<RhsCleaned>::Scalar>::ReturnType Scalar;
34 typedef typename product_promote_storage_type<typename LhsTraits::StorageKind, typename RhsTraits::StorageKind,
35 internal::product_type<Lhs, Rhs>::ret>::ret StorageKind;
36 typedef typename promote_index_type<typename LhsTraits::StorageIndex, typename RhsTraits::StorageIndex>::type
37 StorageIndex;
38
39 enum {
40 RowsAtCompileTime = LhsTraits::RowsAtCompileTime,
41 ColsAtCompileTime = RhsTraits::ColsAtCompileTime,
42 MaxRowsAtCompileTime = LhsTraits::MaxRowsAtCompileTime,
43 MaxColsAtCompileTime = RhsTraits::MaxColsAtCompileTime,
44
45 // FIXME: only needed by GeneralMatrixMatrixTriangular
46 InnerSize = min_size_prefer_fixed(LhsTraits::ColsAtCompileTime, RhsTraits::RowsAtCompileTime),
47
48 // The storage order is somewhat arbitrary here. The correct one will be determined through the evaluator.
49 Flags = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? RowMajorBit
50 : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0
51 : (((LhsTraits::Flags & NoPreferredStorageOrderBit) && (RhsTraits::Flags & RowMajorBit)) ||
52 ((RhsTraits::Flags & NoPreferredStorageOrderBit) && (LhsTraits::Flags & RowMajorBit)))
55 };
56};
57
58struct TransposeProductEnum {
59 // convenience enumerations to specialize transposed products
60 enum : int {
61 Default = 0x00,
62 Matrix = 0x01,
63 Permutation = 0x02,
64 MatrixMatrix = (Matrix << 8) | Matrix,
65 MatrixPermutation = (Matrix << 8) | Permutation,
66 PermutationMatrix = (Permutation << 8) | Matrix
67 };
68};
69template <typename Xpr>
70struct TransposeKind {
71 static constexpr int Kind = is_matrix_base_xpr<Xpr>::value ? TransposeProductEnum::Matrix
72 : is_permutation_base_xpr<Xpr>::value ? TransposeProductEnum::Permutation
73 : TransposeProductEnum::Default;
74};
75
76template <typename Lhs, typename Rhs>
77struct TransposeProductKind {
78 static constexpr int Kind = (TransposeKind<Lhs>::Kind << 8) | TransposeKind<Rhs>::Kind;
79};
80
81template <typename Lhs, typename Rhs, int Option, int Kind = TransposeProductKind<Lhs, Rhs>::Kind>
82struct product_transpose_helper {
83 // by default, don't optimize the transposed product
84 using Derived = Product<Lhs, Rhs, Option>;
85 using Scalar = typename Derived::Scalar;
86 using TransposeType = Transpose<const Derived>;
87 using ConjugateTransposeType = CwiseUnaryOp<scalar_conjugate_op<Scalar>, TransposeType>;
88 using AdjointType = std::conditional_t<NumTraits<Scalar>::IsComplex, ConjugateTransposeType, TransposeType>;
89
90 // return (lhs * rhs)^T
91 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) {
92 return TransposeType(derived);
93 }
94 // return (lhs * rhs)^H
95 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) {
96 return AdjointType(TransposeType(derived));
97 }
98};
99
100template <typename Lhs, typename Rhs, int Option>
101struct product_transpose_helper<Lhs, Rhs, Option, TransposeProductEnum::MatrixMatrix> {
102 // expand the transposed matrix-matrix product
103 using Derived = Product<Lhs, Rhs, Option>;
104
105 using LhsScalar = typename traits<Lhs>::Scalar;
106 using LhsTransposeType = typename DenseBase<Lhs>::ConstTransposeReturnType;
107 using LhsConjugateTransposeType = CwiseUnaryOp<scalar_conjugate_op<LhsScalar>, LhsTransposeType>;
108 using LhsAdjointType =
109 std::conditional_t<NumTraits<LhsScalar>::IsComplex, LhsConjugateTransposeType, LhsTransposeType>;
110
111 using RhsScalar = typename traits<Rhs>::Scalar;
112 using RhsTransposeType = typename DenseBase<Rhs>::ConstTransposeReturnType;
113 using RhsConjugateTransposeType = CwiseUnaryOp<scalar_conjugate_op<RhsScalar>, RhsTransposeType>;
114 using RhsAdjointType =
115 std::conditional_t<NumTraits<RhsScalar>::IsComplex, RhsConjugateTransposeType, RhsTransposeType>;
116
117 using TransposeType = Product<RhsTransposeType, LhsTransposeType, Option>;
118 using AdjointType = Product<RhsAdjointType, LhsAdjointType, Option>;
119
120 // return rhs^T * lhs^T
121 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) {
122 return TransposeType(RhsTransposeType(derived.rhs()), LhsTransposeType(derived.lhs()));
123 }
124 // return rhs^H * lhs^H
125 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) {
126 return AdjointType(RhsAdjointType(RhsTransposeType(derived.rhs())),
127 LhsAdjointType(LhsTransposeType(derived.lhs())));
128 }
129};
130template <typename Lhs, typename Rhs, int Option>
131struct product_transpose_helper<Lhs, Rhs, Option, TransposeProductEnum::PermutationMatrix> {
132 // expand the transposed permutation-matrix product
133 using Derived = Product<Lhs, Rhs, Option>;
134
135 using LhsInverseType = typename PermutationBase<Lhs>::InverseReturnType;
136
137 using RhsScalar = typename traits<Rhs>::Scalar;
138 using RhsTransposeType = typename DenseBase<Rhs>::ConstTransposeReturnType;
139 using RhsConjugateTransposeType = CwiseUnaryOp<scalar_conjugate_op<RhsScalar>, RhsTransposeType>;
140 using RhsAdjointType =
141 std::conditional_t<NumTraits<RhsScalar>::IsComplex, RhsConjugateTransposeType, RhsTransposeType>;
142
143 using TransposeType = Product<RhsTransposeType, LhsInverseType, Option>;
144 using AdjointType = Product<RhsAdjointType, LhsInverseType, Option>;
145
146 // return rhs^T * lhs^-1
147 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) {
148 return TransposeType(RhsTransposeType(derived.rhs()), LhsInverseType(derived.lhs()));
149 }
150 // return rhs^H * lhs^-1
151 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) {
152 return AdjointType(RhsAdjointType(RhsTransposeType(derived.rhs())), LhsInverseType(derived.lhs()));
153 }
154};
155template <typename Lhs, typename Rhs, int Option>
156struct product_transpose_helper<Lhs, Rhs, Option, TransposeProductEnum::MatrixPermutation> {
157 // expand the transposed matrix-permutation product
158 using Derived = Product<Lhs, Rhs, Option>;
159
160 using LhsScalar = typename traits<Lhs>::Scalar;
161 using LhsTransposeType = typename DenseBase<Lhs>::ConstTransposeReturnType;
162 using LhsConjugateTransposeType = CwiseUnaryOp<scalar_conjugate_op<LhsScalar>, LhsTransposeType>;
163 using LhsAdjointType =
164 std::conditional_t<NumTraits<LhsScalar>::IsComplex, LhsConjugateTransposeType, LhsTransposeType>;
165
166 using RhsInverseType = typename PermutationBase<Rhs>::InverseReturnType;
167
168 using TransposeType = Product<RhsInverseType, LhsTransposeType, Option>;
169 using AdjointType = Product<RhsInverseType, LhsAdjointType, Option>;
170
171 // return rhs^-1 * lhs^T
172 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) {
173 return TransposeType(RhsInverseType(derived.rhs()), LhsTransposeType(derived.lhs()));
174 }
175 // return rhs^-1 * lhs^H
176 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) {
177 return AdjointType(RhsInverseType(derived.rhs()), LhsAdjointType(LhsTransposeType(derived.lhs())));
178 }
179};
180
181} // end namespace internal
182
197template <typename Lhs_, typename Rhs_, int Option>
199 : public ProductImpl<Lhs_, Rhs_, Option,
200 typename internal::product_promote_storage_type<
201 typename internal::traits<Lhs_>::StorageKind, typename internal::traits<Rhs_>::StorageKind,
202 internal::product_type<Lhs_, Rhs_>::ret>::ret> {
203 public:
204 typedef Lhs_ Lhs;
205 typedef Rhs_ Rhs;
206
207 typedef
208 typename ProductImpl<Lhs, Rhs, Option,
209 typename internal::product_promote_storage_type<
210 typename internal::traits<Lhs>::StorageKind, typename internal::traits<Rhs>::StorageKind,
211 internal::product_type<Lhs, Rhs>::ret>::ret>::Base Base;
212 EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
213
214 typedef typename internal::ref_selector<Lhs>::type LhsNested;
215 typedef typename internal::ref_selector<Rhs>::type RhsNested;
216 typedef internal::remove_all_t<LhsNested> LhsNestedCleaned;
217 typedef internal::remove_all_t<RhsNested> RhsNestedCleaned;
218
220 using AdjointReturnType = typename internal::product_transpose_helper<Lhs, Rhs, Option>::AdjointType;
221
222 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) {
223 eigen_assert(lhs.cols() == rhs.rows() && "invalid matrix product" &&
224 "if you wanted a coeff-wise or a dot product use the respective explicit functions");
225 }
226
227 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_lhs.rows(); }
228 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_rhs.cols(); }
229
230 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const LhsNestedCleaned& lhs() const { return m_lhs; }
231 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const RhsNestedCleaned& rhs() const { return m_rhs; }
232
233 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeReturnType transpose() const {
234 return internal::product_transpose_helper<Lhs, Rhs, Option>::run_transpose(*this);
235 }
236 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointReturnType adjoint() const {
237 return internal::product_transpose_helper<Lhs, Rhs, Option>::run_adjoint(*this);
238 }
239
240 protected:
241 LhsNested m_lhs;
242 RhsNested m_rhs;
243};
244
245namespace internal {
246
247template <typename Lhs, typename Rhs, int Option, int ProductTag = internal::product_type<Lhs, Rhs>::ret>
248class dense_product_base : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {};
249
251template <typename Lhs, typename Rhs, int Option>
252class dense_product_base<Lhs, Rhs, Option, InnerProduct>
253 : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {
254 typedef Product<Lhs, Rhs, Option> ProductXpr;
255 typedef typename internal::dense_xpr_base<ProductXpr>::type Base;
256
257 public:
258 using Base::derived;
259 typedef typename Base::Scalar Scalar;
260
261 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator const Scalar() const {
262 return internal::evaluator<ProductXpr>(derived()).coeff(0, 0);
263 }
264};
265
266} // namespace internal
267
268// Generic API dispatcher
269template <typename Lhs, typename Rhs, int Option, typename StorageKind>
270class ProductImpl : public internal::generic_xpr_base<Product<Lhs, Rhs, Option>, MatrixXpr, StorageKind>::type {
271 public:
272 typedef typename internal::generic_xpr_base<Product<Lhs, Rhs, Option>, MatrixXpr, StorageKind>::type Base;
273};
274
275template <typename Lhs, typename Rhs, int Option>
276class ProductImpl<Lhs, Rhs, Option, Dense> : public internal::dense_product_base<Lhs, Rhs, Option> {
277 typedef Product<Lhs, Rhs, Option> Derived;
278
279 public:
280 typedef typename internal::dense_product_base<Lhs, Rhs, Option> Base;
281 EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
282 protected:
283 enum {
284 IsOneByOne = (RowsAtCompileTime == 1 || RowsAtCompileTime == Dynamic) &&
285 (ColsAtCompileTime == 1 || ColsAtCompileTime == Dynamic),
286 EnableCoeff = IsOneByOne || Option == LazyProduct
287 };
288
289 public:
290 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const {
291 EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS);
292 eigen_assert((Option == LazyProduct) || (this->rows() == 1 && this->cols() == 1));
293
294 return internal::evaluator<Derived>(derived()).coeff(row, col);
295 }
296
297 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index i) const {
298 EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS);
299 eigen_assert((Option == LazyProduct) || (this->rows() == 1 && this->cols() == 1));
300
301 return internal::evaluator<Derived>(derived()).coeff(i);
302 }
303};
304
305} // end namespace Eigen
306
307#endif // EIGEN_PRODUCT_H
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:202
Expression of the transpose of a matrix.
Definition Transpose.h:56
const unsigned int NoPreferredStorageOrderBit
Definition Constants.h:182
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition Core:137
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25