Eigen  5.0.1
 
Loading...
Searching...
No Matches
DiagonalMatrix.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_DIAGONALMATRIX_H
13#define EIGEN_DIAGONALMATRIX_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
33template <typename Derived>
34class DiagonalBase : public EigenBase<Derived> {
35 public:
36 using DiagonalVectorType = typename internal::traits<Derived>::DiagonalVectorType;
37 using Scalar = typename DiagonalVectorType::Scalar;
38 using RealScalar = typename DiagonalVectorType::RealScalar;
39 using StorageKind = typename internal::traits<Derived>::StorageKind;
40 using StorageIndex = typename internal::traits<Derived>::StorageIndex;
41
42 enum {
43 RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
44 ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
45 MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
46 MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
47 SizeAtCompileTime = internal::size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime),
48 MaxSizeAtCompileTime = internal::size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime),
49 IsVectorAtCompileTime = 0,
51 };
52
53 using DenseMatrixType =
55 using DenseType = DenseMatrixType;
56 using PlainObject =
58
60 EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
62 EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast<Derived*>(this); }
63
68 EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); }
69
71 EIGEN_DEVICE_FUNC inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
73 EIGEN_DEVICE_FUNC inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
74
76 EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const {
77 eigen_assert(row >= 0 && col >= 0 && row < rows() && col < cols());
78 return row == col ? diagonal().coeff(row) : Scalar(0);
79 }
80
82 EIGEN_DEVICE_FUNC constexpr Index rows() const { return diagonal().size(); }
84 EIGEN_DEVICE_FUNC constexpr Index cols() const { return diagonal().size(); }
85
87 template <typename MatrixDerived>
89 const MatrixBase<MatrixDerived>& matrix) const {
90 return Product<Derived, MatrixDerived, LazyProduct>(derived(), matrix.derived());
91 }
92
93 template <typename OtherDerived>
94 using DiagonalProductReturnType = DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(
95 DiagonalVectorType, typename OtherDerived::DiagonalVectorType, internal::scalar_product_op)>;
96
98 template <typename OtherDerived>
99 EIGEN_DEVICE_FUNC const DiagonalProductReturnType<OtherDerived> operator*(
100 const DiagonalBase<OtherDerived>& other) const {
101 return diagonal().cwiseProduct(other.diagonal()).asDiagonal();
102 }
103
104 using DiagonalInverseReturnType =
106
108 EIGEN_DEVICE_FUNC inline const DiagonalInverseReturnType inverse() const {
109 return diagonal().cwiseInverse().asDiagonal();
110 }
111
112 using TransposeReturnType = DiagonalWrapper<const DiagonalVectorType>;
113
117 EIGEN_DEVICE_FUNC const TransposeReturnType transpose() const { return diagonal().asDiagonal(); }
118
119 using ConjugateReturnType = std::conditional_t<
120 NumTraits<Scalar>::IsComplex,
122 TransposeReturnType>;
123
127 EIGEN_DEVICE_FUNC const ConjugateReturnType conjugate() const { return diagonal().conjugate().asDiagonal(); }
128
129 using AdjointReturnType = ConjugateReturnType;
130
135 EIGEN_DEVICE_FUNC const AdjointReturnType adjoint() const { return conjugate(); }
136
137 using DiagonalScaleReturnType = DiagonalWrapper<const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(
138 DiagonalVectorType, Scalar, internal::scalar_product_op)>;
139
141 EIGEN_DEVICE_FUNC inline const DiagonalScaleReturnType operator*(const Scalar& scalar) const {
142 return (diagonal() * scalar).asDiagonal();
143 }
144
145 using ScaleDiagonalReturnType = DiagonalWrapper<const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(
146 Scalar, DiagonalVectorType, internal::scalar_product_op)>;
147
149 EIGEN_DEVICE_FUNC friend inline const ScaleDiagonalReturnType operator*(const Scalar& scalar,
150 const DiagonalBase& other) {
151 return (scalar * other.diagonal()).asDiagonal();
152 }
153
154 template <typename OtherDerived>
155 using DiagonalSumReturnType = DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(
156 DiagonalVectorType, typename OtherDerived::DiagonalVectorType, internal::scalar_sum_op)>;
157
159 template <typename OtherDerived>
160 EIGEN_DEVICE_FUNC inline const DiagonalSumReturnType<OtherDerived> operator+(
161 const DiagonalBase<OtherDerived>& other) const {
162 return (diagonal() + other.diagonal()).asDiagonal();
163 }
164
165 template <typename OtherDerived>
166 using DiagonalDifferenceReturnType = DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(
167 DiagonalVectorType, typename OtherDerived::DiagonalVectorType, internal::scalar_difference_op)>;
168
170 template <typename OtherDerived>
171 EIGEN_DEVICE_FUNC inline const DiagonalDifferenceReturnType<OtherDerived> operator-(
172 const DiagonalBase<OtherDerived>& other) const {
173 return (diagonal() - other.diagonal()).asDiagonal();
174 }
175
176 // Sums with a dense matrix are lazy: the diagonal is read through its index-based evaluator and no dense
177 // copy of it is formed, so `A + D` composes with the enclosing expression like `A + B` does.
178
180 template <typename OtherDerived>
181 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_sum_op)
182 operator+(const MatrixBase<OtherDerived>& lhs, const DiagonalBase & rhs) {
183 return EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_sum_op)(lhs.derived(), rhs.derived());
184 }
185
187 template <typename OtherDerived>
188 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_sum_op)
189 operator+(const DiagonalBase & lhs, const MatrixBase<OtherDerived>& rhs) {
190 return EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_sum_op)(lhs.derived(), rhs.derived());
191 }
192
194 template <typename OtherDerived>
195 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_difference_op)
196 operator-(const MatrixBase<OtherDerived>& lhs, const DiagonalBase & rhs) {
197 return EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_difference_op)(lhs.derived(),
198 rhs.derived());
199 }
200
202 template <typename OtherDerived>
203 EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_difference_op)
204 operator-(const DiagonalBase & lhs, const MatrixBase<OtherDerived>& rhs) {
205 return EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_difference_op)(lhs.derived(),
206 rhs.derived());
207 }
208};
209
222
223namespace internal {
224template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime>
225struct traits<DiagonalMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime>>
226 : traits<Matrix<Scalar_, SizeAtCompileTime, SizeAtCompileTime, 0, MaxSizeAtCompileTime, MaxSizeAtCompileTime>> {
227 using DiagonalVectorType = Matrix<Scalar_, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>;
228 using StorageKind = DiagonalShape;
229 enum { Flags = LvalueBit | NoPreferredStorageOrderBit | NestByRefBit };
230};
231} // namespace internal
232template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime>
233class DiagonalMatrix : public DiagonalBase<DiagonalMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime>> {
234 public:
235#ifndef EIGEN_PARSED_BY_DOXYGEN
236 using DiagonalVectorType = typename internal::traits<DiagonalMatrix>::DiagonalVectorType;
237 using Nested = const DiagonalMatrix&;
238 using Scalar = Scalar_;
239 using StorageKind = typename internal::traits<DiagonalMatrix>::StorageKind;
240 using StorageIndex = typename internal::traits<DiagonalMatrix>::StorageIndex;
241#endif
242
243 protected:
244 DiagonalVectorType m_diagonal;
245
246 public:
248 EIGEN_DEVICE_FUNC constexpr inline const DiagonalVectorType& diagonal() const { return m_diagonal; }
250 EIGEN_DEVICE_FUNC constexpr inline DiagonalVectorType& diagonal() { return m_diagonal; }
251
253 EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix() {}
254
255 /** Constructs a diagonal matrix with given dimension */
256 EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalMatrix(Index dim) : m_diagonal(dim) {}
257
259 EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x, y) {}
260
262 EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z)
263 : m_diagonal(x, y, z) {}
264
265 /** \brief Construct a diagonal matrix with fixed size from an arbitrary number of coefficients.
266 *
267 * \warning To construct a diagonal matrix of fixed size, the number of values passed to this
268 * constructor must match the fixed dimension of \c *this.
269 *
270 * \sa DiagonalMatrix(const Scalar&, const Scalar&)
271 * \sa DiagonalMatrix(const Scalar&, const Scalar&, const Scalar&)
272 */
273 template <typename... ArgTypes>
274 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE DiagonalMatrix(const Scalar& a0, const Scalar& a1, const Scalar& a2,
275 const ArgTypes&... args)
276 : m_diagonal(a0, a1, a2, args...) {}
277
279 * lists
280 */
281 EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE DiagonalMatrix(
282 const std::initializer_list<std::initializer_list<Scalar>>& list)
283 : m_diagonal(list) {}
286 EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalMatrix(DiagonalVectorType&& diag) : m_diagonal(std::move(diag)) {}
287
289 template <typename OtherDerived>
290 EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other)
291 : m_diagonal(other.diagonal()) {}
292
293#ifndef EIGEN_PARSED_BY_DOXYGEN
295 inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {}
296#endif
297
299 EIGEN_DEVICE_FUNC constexpr DiagonalMatrix(DiagonalMatrix&&) = default;
300
302 template <typename OtherDerived>
303 EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other)
304 : m_diagonal(other) {}
305
307 template <typename OtherDerived>
308 EIGEN_DEVICE_FUNC DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other) {
309 m_diagonal = other.diagonal();
310 return *this;
311 }
312
313#ifndef EIGEN_PARSED_BY_DOXYGEN
317 EIGEN_DEVICE_FUNC DiagonalMatrix& operator=(const DiagonalMatrix& other) {
318 m_diagonal = other.diagonal();
319 return *this;
320 }
321#endif
322
324 EIGEN_DEVICE_FUNC constexpr DiagonalMatrix& operator=(DiagonalMatrix&& other) noexcept(
325 DiagonalVectorType::MaxSizeAtCompileTime == Dynamic &&
326 std::is_nothrow_move_assignable<DiagonalVectorType>::value) {
327 EIGEN_IF_CONSTEXPR (DiagonalVectorType::MaxSizeAtCompileTime == Dynamic) {
328 m_diagonal = std::move(other.m_diagonal);
329 } else {
330 // Preserve the vectorized assignment path for inline storage.
331 m_diagonal = other.m_diagonal;
332 }
333 return *this;
334 }
335
336 using InitializeReturnType =
338
339 using ZeroInitializeReturnType =
341
343 EIGEN_DEVICE_FUNC static const ZeroInitializeReturnType Zero() { return DiagonalVectorType::Zero().asDiagonal(); }
345 EIGEN_DEVICE_FUNC static const ZeroInitializeReturnType Zero(Index size) {
346 return DiagonalVectorType::Zero(size).asDiagonal();
347 }
348
349 EIGEN_DEVICE_FUNC static const InitializeReturnType Identity() { return DiagonalVectorType::Ones().asDiagonal(); }
351 EIGEN_DEVICE_FUNC static const InitializeReturnType Identity(Index size) {
352 return DiagonalVectorType::Ones(size).asDiagonal();
353 }
354
356 EIGEN_DEVICE_FUNC inline void resize(Index size) { m_diagonal.resize(size); }
358 EIGEN_DEVICE_FUNC inline void setZero() { m_diagonal.setZero(); }
360 EIGEN_DEVICE_FUNC inline void setZero(Index size) { m_diagonal.setZero(size); }
362 EIGEN_DEVICE_FUNC inline void setIdentity() { m_diagonal.setOnes(); }
364 EIGEN_DEVICE_FUNC inline void setIdentity(Index size) { m_diagonal.setOnes(size); }
365};
366
380
381namespace internal {
382template <typename DiagonalVectorType_>
383struct traits<DiagonalWrapper<DiagonalVectorType_>> {
384 using DiagonalVectorType = DiagonalVectorType_;
385 using Scalar = typename DiagonalVectorType::Scalar;
386 using StorageIndex = typename DiagonalVectorType::StorageIndex;
387 using StorageKind = DiagonalShape;
388 using XprKind = typename traits<DiagonalVectorType>::XprKind;
389 enum {
390 RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
391 ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
392 MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
393 MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
394 Flags = (traits<DiagonalVectorType>::Flags & LvalueBit) | NoPreferredStorageOrderBit
395 };
396};
397} // namespace internal
398
399template <typename DiagonalVectorType_>
400class DiagonalWrapper : public DiagonalBase<DiagonalWrapper<DiagonalVectorType_>>, internal::no_assignment_operator {
401 public:
402#ifndef EIGEN_PARSED_BY_DOXYGEN
403 using DiagonalVectorType = DiagonalVectorType_;
404 using Nested = DiagonalWrapper;
405#endif
406
408 EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalWrapper(DiagonalVectorType& a_diagonal)
409 : m_diagonal(a_diagonal) {}
410
412 EIGEN_DEVICE_FUNC constexpr const DiagonalVectorType& diagonal() const { return m_diagonal; }
413
414 protected:
415 typename DiagonalVectorType::Nested m_diagonal;
416};
417
427template <typename Derived>
428EIGEN_DEVICE_FUNC constexpr const DiagonalWrapper<const Derived> MatrixBase<Derived>::asDiagonal() const {
429 return DiagonalWrapper<const Derived>(derived());
430}
431
440template <typename Derived>
441bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const {
442 if (cols() != rows()) return false;
443 RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
444 for (Index j = 0; j < cols(); ++j) {
445 RealScalar absOnDiagonal = numext::abs(coeff(j, j));
446 if (absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
447 }
448 for (Index j = 0; j < cols(); ++j)
449 for (Index i = 0; i < j; ++i) {
450 if (!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
451 if (!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
452 }
453 return true;
454}
455
463
465template <typename Derived>
466template <int DiagIndex_>
468 using DiagType = Diagonal<Derived, DiagIndex_>;
469 using ReturnType = DiagonalWrapper<DiagType>;
470 DiagType diag(this->derived());
471 return ReturnType(diag);
472}
473
475template <typename Derived>
476template <int DiagIndex_>
478 const {
480 using ReturnType = DiagonalWrapper<DiagType>;
481 DiagType diag(this->derived());
482 return ReturnType(diag);
483}
484
486template <typename Derived>
488 Index index) {
489 using DiagType = Diagonal<Derived, DynamicIndex>;
490 using ReturnType = DiagonalWrapper<DiagType>;
491 DiagType diag(this->derived(), index);
492 return ReturnType(diag);
493}
494
496template <typename Derived>
498 Index index) const {
500 using ReturnType = DiagonalWrapper<DiagType>;
501 DiagType diag(this->derived(), index);
502 return ReturnType(diag);
503}
504
505namespace internal {
506
507template <>
508struct storage_kind_to_shape<DiagonalShape> {
509 using Shape = DiagonalShape;
510};
511
517template <typename XprType>
518struct diagonal_matrix_evaluator : evaluator_base<XprType> {
519 using DiagonalVectorType = typename XprType::DiagonalVectorType;
520 using Scalar = typename XprType::Scalar;
521 using CoeffReturnType = Scalar;
522
523 static constexpr int CoeffReadCost =
524 int(evaluator<DiagonalVectorType>::CoeffReadCost) + int(NumTraits<Scalar>::AddCost);
525 static constexpr unsigned int Flags = 0;
526 static constexpr int Alignment = 0;
527
528 EIGEN_DEVICE_FUNC explicit diagonal_matrix_evaluator(const XprType& xpr) : m_diagonal(xpr.diagonal()) {
529 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
530 }
531
532 EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const { return row == col ? m_diagonal.coeff(row) : Scalar(0); }
533
534 // Linear access is requested only for vector-shaped operands (inner products), i.e. a 1x1 diagonal.
535 EIGEN_DEVICE_FUNC Scalar coeff(Index index) const {
536 eigen_assert(index == 0);
537 return m_diagonal.coeff(index);
538 }
539
540 protected:
541 evaluator<DiagonalVectorType> m_diagonal;
542};
543
544template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime>
545struct evaluator<DiagonalMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime>>
546 : diagonal_matrix_evaluator<DiagonalMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime>> {
547 using XprType = DiagonalMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime>;
548 EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : diagonal_matrix_evaluator<XprType>(xpr) {}
549};
550
551template <typename DiagonalVectorType_>
552struct evaluator<DiagonalWrapper<DiagonalVectorType_>>
553 : diagonal_matrix_evaluator<DiagonalWrapper<DiagonalVectorType_>> {
554 using XprType = DiagonalWrapper<DiagonalVectorType_>;
555 EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : diagonal_matrix_evaluator<XprType>(xpr) {}
556};
557
558struct Diagonal2Dense {};
559
560template <>
561struct AssignmentKind<DenseShape, DiagonalShape> {
562 using Kind = Diagonal2Dense;
563};
564
565// Diagonal matrix to Dense assignment
566template <typename DstXprType, typename SrcXprType, typename Functor>
567struct Assignment<DstXprType, SrcXprType, Functor, Diagonal2Dense> {
568 static EIGEN_DEVICE_FUNC void run(
569 DstXprType& dst, const SrcXprType& src,
570 const internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
571 Index dstRows = src.rows();
572 Index dstCols = src.cols();
573 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
574
575 dst.setZero();
576 dst.diagonal() = src.diagonal();
577 }
578
579 static EIGEN_DEVICE_FUNC void run(
580 DstXprType& dst, const SrcXprType& src,
581 const internal::add_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
582 dst.diagonal() += src.diagonal();
583 }
584
585 static EIGEN_DEVICE_FUNC void run(
586 DstXprType& dst, const SrcXprType& src,
587 const internal::sub_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
588 dst.diagonal() -= src.diagonal();
589 }
590};
591
592/***************************************************************************
593 * Dense ?= lhs +/- rhs, where one operand is dense and the other has one structural nonzero in each column of the
594 * destination: the lazy CwiseBinaryOp keeps its type, but a direct assignment writes each column as two vectorized
595 * segments of the dense operand around that nonzero, instead of evaluating the sum coefficient by coefficient
596 * without packets.
597 ***************************************************************************/
598
599// The three functors such an assignment can carry, and the sign with which they add the source.
600template <typename Functor>
601struct additive_assign_sign : std::integral_constant<int, 0> {};
602template <typename Scalar>
603struct additive_assign_sign<assign_op<Scalar, Scalar>> : std::integral_constant<int, 1> {};
604template <typename Scalar>
605struct additive_assign_sign<add_assign_op<Scalar, Scalar>> : std::integral_constant<int, 1> {};
606template <typename Scalar>
607struct additive_assign_sign<sub_assign_op<Scalar, Scalar>> : std::integral_constant<int, -1> {};
608
609template <typename Functor>
610struct is_plain_assign : std::false_type {};
611template <typename Scalar>
612struct is_plain_assign<assign_op<Scalar, Scalar>> : std::true_type {};
613
614template <typename BinaryOp>
615struct is_additive_binary_op : std::false_type {};
616template <typename Scalar>
617struct is_additive_binary_op<scalar_sum_op<Scalar, Scalar>> : std::true_type {};
618template <typename Scalar>
619struct is_additive_binary_op<scalar_difference_op<Scalar, Scalar>> : std::true_type {};
620
621template <typename T>
622struct is_dense_shape : std::is_same<typename evaluator_traits<T>::Shape, DenseShape> {};
623template <typename T>
624struct is_diagonal_shape : std::is_same<typename evaluator_traits<T>::Shape, DiagonalShape> {};
625template <typename T>
626struct is_default_product : std::false_type {};
627template <typename Lhs, typename Rhs>
628struct is_default_product<Product<Lhs, Rhs, DefaultProduct>> : std::true_type {};
629// Specialized in PermutationMatrix.h: a permutation's dense expression counts as the structured operand of a sum
630// with a diagonal matrix, not as its dense one.
631template <typename T>
632struct is_permutation_dense_xpr : std::false_type {};
633
634template <typename BinaryOp>
635struct is_difference_op : std::false_type {};
636template <typename Scalar>
637struct is_difference_op<scalar_difference_op<Scalar, Scalar>> : std::true_type {};
638
639// The block pass below also forms dst ?= +/-dense at the structured coefficients, then overwrites them. For signed
640// integers that intermediate can overflow where the coefficient-wise dst ?= op(lhs, rhs) does not (-INT_MIN, or
641// INT_MIN - 1 in INT_MIN - (1 - 1)), so they take the fast path only when the block pass is a copy.
642template <typename Scalar, typename Functor, bool NegateDense>
643struct dense_block_pass_cannot_overflow
644 : bool_constant<!(NumTraits<Scalar>::IsInteger && std::numeric_limits<Scalar>::is_signed) ||
645 (is_plain_assign<Functor>::value && !NegateDense)> {};
646
647// Mixed scalar types and functors other than =, += and -= stay on the generic coefficient-wise path.
648template <typename Dst, typename DenseXpr, typename DiagonalXpr, typename Functor, bool NegateDense>
649struct dense_diagonal_sum_fast_path
650 : bool_constant<is_dense_shape<DenseXpr>::value && !is_permutation_dense_xpr<DenseXpr>::value &&
651 is_diagonal_shape<DiagonalXpr>::value && additive_assign_sign<Functor>::value != 0 &&
652 std::is_same<typename Dst::Scalar, typename DenseXpr::Scalar>::value &&
653 std::is_same<typename DenseXpr::Scalar, typename DiagonalXpr::Scalar>::value &&
654 dense_block_pass_cannot_overflow<typename Dst::Scalar, Functor, NegateDense>::value> {};
655
656// block ?= +/-dense block as one of =, = -, += and -=, chosen at compile time: bool has no negation or subtraction,
657// so no other operator may be instantiated.
658template <bool Assign, int Sign>
659struct dense_block_update;
660template <>
661struct dense_block_update<true, 1> {
662 template <typename Block, typename DenseBlock>
663 EIGEN_DEVICE_FUNC static void run(Block&& block, const DenseBlock& dense) {
664 block = dense;
665 }
666};
667template <>
668struct dense_block_update<true, -1> {
669 template <typename Block, typename DenseBlock>
670 EIGEN_DEVICE_FUNC static void run(Block&& block, const DenseBlock& dense) {
671 block = -dense;
672 }
673};
674template <>
675struct dense_block_update<false, 1> {
676 template <typename Block, typename DenseBlock>
677 EIGEN_DEVICE_FUNC static void run(Block&& block, const DenseBlock& dense) {
678 block += dense;
679 }
680};
681template <>
682struct dense_block_update<false, -1> {
683 template <typename Block, typename DenseBlock>
684 EIGEN_DEVICE_FUNC static void run(Block&& block, const DenseBlock& dense) {
685 block -= dense;
686 }
687};
688
689// A diagonal as the structured operand: its nonzero in column k is at row k.
690template <typename DiagonalXpr>
691struct diagonal_column_nonzeros {
692 using Scalar = typename DiagonalXpr::Scalar;
693 EIGEN_DEVICE_FUNC explicit diagonal_column_nonzeros(const DiagonalXpr& diagonal) : m_diagonal(diagonal) {}
694 EIGEN_DEVICE_FUNC Index row(Index k) const { return k; }
695 EIGEN_DEVICE_FUNC Scalar value(Index k) const { return m_diagonal.coeff(k, k); }
696 evaluator<DiagonalXpr> m_diagonal;
697};
698
699// Column-major views of a row-major destination and its dense operand; a structured operand is only paired with a
700// destination along whose columns it has one nonzero each, so after transposition it needs no view of its own.
701template <bool Transpose>
702struct column_major_view {
703 template <typename Xpr>
704 EIGEN_DEVICE_FUNC static Xpr& run(Xpr& xpr) {
705 return xpr;
706 }
707};
708template <>
709struct column_major_view<true> {
710 template <typename Xpr>
711 EIGEN_DEVICE_FUNC static auto run(Xpr& xpr) {
712 return xpr.transpose();
713 }
714};
715
716// dst ?= op(lhs, rhs) in blocks of columns. For each column k of a block, with the structured operand's nonzero at
717// row r, v(k) = func(dst(r, k), op(lhs(r, k), rhs(r, k))) is formed from coefficients read before the block is
718// written; then block ?= +/-dense block, and dst(r, k) = v(k). So each structured coefficient gets the
719// coefficient-wise value and grouping, also when the diagonal or the dense operand is read from dst; structural
720// zeros are not added.
721template <bool DenseOnLeft>
722struct dense_structured_sum_assignment {
723 template <typename Dst, typename DenseXpr, typename Structured, typename BinaryOp, typename Functor>
724 EIGEN_DEVICE_FUNC static void run(Dst& dst, const DenseXpr& dense, const Structured& structured, const BinaryOp& op,
725 const Functor& func) {
726 using Scalar = typename Dst::Scalar;
727 constexpr bool kNegateDense = !DenseOnLeft && std::is_same<BinaryOp, scalar_difference_op<Scalar, Scalar>>::value;
728 constexpr int kSign = additive_assign_sign<Functor>::value * (kNegateDense ? -1 : 1);
729 constexpr Index kBlockColumns = 32;
730 using Update = dense_block_update<is_plain_assign<Functor>::value, kSign>;
731 const evaluator<DenseXpr> denseEval(dense);
732 Scalar values[kBlockColumns];
733 for (Index j = 0; j < dst.cols(); j += kBlockColumns) {
734 const Index columns = numext::mini(Index(kBlockColumns), dst.cols() - j);
735 for (Index k = 0; k < columns; ++k) {
736 const Index r = structured.row(j + k);
737 const Scalar s = structured.value(j + k);
738 const Scalar d = denseEval.coeff(r, j + k);
739 EIGEN_IF_CONSTEXPR (!is_plain_assign<Functor>::value) {
740 values[k] = dst.coeff(r, j + k);
741 }
742 func.assignCoeff(values[k], DenseOnLeft ? op(d, s) : op(s, d));
743 }
744 Update::run(dst.middleCols(j, columns), dense.middleCols(j, columns));
745 for (Index k = 0; k < columns; ++k) {
746 dst.coeffRef(structured.row(j + k), j + k) = values[k];
747 }
748 }
749 }
750
751 template <typename Dst, typename SrcXprType, typename DenseXpr, typename Structured, typename Functor>
752 EIGEN_DEVICE_FUNC static void assign(Dst& dst, const SrcXprType& src, const DenseXpr& denseXpr,
753 const Structured& structured, const Functor& func) {
754 // Evaluates a product operand once, before dst is resized or written.
755 const typename nested_eval<DenseXpr, 1>::type dense(denseXpr);
756 resize_if_allowed(dst, src, func);
757 auto&& dstView = column_major_view<bool(Dst::IsRowMajor)>::run(dst);
758 run(dstView, column_major_view<bool(Dst::IsRowMajor)>::run(dense), structured, src.functor(), func);
759 }
760};
761
762template <typename DstXprType, typename BinaryOp, typename Lhs, typename Rhs, typename Functor>
763struct Assignment<DstXprType, CwiseBinaryOp<BinaryOp, const Lhs, const Rhs>, Functor, Dense2Dense,
764 std::enable_if_t<is_additive_binary_op<BinaryOp>::value &&
765 dense_diagonal_sum_fast_path<DstXprType, Lhs, Rhs, Functor, false>::value>> {
766 using SrcXprType = CwiseBinaryOp<BinaryOp, const Lhs, const Rhs>;
767 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) {
768 dense_structured_sum_assignment<true>::assign(dst, src, src.lhs(), diagonal_column_nonzeros<Rhs>(src.rhs()), func);
769 }
770};
771
772// A dense product on the right is left to the "xpr + product" rule above.
773template <typename DstXprType, typename BinaryOp, typename Lhs, typename Rhs, typename Functor>
774struct Assignment<DstXprType, CwiseBinaryOp<BinaryOp, const Lhs, const Rhs>, Functor, Dense2Dense,
775 std::enable_if_t<is_additive_binary_op<BinaryOp>::value &&
776 dense_diagonal_sum_fast_path<DstXprType, Rhs, Lhs, Functor,
777 is_difference_op<BinaryOp>::value>::value &&
778 !is_default_product<Rhs>::value>> {
779 using SrcXprType = CwiseBinaryOp<BinaryOp, const Lhs, const Rhs>;
780 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) {
781 dense_structured_sum_assignment<false>::assign(dst, src, src.rhs(), diagonal_column_nonzeros<Lhs>(src.lhs()), func);
782 }
783};
784
785} // namespace internal
786
787} // end namespace Eigen
788
789#endif // EIGEN_DIAGONALMATRIX_H
Base class for diagonal matrices and expressions.
Definition DiagonalMatrix.h:34
const AdjointReturnType adjoint() const
Definition DiagonalMatrix.h:135
const Product< Derived, MatrixDerived, LazyProduct > operator*(const MatrixBase< MatrixDerived > &matrix) const
Definition DiagonalMatrix.h:88
friend const ScaleDiagonalReturnType operator*(const Scalar &scalar, const DiagonalBase &other)
Definition DiagonalMatrix.h:149
DiagonalVectorType & diagonal()
Definition DiagonalMatrix.h:73
const Derived & derived() const
Definition DiagonalMatrix.h:60
DenseMatrixType toDenseMatrix() const
Definition DiagonalMatrix.h:68
const ConjugateReturnType conjugate() const
Definition DiagonalMatrix.h:127
Scalar coeff(Index row, Index col) const
Definition DiagonalMatrix.h:76
const DiagonalInverseReturnType inverse() const
Definition DiagonalMatrix.h:108
Derived & derived()
Definition DiagonalMatrix.h:62
const DiagonalProductReturnType< OtherDerived > operator*(const DiagonalBase< OtherDerived > &other) const
Definition DiagonalMatrix.h:99
constexpr Index cols() const
Definition DiagonalMatrix.h:84
const DiagonalVectorType & diagonal() const
Definition DiagonalMatrix.h:71
const DiagonalScaleReturnType operator*(const Scalar &scalar) const
Definition DiagonalMatrix.h:141
const DiagonalSumReturnType< OtherDerived > operator+(const DiagonalBase< OtherDerived > &other) const
Definition DiagonalMatrix.h:160
const TransposeReturnType transpose() const
Definition DiagonalMatrix.h:117
const DiagonalDifferenceReturnType< OtherDerived > operator-(const DiagonalBase< OtherDerived > &other) const
Definition DiagonalMatrix.h:171
constexpr Index rows() const
Definition DiagonalMatrix.h:82
Represents a diagonal matrix with its storage.
Definition DiagonalMatrix.h:233
DiagonalMatrix & operator=(const DiagonalBase< OtherDerived > &other)
Definition DiagonalMatrix.h:308
static const InitializeReturnType Identity(Index size)
Definition DiagonalMatrix.h:351
static const ZeroInitializeReturnType Zero(Index size)
Definition DiagonalMatrix.h:345
constexpr DiagonalMatrix(Index dim)
Definition DiagonalMatrix.h:256
DiagonalMatrix(const std::initializer_list< std::initializer_list< Scalar > > &list)
Constructs a DiagonalMatrix and initializes it by elements given by an initializer list of initialize...
Definition DiagonalMatrix.h:281
constexpr DiagonalMatrix(const Scalar &a0, const Scalar &a1, const Scalar &a2, const ArgTypes &... args)
Construct a diagonal matrix with fixed size from an arbitrary number of coefficients.
Definition DiagonalMatrix.h:274
constexpr DiagonalMatrix & operator=(DiagonalMatrix &&other) noexcept(DiagonalVectorType::MaxSizeAtCompileTime==Dynamic &&std::is_nothrow_move_assignable< DiagonalVectorType >::value)
Definition DiagonalMatrix.h:324
constexpr DiagonalMatrix(const Scalar &x, const Scalar &y, const Scalar &z)
Definition DiagonalMatrix.h:262
constexpr DiagonalMatrix(DiagonalMatrix &&)=default
static const InitializeReturnType Identity()
Definition DiagonalMatrix.h:349
constexpr DiagonalMatrix()
Definition DiagonalMatrix.h:253
void setIdentity(Index size)
Definition DiagonalMatrix.h:364
void setZero()
Definition DiagonalMatrix.h:358
void setIdentity()
Definition DiagonalMatrix.h:362
constexpr const DiagonalVectorType & diagonal() const
Definition DiagonalMatrix.h:248
void setZero(Index size)
Definition DiagonalMatrix.h:360
constexpr DiagonalMatrix(const DiagonalBase< OtherDerived > &other)
Definition DiagonalMatrix.h:290
constexpr DiagonalMatrix(const MatrixBase< OtherDerived > &other)
Definition DiagonalMatrix.h:303
void resize(Index size)
Definition DiagonalMatrix.h:356
static const ZeroInitializeReturnType Zero()
Definition DiagonalMatrix.h:343
constexpr DiagonalMatrix(const Scalar &x, const Scalar &y)
Definition DiagonalMatrix.h:259
constexpr DiagonalMatrix(DiagonalVectorType &&diag)
Constructs a DiagonalMatrix from an r-value diagonal vector type.
Definition DiagonalMatrix.h:286
constexpr DiagonalVectorType & diagonal()
Definition DiagonalMatrix.h:250
Expression of a diagonal matrix.
Definition DiagonalMatrix.h:400
constexpr DiagonalWrapper(DiagonalVectorType &a_diagonal)
Definition DiagonalMatrix.h:408
constexpr const DiagonalVectorType & diagonal() const
Definition DiagonalMatrix.h:412
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition Diagonal.h:78
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
constexpr DiagonalWrapper< Diagonal< Derived, DiagIndex_ > > diagonalView()
Definition DiagonalMatrix.h:467
bool isDiagonal(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition DiagonalMatrix.h:441
constexpr const DiagonalWrapper< const Derived > asDiagonal() const
Definition DiagonalMatrix.h:428
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:203
constexpr unsigned int NoPreferredStorageOrderBit
Definition Constants.h:183
constexpr unsigned int LvalueBit
Definition Constants.h:149
Definition EigenBase.h:34
constexpr Index size() const noexcept
Definition EigenBase.h:65
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44