Eigen  5.0.1
 
Loading...
Searching...
No Matches
ScaledPermutationMatrix.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// This Source Code Form is subject to the terms of the Mozilla
5// Public License v. 2.0. If a copy of the MPL was not distributed
6// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
7// SPDX-FileCopyrightText: The Eigen Authors
8// SPDX-License-Identifier: MPL-2.0
9
10#ifndef EIGEN_SCALEDPERMUTATIONMATRIX_H
11#define EIGEN_SCALEDPERMUTATIONMATRIX_H
12
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19
20template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
21struct traits<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
22 using Scalar = Scalar_;
23 using StorageIndex = StorageIndex_;
24 // Dense, so that products and sums with dense operands promote with the existing rules; the O(n) kernels are
25 // selected by the shape (ScaledPermutationShape), as for TriangularView.
26 using StorageKind = Dense;
27 using XprKind = MatrixXpr;
28 using PermutationType = PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>;
29 using ScalesType = Matrix<Scalar_, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>;
30 static constexpr int RowsAtCompileTime = SizeAtCompileTime;
31 static constexpr int ColsAtCompileTime = SizeAtCompileTime;
32 static constexpr int MaxRowsAtCompileTime = MaxSizeAtCompileTime;
33 static constexpr int MaxColsAtCompileTime = MaxSizeAtCompileTime;
34 static constexpr unsigned int Flags = NestByRefBit;
35};
36
38template <typename Scalar, typename Lhs, typename Rhs, typename StorageIndex>
39struct scaled_permutation_result {
40 static constexpr int Size = size_prefer_fixed(traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime);
41 static constexpr int MaxSize =
42 min_size_prefer_fixed(traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime);
43 using type = ScaledPermutationMatrix<Scalar, Size, MaxSize, StorageIndex>;
44};
45
46template <typename Lhs, typename Rhs, typename StorageIndex>
47struct scaled_permutation_product_result {
48 using LhsScalar = typename traits<Lhs>::Scalar;
49 using RhsScalar = typename traits<Rhs>::Scalar;
50 using Scalar =
51 typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_product_op<LhsScalar, RhsScalar>>::ReturnType;
52 using type = typename scaled_permutation_result<Scalar, Lhs, Rhs, StorageIndex>::type;
53};
54
56template <typename IndicesType, typename Result>
57EIGEN_DEVICE_FUNC void invert_permutation_indices(const IndicesType& indices, Result& result) {
58 using StorageIndex = typename Result::Scalar;
59 for (Index k = 0; k < indices.size(); ++k) result.coeffRef(indices.coeff(k)) = StorageIndex(k);
60}
61
62} // namespace internal
63
81template <typename Derived>
82class ScaledPermutationBase : public EigenBase<Derived> {
83 using Traits = internal::traits<Derived>;
84 using Base = EigenBase<Derived>;
85
86 public:
87#ifndef EIGEN_PARSED_BY_DOXYGEN
88 using Scalar = typename Traits::Scalar;
89 using RealScalar = typename NumTraits<Scalar>::Real;
90 using StorageIndex = typename Traits::StorageIndex;
91 using StorageKind = typename Traits::StorageKind;
92 using PermutationType = typename Traits::PermutationType;
93 using ScalesType = typename Traits::ScalesType;
94 using IndicesType = typename PermutationType::IndicesType;
95 static constexpr int RowsAtCompileTime = Traits::RowsAtCompileTime;
96 static constexpr int ColsAtCompileTime = Traits::ColsAtCompileTime;
97 static constexpr int MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime;
98 static constexpr int MaxColsAtCompileTime = Traits::MaxColsAtCompileTime;
99 static constexpr int SizeAtCompileTime = internal::size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime);
100 static constexpr int MaxSizeAtCompileTime =
101 internal::size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime);
102 static constexpr bool IsVectorAtCompileTime = false;
103 static constexpr unsigned int Flags = Traits::Flags;
104 using DenseMatrixType =
107 using Nested = const Derived&;
108 using Base::derived;
109#endif
110
112 EIGEN_DEVICE_FUNC constexpr Index rows() const { return indices().size(); }
114 EIGEN_DEVICE_FUNC constexpr Index cols() const { return indices().size(); }
115
117 EIGEN_DEVICE_FUNC const PermutationType& permutation() const { return derived().permutation(); }
119 EIGEN_DEVICE_FUNC constexpr const IndicesType& indices() const { return derived().indices(); }
121 EIGEN_DEVICE_FUNC const ScalesType& scales() const { return derived().scales(); }
122
124 EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const {
125 eigen_assert(row >= 0 && col >= 0 && row < rows() && col < cols());
126 return Index(indices().coeff(col)) == row ? scales().coeff(col) : Scalar(0);
127 }
128
130 EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); }
131
132#ifndef EIGEN_PARSED_BY_DOXYGEN
133 template <typename DenseDerived>
134 EIGEN_DEVICE_FUNC void evalTo(MatrixBase<DenseDerived>& other) const {
135 other.setZero();
136 for (Index k = 0; k < rows(); ++k) other.coeffRef(indices().coeff(k), k) = scales().coeff(k);
137 }
138#endif
139
142 PlainObject inverse() const {
143 PlainObject result(rows());
144 for (Index k = 0; k < rows(); ++k) {
145 const Index image = indices().coeff(k);
146 result.indices().coeffRef(image) = StorageIndex(k);
147 result.scales().coeffRef(image) = Scalar(1) / scales().coeff(k);
148 }
149 return result;
150 }
151
153 PlainObject transpose() const {
154 PlainObject result(rows());
155 for (Index k = 0; k < rows(); ++k) {
156 const Index image = indices().coeff(k);
157 result.indices().coeffRef(image) = StorageIndex(k);
158 result.scales().coeffRef(image) = scales().coeff(k);
159 }
160 return result;
161 }
162
164 PlainObject adjoint() const {
165 PlainObject result = transpose();
166 result.scales() = result.scales().conjugate();
167 return result;
168 }
169
171 Scalar determinant() const { return Scalar(RealScalar(permutation().determinant())) * scales().prod(); }
172
175 template <typename OtherDerived>
177 const MatrixBase<OtherDerived>& other) const {
179 }
180
183 template <typename OtherDerived>
185 const MatrixBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
186 return Product<OtherDerived, Derived, DefaultProduct>(other.derived(), scaled.derived());
187 }
188
190 template <typename OtherDerived>
195
197 template <typename OtherDerived>
199 const TriangularBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
201 }
202
203 // Closed-form products, all O(n). With S e_c = v_c e_{tau(c)} the rules are:
204 // S D: scale v_c d_c D S: scale d_{tau(c)} v_c
205 // S P: (tau(sigma(c)), v_{sigma(c)}) P S: (sigma(tau(c)), v_c)
206 // S T: (tau(tau2(c)), v_{tau2(c)} v2_c)
207
209 template <typename OtherDerived>
210 typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type operator*(
211 const DiagonalBase<OtherDerived>& other) const {
212 using Result = typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type;
213 eigen_assert(rows() == other.rows());
214 return Result(indices(), scales().cwiseProduct(other.diagonal()));
215 }
216
218 template <typename OtherDerived>
219 friend typename internal::scaled_permutation_product_result<OtherDerived, Derived, StorageIndex>::type operator*(
220 const DiagonalBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
221 using Result = typename internal::scaled_permutation_product_result<OtherDerived, Derived, StorageIndex>::type;
222 eigen_assert(other.rows() == scaled.rows());
223 Result result(scaled.rows());
224 result.indices() = scaled.indices();
225 for (Index k = 0; k < scaled.rows(); ++k)
226 result.scales().coeffRef(k) = other.diagonal().coeff(scaled.indices().coeff(k)) * scaled.scales().coeff(k);
227 return result;
228 }
229
231 template <typename OtherDerived>
232 PlainObject operator*(const PermutationBase<OtherDerived>& other) const {
233 eigen_assert(rows() == other.rows());
234 PlainObject result(rows());
235 for (Index k = 0; k < rows(); ++k) {
236 const Index source = other.indices().coeff(k);
237 result.indices().coeffRef(k) = indices().coeff(source);
238 result.scales().coeffRef(k) = scales().coeff(source);
239 }
240 return result;
241 }
242
244 template <typename OtherDerived>
245 friend PlainObject operator*(const PermutationBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
246 eigen_assert(other.rows() == scaled.rows());
247 PlainObject result(scaled.rows());
248 for (Index k = 0; k < scaled.rows(); ++k)
249 result.indices().coeffRef(k) = StorageIndex(other.indices().coeff(scaled.indices().coeff(k)));
250 result.scales() = scaled.scales();
251 return result;
252 }
253
255 template <typename OtherDerived>
256 PlainObject operator*(const InverseImpl<OtherDerived, PermutationStorage>& other) const {
257 eigen_assert(rows() == other.rows());
258 IndicesType inverse(rows());
259 internal::invert_permutation_indices(other.derived().nestedExpression().indices(), inverse);
260 PlainObject result(rows());
261 for (Index k = 0; k < rows(); ++k) {
262 const Index source = inverse.coeff(k);
263 result.indices().coeffRef(k) = indices().coeff(source);
264 result.scales().coeffRef(k) = scales().coeff(source);
265 }
266 return result;
267 }
268
270 template <typename OtherDerived>
271 friend PlainObject operator*(const InverseImpl<OtherDerived, PermutationStorage>& other,
272 const ScaledPermutationBase& scaled) {
273 eigen_assert(other.rows() == scaled.rows());
274 IndicesType inverse(scaled.rows());
275 internal::invert_permutation_indices(other.derived().nestedExpression().indices(), inverse);
276 PlainObject result(scaled.rows());
277 for (Index k = 0; k < scaled.rows(); ++k) result.indices().coeffRef(k) = inverse.coeff(scaled.indices().coeff(k));
278 result.scales() = scaled.scales();
279 return result;
280 }
281
283 template <typename OtherDerived>
284 typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type operator*(
285 const ScaledPermutationBase<OtherDerived>& other) const {
286 using Result = typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type;
287 eigen_assert(rows() == other.rows());
288 Result result(rows());
289 for (Index k = 0; k < rows(); ++k) {
290 const Index source = other.indices().coeff(k);
291 result.indices().coeffRef(k) = indices().coeff(source);
292 result.scales().coeffRef(k) = scales().coeff(source) * other.scales().coeff(k);
293 }
294 return result;
295 }
296
298 PlainObject operator*(const Scalar& alpha) const { return PlainObject(indices(), scales() * alpha); }
299
301 friend PlainObject operator*(const Scalar& alpha, const ScaledPermutationBase& scaled) {
302 return PlainObject(scaled.indices(), alpha * scaled.scales());
303 }
304
306 PlainObject operator-() const { return PlainObject(indices(), -scales()); }
307
308 // Sums with a dense matrix are lazy: the scaled permutation is read through its index-based evaluator.
309
311 template <typename OtherDerived>
312 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_sum_op)
313 operator+(const MatrixBase<OtherDerived>& lhs, const ScaledPermutationBase & rhs) {
314 return EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_sum_op)(lhs.derived(), rhs.derived());
315 }
316
318 template <typename OtherDerived>
319 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_sum_op)
320 operator+(const ScaledPermutationBase & lhs, const MatrixBase<OtherDerived>& rhs) {
321 return EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_sum_op)(lhs.derived(), rhs.derived());
322 }
323
325 template <typename OtherDerived>
326 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_difference_op)
327 operator-(const MatrixBase<OtherDerived>& lhs, const ScaledPermutationBase & rhs) {
328 return EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_difference_op)(lhs.derived(),
329 rhs.derived());
330 }
331
333 template <typename OtherDerived>
334 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_difference_op)
335 operator-(const ScaledPermutationBase & lhs, const MatrixBase<OtherDerived>& rhs) {
336 return EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_difference_op)(lhs.derived(),
337 rhs.derived());
338 }
339};
340
356template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
358 : public ScaledPermutationBase<
359 ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
361 using Traits = internal::traits<ScaledPermutationMatrix>;
362
363 public:
364#ifndef EIGEN_PARSED_BY_DOXYGEN
365 using Scalar = Scalar_;
366 using StorageIndex = StorageIndex_;
367 using PermutationType = typename Traits::PermutationType;
368 using ScalesType = typename Traits::ScalesType;
369 using IndicesType = typename PermutationType::IndicesType;
370#endif
371
373 EIGEN_DEVICE_FUNC ScaledPermutationMatrix() = default;
374
376 EIGEN_DEVICE_FUNC explicit ScaledPermutationMatrix(Index size) : m_permutation(size), m_scales(size) {}
377
379 template <typename PermutationDerived, typename DiagonalDerived>
381 const DiagonalBase<DiagonalDerived>& diagonal)
382 : m_permutation(permutation), m_scales(diagonal.diagonal()) {
383 eigen_assert(permutation.rows() == diagonal.rows());
384 }
385
387 template <typename IndicesDerived, typename ScalesDerived>
390 : m_permutation(indices), m_scales(scales) {
391 eigen_assert(indices.size() == scales.size());
392 }
393
395 template <typename OtherDerived>
397 : m_permutation(permutation), m_scales(ScalesType::Ones(permutation.rows())) {}
398
400 template <typename OtherDerived>
401 EIGEN_DEVICE_FUNC explicit ScaledPermutationMatrix(const DiagonalBase<OtherDerived>& diagonal)
402 : m_permutation(diagonal.rows()), m_scales(diagonal.diagonal()) {
403 m_permutation.setIdentity();
404 }
405
407 template <typename OtherDerived>
409 : m_permutation(other.permutation()), m_scales(other.scales()) {}
410
412 template <typename OtherDerived>
414 m_permutation = other.permutation();
415 m_scales = other.scales();
416 return *this;
417 }
418
420 EIGEN_DEVICE_FUNC const PermutationType& permutation() const { return m_permutation; }
422 EIGEN_DEVICE_FUNC PermutationType& permutation() { return m_permutation; }
424 EIGEN_DEVICE_FUNC constexpr const IndicesType& indices() const { return m_permutation.indices(); }
426 EIGEN_DEVICE_FUNC constexpr IndicesType& indices() { return m_permutation.indices(); }
428 EIGEN_DEVICE_FUNC const ScalesType& scales() const { return m_scales; }
430 EIGEN_DEVICE_FUNC ScalesType& scales() { return m_scales; }
431
433 EIGEN_DEVICE_FUNC void resize(Index size) {
434 m_permutation.resize(size);
435 m_scales.resize(size);
436 }
437
439 EIGEN_DEVICE_FUNC void setIdentity() {
440 m_permutation.setIdentity();
441 m_scales.setOnes();
442 }
443
445 EIGEN_DEVICE_FUNC void setIdentity(Index size) {
446 resize(size);
447 setIdentity();
448 }
449
450 protected:
451 PermutationType m_permutation;
452 ScalesType m_scales;
453};
454
455// The products of a permutation (or its inverse) and a diagonal matrix. With P e_c = e_{sigma(c)}:
456// P D: (sigma(c), d_c) D P: (sigma(c), d_{sigma(c)})
457// P^-1 D: (sigma^-1(c), d_c) D P^-1: (sigma^-1(c), d_{sigma^-1(c)})
458
461template <typename PermutationDerived, typename DiagonalDerived>
462typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived, DiagonalDerived,
463 typename PermutationDerived::StorageIndex>::type
465 using Result =
466 typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived,
467 DiagonalDerived, typename PermutationDerived::StorageIndex>::type;
468 eigen_assert(permutation.rows() == diagonal.rows());
469 return Result(permutation.indices(), diagonal.diagonal());
470}
471
474template <typename DiagonalDerived, typename PermutationDerived>
475typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived, DiagonalDerived,
476 typename PermutationDerived::StorageIndex>::type
478 using Result =
479 typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived,
480 DiagonalDerived, typename PermutationDerived::StorageIndex>::type;
481 eigen_assert(permutation.rows() == diagonal.rows());
482 Result result(permutation.rows());
483 result.indices() = permutation.indices();
484 for (Index k = 0; k < permutation.rows(); ++k)
485 result.scales().coeffRef(k) = diagonal.diagonal().coeff(permutation.indices().coeff(k));
486 return result;
487}
488
491template <typename PermutationType, typename DiagonalDerived>
492typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
493 typename PermutationType::StorageIndex>::type
494operator*(const InverseImpl<PermutationType, PermutationStorage>& inverse,
495 const DiagonalBase<DiagonalDerived>& diagonal) {
496 using Result =
497 typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
498 typename PermutationType::StorageIndex>::type;
499 eigen_assert(inverse.rows() == diagonal.rows());
500 Result result(inverse.rows());
501 internal::invert_permutation_indices(inverse.derived().nestedExpression().indices(), result.indices());
502 result.scales() = diagonal.diagonal();
503 return result;
504}
505
508template <typename DiagonalDerived, typename PermutationType>
509typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
510 typename PermutationType::StorageIndex>::type
512 const InverseImpl<PermutationType, PermutationStorage>& inverse) {
513 using Result =
514 typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
515 typename PermutationType::StorageIndex>::type;
516 eigen_assert(inverse.rows() == diagonal.rows());
517 Result result(inverse.rows());
518 internal::invert_permutation_indices(inverse.derived().nestedExpression().indices(), result.indices());
519 for (Index k = 0; k < inverse.rows(); ++k)
520 result.scales().coeffRef(k) = diagonal.diagonal().coeff(result.indices().coeff(k));
521 return result;
522}
523
524namespace internal {
525
526template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
527struct evaluator_traits<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
528 using Kind = IndexBased;
529 using Shape = ScaledPermutationShape;
530};
531
534template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
535struct evaluator<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>>
536 : evaluator_base<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
537 using XprType = ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>;
538 using Scalar = Scalar_;
539 using CoeffReturnType = Scalar;
540
541 static constexpr int CoeffReadCost =
542 int(NumTraits<StorageIndex_>::ReadCost) + int(NumTraits<Scalar>::ReadCost) + int(NumTraits<Scalar>::AddCost);
543 static constexpr unsigned int Flags = 0;
544 static constexpr int Alignment = 0;
545
546 EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : m_indices(xpr.indices()), m_scales(xpr.scales()) {}
547
548 EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const {
549 return Index(m_indices.coeff(col)) == row ? m_scales.coeff(col) : Scalar(0);
550 }
551
552 // Linear access is requested only for vector-shaped operands (inner products), i.e. a 1x1 matrix.
553 EIGEN_DEVICE_FUNC Scalar coeff(Index index) const {
554 eigen_assert(index == 0);
555 return m_scales.coeff(index);
556 }
557
558 protected:
559 evaluator<typename XprType::IndicesType> m_indices;
560 evaluator<typename XprType::ScalesType> m_scales;
561};
562
563struct ScaledPermutation2Dense {};
564
565template <>
566struct AssignmentKind<DenseShape, ScaledPermutationShape> {
567 using Kind = ScaledPermutation2Dense;
568};
569
570// Scaled permutation to dense assignment: zero fill plus one scatter of n coefficients.
571template <typename DstXprType, typename SrcXprType, typename Functor>
572struct Assignment<DstXprType, SrcXprType, Functor, ScaledPermutation2Dense> {
573 static EIGEN_DEVICE_FUNC void run(
574 DstXprType& dst, const SrcXprType& src,
575 const internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>&) {
576 if (dst.rows() != src.rows() || dst.cols() != src.cols()) dst.resize(src.rows(), src.cols());
577 dst.setZero();
578 for (Index k = 0; k < src.rows(); ++k) dst.coeffRef(src.indices().coeff(k), k) = src.scales().coeff(k);
579 }
580
581 static EIGEN_DEVICE_FUNC void run(
582 DstXprType& dst, const SrcXprType& src,
583 const internal::add_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>&) {
584 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
585 for (Index k = 0; k < src.rows(); ++k) dst.coeffRef(src.indices().coeff(k), k) += src.scales().coeff(k);
586 }
587
588 static EIGEN_DEVICE_FUNC void run(
589 DstXprType& dst, const SrcXprType& src,
590 const internal::sub_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>&) {
591 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
592 for (Index k = 0; k < src.rows(); ++k) dst.coeffRef(src.indices().coeff(k), k) -= src.scales().coeff(k);
593 }
594};
595
596/***************************************************************************
597 * Products with a dense matrix: rows (S * X) or columns (X * S) are scaled and permuted, O(n m).
598 * evalTo reuses the dense permutation kernel, which handles X aliasing dst, and scales in place afterwards;
599 * the accumulating form works on the nested (evaluated once) operand.
600 * scaleAndAddTo evaluates dst += alpha * (lhs * rhs) with alpha a left factor of the product. Scalar
601 * multiplication need not commute, so both kernels keep that operand order: S * X regroups it as
602 * (alpha * v_c) * X(c, j) by associativity; X * S keeps alpha * (X(i, tau(c)) * v_c), as folding alpha into
603 * v_c would move it past the dense coefficient.
604 ***************************************************************************/
605
606template <typename Lhs, typename Rhs, int ProductTag>
607struct generic_product_impl<Lhs, Rhs, ScaledPermutationShape, DenseShape, ProductTag>
608 : generic_product_impl_base<Lhs, Rhs,
609 generic_product_impl<Lhs, Rhs, ScaledPermutationShape, DenseShape, ProductTag>> {
610 using Scalar = typename Product<Lhs, Rhs>::Scalar;
611
612 template <typename Dest>
613 static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
614 permutation_matrix_product<Rhs, OnTheLeft, false, DenseShape>::run(dst, lhs.permutation(), rhs);
615 for (Index k = 0; k < lhs.rows(); ++k) {
616 auto row = dst.row(lhs.indices().coeff(k));
617 row = lhs.scales().coeff(k) * row;
618 }
619 }
620
621 template <typename Dest>
622 static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
623 typename nested_eval<Rhs, 1>::type rhsNested(rhs);
624 for (Index k = 0; k < lhs.rows(); ++k)
625 dst.row(lhs.indices().coeff(k)) += (alpha * lhs.scales().coeff(k)) * rhsNested.row(k);
626 }
627};
628
629template <typename Lhs, typename Rhs, int ProductTag>
630struct generic_product_impl<Lhs, Rhs, DenseShape, ScaledPermutationShape, ProductTag>
631 : generic_product_impl_base<Lhs, Rhs,
632 generic_product_impl<Lhs, Rhs, DenseShape, ScaledPermutationShape, ProductTag>> {
633 using Scalar = typename Product<Lhs, Rhs>::Scalar;
634
635 template <typename Dest>
636 static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
637 permutation_matrix_product<Lhs, OnTheRight, false, DenseShape>::run(dst, rhs.permutation(), lhs);
638 for (Index k = 0; k < rhs.rows(); ++k) dst.col(k) *= rhs.scales().coeff(k);
639 }
640
641 template <typename Dest>
642 static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
643 typename nested_eval<Lhs, 1>::type lhsNested(lhs);
644 for (Index k = 0; k < rhs.rows(); ++k)
645 dst.col(k) += alpha * (lhsNested.col(rhs.indices().coeff(k)) * rhs.scales().coeff(k));
646 }
647};
648
649// A triangular or self-adjoint operand is evaluated into a plain matrix first, as toDenseMatrix() does.
650template <typename Lhs, typename Rhs, int ProductTag, bool ViewOnTheRight>
651struct scaled_permutation_view_product_impl;
652
653template <typename Lhs, typename Rhs, int ProductTag>
654struct scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true>
655 : generic_product_impl_base<Lhs, Rhs, scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true>> {
656 using Scalar = typename Product<Lhs, Rhs>::Scalar;
657 using DenseType = typename Rhs::DenseMatrixType;
658 using DenseImpl = generic_product_impl<Lhs, DenseType, ScaledPermutationShape, DenseShape, ProductTag>;
659
660 template <typename Dest>
661 static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
662 const DenseType dense(rhs);
663 DenseImpl::evalTo(dst, lhs, dense);
664 }
665 template <typename Dest>
666 static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
667 const DenseType dense(rhs);
668 DenseImpl::scaleAndAddTo(dst, lhs, dense, alpha);
669 }
670};
671
672template <typename Lhs, typename Rhs, int ProductTag>
673struct scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false>
674 : generic_product_impl_base<Lhs, Rhs, scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false>> {
675 using Scalar = typename Product<Lhs, Rhs>::Scalar;
676 using DenseType = typename Lhs::DenseMatrixType;
677 using DenseImpl = generic_product_impl<DenseType, Rhs, DenseShape, ScaledPermutationShape, ProductTag>;
678
679 template <typename Dest>
680 static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
681 const DenseType dense(lhs);
682 DenseImpl::evalTo(dst, dense, rhs);
683 }
684 template <typename Dest>
685 static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
686 const DenseType dense(lhs);
687 DenseImpl::scaleAndAddTo(dst, dense, rhs, alpha);
688 }
689};
690
691template <typename Lhs, typename Rhs, int ProductTag>
692struct generic_product_impl<Lhs, Rhs, ScaledPermutationShape, TriangularShape, ProductTag>
693 : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true> {};
694template <typename Lhs, typename Rhs, int ProductTag>
695struct generic_product_impl<Lhs, Rhs, ScaledPermutationShape, SelfAdjointShape, ProductTag>
696 : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true> {};
697template <typename Lhs, typename Rhs, int ProductTag>
698struct generic_product_impl<Lhs, Rhs, TriangularShape, ScaledPermutationShape, ProductTag>
699 : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false> {};
700template <typename Lhs, typename Rhs, int ProductTag>
701struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, ScaledPermutationShape, ProductTag>
702 : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false> {};
703
704} // namespace internal
705
706} // namespace Eigen
707
708#endif // EIGEN_SCALEDPERMUTATIONMATRIX_H
Derived & setZero()
Definition CwiseNullaryOp.h:521
Base class for diagonal matrices and expressions.
Definition DiagonalMatrix.h:34
const DiagonalVectorType & diagonal() const
Definition DiagonalMatrix.h:71
constexpr Index rows() const
Definition DiagonalMatrix.h:82
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Base class for permutations.
Definition PermutationMatrix.h:92
constexpr const IndicesType & indices() const
Definition PermutationMatrix.h:159
Index rows() const
Definition PermutationMatrix.h:133
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:203
Base class for scaled permutation matrices.
Definition ScaledPermutationMatrix.h:82
const PermutationType & permutation() const
Definition ScaledPermutationMatrix.h:117
PlainObject transpose() const
Definition ScaledPermutationMatrix.h:153
internal::scaled_permutation_product_result< Derived, OtherDerived, StorageIndex >::type operator*(const DiagonalBase< OtherDerived > &other) const
Definition ScaledPermutationMatrix.h:210
PlainObject adjoint() const
Definition ScaledPermutationMatrix.h:164
PlainObject operator*(const Scalar &alpha) const
Definition ScaledPermutationMatrix.h:298
friend PlainObject operator*(const InverseImpl< OtherDerived, PermutationStorage > &other, const ScaledPermutationBase &scaled)
Definition ScaledPermutationMatrix.h:271
const Product< Derived, OtherDerived, DefaultProduct > operator*(const TriangularBase< OtherDerived > &other) const
Definition ScaledPermutationMatrix.h:191
Scalar coeff(Index row, Index col) const
Definition ScaledPermutationMatrix.h:124
friend PlainObject operator*(const Scalar &alpha, const ScaledPermutationBase &scaled)
Definition ScaledPermutationMatrix.h:301
const ScalesType & scales() const
Definition ScaledPermutationMatrix.h:121
friend PlainObject operator*(const PermutationBase< OtherDerived > &other, const ScaledPermutationBase &scaled)
Definition ScaledPermutationMatrix.h:245
PlainObject inverse() const
Definition ScaledPermutationMatrix.h:142
constexpr Index rows() const
Definition ScaledPermutationMatrix.h:112
PlainObject operator*(const PermutationBase< OtherDerived > &other) const
Definition ScaledPermutationMatrix.h:232
Scalar determinant() const
Definition ScaledPermutationMatrix.h:171
constexpr const IndicesType & indices() const
Definition ScaledPermutationMatrix.h:119
friend internal::scaled_permutation_product_result< OtherDerived, Derived, StorageIndex >::type operator*(const DiagonalBase< OtherDerived > &other, const ScaledPermutationBase &scaled)
Definition ScaledPermutationMatrix.h:219
friend const Product< OtherDerived, Derived, DefaultProduct > operator*(const TriangularBase< OtherDerived > &other, const ScaledPermutationBase &scaled)
Definition ScaledPermutationMatrix.h:198
const Product< Derived, OtherDerived, DefaultProduct > operator*(const MatrixBase< OtherDerived > &other) const
Definition ScaledPermutationMatrix.h:176
friend const Product< OtherDerived, Derived, DefaultProduct > operator*(const MatrixBase< OtherDerived > &other, const ScaledPermutationBase &scaled)
Definition ScaledPermutationMatrix.h:184
internal::scaled_permutation_product_result< Derived, OtherDerived, StorageIndex >::type operator*(const ScaledPermutationBase< OtherDerived > &other) const
Definition ScaledPermutationMatrix.h:284
constexpr Index cols() const
Definition ScaledPermutationMatrix.h:114
PlainObject operator*(const InverseImpl< OtherDerived, PermutationStorage > &other) const
Definition ScaledPermutationMatrix.h:256
PlainObject operator-() const
Definition ScaledPermutationMatrix.h:306
DenseMatrixType toDenseMatrix() const
Definition ScaledPermutationMatrix.h:130
Scaled permutation matrix with its storage.
Definition ScaledPermutationMatrix.h:359
void resize(Index size)
Definition ScaledPermutationMatrix.h:433
ScaledPermutationMatrix(const DiagonalBase< OtherDerived > &diagonal)
Definition ScaledPermutationMatrix.h:401
internal::scaled_permutation_result< typenameDiagonalDerived::Scalar, PermutationDerived, DiagonalDerived, typenamePermutationDerived::StorageIndex >::type operator*(const PermutationBase< PermutationDerived > &permutation, const DiagonalBase< DiagonalDerived > &diagonal)
Definition ScaledPermutationMatrix.h:464
const PermutationType & permutation() const
Definition ScaledPermutationMatrix.h:420
ScaledPermutationMatrix(const ScaledPermutationBase< OtherDerived > &other)
Definition ScaledPermutationMatrix.h:408
const ScalesType & scales() const
Definition ScaledPermutationMatrix.h:428
constexpr const IndicesType & indices() const
Definition ScaledPermutationMatrix.h:424
ScaledPermutationMatrix(const PermutationBase< OtherDerived > &permutation)
Definition ScaledPermutationMatrix.h:396
ScaledPermutationMatrix(Index size)
Definition ScaledPermutationMatrix.h:376
constexpr IndicesType & indices()
Definition ScaledPermutationMatrix.h:426
internal::scaled_permutation_result< typenameDiagonalDerived::Scalar, PermutationDerived, DiagonalDerived, typenamePermutationDerived::StorageIndex >::type operator*(const DiagonalBase< DiagonalDerived > &diagonal, const PermutationBase< PermutationDerived > &permutation)
Definition ScaledPermutationMatrix.h:477
ScaledPermutationMatrix & operator=(const ScaledPermutationBase< OtherDerived > &other)
Definition ScaledPermutationMatrix.h:413
ScaledPermutationMatrix(const PermutationBase< PermutationDerived > &permutation, const DiagonalBase< DiagonalDerived > &diagonal)
Definition ScaledPermutationMatrix.h:380
void setIdentity()
Definition ScaledPermutationMatrix.h:439
ScalesType & scales()
Definition ScaledPermutationMatrix.h:430
internal::scaled_permutation_result< typenameDiagonalDerived::Scalar, PermutationType, DiagonalDerived, typenamePermutationType::StorageIndex >::type operator*(const InverseImpl< PermutationType, PermutationStorage > &inverse, const DiagonalBase< DiagonalDerived > &diagonal)
Definition ScaledPermutationMatrix.h:494
ScaledPermutationMatrix(const MatrixBase< IndicesDerived > &indices, const MatrixBase< ScalesDerived > &scales)
Definition ScaledPermutationMatrix.h:388
PermutationType & permutation()
Definition ScaledPermutationMatrix.h:422
internal::scaled_permutation_result< typenameDiagonalDerived::Scalar, PermutationType, DiagonalDerived, typenamePermutationType::StorageIndex >::type operator*(const DiagonalBase< DiagonalDerived > &diagonal, const InverseImpl< PermutationType, PermutationStorage > &inverse)
Definition ScaledPermutationMatrix.h:511
void setIdentity(Index size)
Definition ScaledPermutationMatrix.h:445
Base class for triangular part in a matrix.
Definition TriangularMatrix.h:68
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
constexpr Index size() const noexcept
Definition EigenBase.h:65
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44