1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_DIAGONALPRODUCT_H
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_DIAGONALPRODUCT_H
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, typename DiagonalType, int ProductOrder>
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : traits<MatrixType>
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename scalar_product_traits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar;
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum {
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ColsAtCompileTime = MatrixType::ColsAtCompileTime,
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    _StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    _ScalarAccessOnDiag =  !((int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheLeft)
307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                          ||(int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheRight)),
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    _SameTypes = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // FIXME currently we need same types, but in the future the next rule should be the one
337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    //_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    _Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    _LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit,//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  };
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, typename DiagonalType, int ProductOrder>
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass DiagonalProduct : internal::no_assignment_operator,
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                        public MatrixBase<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef MatrixBase<DiagonalProduct> Base;
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_DENSE_PUBLIC_INTERFACE(DiagonalProduct)
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline DiagonalProduct(const MatrixType& matrix, const DiagonalType& diagonal)
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_matrix(matrix), m_diagonal(diagonal)
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols()));
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STRONG_INLINE Index rows() const { return m_matrix.rows(); }
597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STRONG_INLINE Index cols() const { return m_matrix.cols(); }
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col);
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const
677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      enum {
697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        StorageOrder = int(MatrixType::Flags) & RowMajorBit ? RowMajor : ColMajor
707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      };
717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return coeff(int(StorageOrder)==ColMajor?idx:0,int(StorageOrder)==ColMajor?0:idx);
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<int LoadMode>
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      enum {
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        StorageOrder = Flags & RowMajorBit ? RowMajor : ColMajor
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      };
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col;
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return packet_impl<LoadMode>(row,col,indexInDiagonalVector,typename internal::conditional<
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath       ||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), internal::true_type, internal::false_type>::type());
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<int LoadMode>
877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STRONG_INLINE PacketScalar packet(Index idx) const
887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      enum {
907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        StorageOrder = int(MatrixType::Flags) & RowMajorBit ? RowMajor : ColMajor
917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      };
927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return packet<LoadMode>(int(StorageOrder)==ColMajor?idx:0,int(StorageOrder)==ColMajor?0:idx);
937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<int LoadMode>
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::true_type) const
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                     internal::pset1<PacketScalar>(m_diagonal.diagonal().coeff(id)));
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<int LoadMode>
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::false_type) const
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      enum {
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        DiagonalVectorPacketLoadMode = (LoadMode == Aligned && (((InnerSize%16) == 0) || (int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit)==AlignedBit) ? Aligned : Unaligned)
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      };
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                     m_diagonal.diagonal().template packet<DiagonalVectorPacketLoadMode>(id));
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typename MatrixType::Nested m_matrix;
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typename DiagonalType::Nested m_diagonal;
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the diagonal matrix product of \c *this by the diagonal matrix \a diagonal.
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived>
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename DiagonalDerived>
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathinline const DiagonalProduct<Derived, DiagonalDerived, OnTheRight>
1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezMatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &a_diagonal) const
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), a_diagonal.derived());
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_DIAGONALPRODUCT_H
131