Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / extern / Eigen2 / Eigen / src / Core / DiagonalProduct.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra. Eigen itself is part of the KDE project.
3 //
4 // Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6 //
7 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25
26 #ifndef EIGEN_DIAGONALPRODUCT_H
27 #define EIGEN_DIAGONALPRODUCT_H
28
29 /** \internal Specialization of ei_nested for DiagonalMatrix.
30  *  Unlike ei_nested, if the argument is a DiagonalMatrix and if it must be evaluated,
31  *  then it evaluated to a DiagonalMatrix having its own argument evaluated.
32  */
33 template<typename T, int N> struct ei_nested_diagonal : ei_nested<T,N> {};
34 template<typename T, int N> struct ei_nested_diagonal<DiagonalMatrix<T>,N >
35  : ei_nested<DiagonalMatrix<T>, N, DiagonalMatrix<NestByValue<typename ei_plain_matrix_type<T>::type> > >
36 {};
37
38 // specialization of ProductReturnType
39 template<typename Lhs, typename Rhs>
40 struct ProductReturnType<Lhs,Rhs,DiagonalProduct>
41 {
42   typedef typename ei_nested_diagonal<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
43   typedef typename ei_nested_diagonal<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
44
45   typedef Product<LhsNested, RhsNested, DiagonalProduct> Type;
46 };
47
48 template<typename LhsNested, typename RhsNested>
49 struct ei_traits<Product<LhsNested, RhsNested, DiagonalProduct> >
50 {
51   // clean the nested types:
52   typedef typename ei_cleantype<LhsNested>::type _LhsNested;
53   typedef typename ei_cleantype<RhsNested>::type _RhsNested;
54   typedef typename _LhsNested::Scalar Scalar;
55
56   enum {
57     LhsFlags = _LhsNested::Flags,
58     RhsFlags = _RhsNested::Flags,
59     RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
60     ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
61     MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
62     MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
63
64     LhsIsDiagonal = (_LhsNested::Flags&Diagonal)==Diagonal,
65     RhsIsDiagonal = (_RhsNested::Flags&Diagonal)==Diagonal,
66
67     CanVectorizeRhs =  (!RhsIsDiagonal) && (RhsFlags & RowMajorBit) && (RhsFlags & PacketAccessBit)
68                      && (ColsAtCompileTime % ei_packet_traits<Scalar>::size == 0),
69
70     CanVectorizeLhs =  (!LhsIsDiagonal) && (!(LhsFlags & RowMajorBit)) && (LhsFlags & PacketAccessBit)
71                      && (RowsAtCompileTime % ei_packet_traits<Scalar>::size == 0),
72
73     RemovedBits = ~((RhsFlags & RowMajorBit) && (!CanVectorizeLhs) ? 0 : RowMajorBit),
74
75     Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
76           | (((CanVectorizeLhs&&RhsIsDiagonal) || (CanVectorizeRhs&&LhsIsDiagonal)) ? PacketAccessBit : 0),
77
78     CoeffReadCost = NumTraits<Scalar>::MulCost + _LhsNested::CoeffReadCost + _RhsNested::CoeffReadCost
79   };
80 };
81
82 template<typename LhsNested, typename RhsNested> class Product<LhsNested, RhsNested, DiagonalProduct> : ei_no_assignment_operator,
83   public MatrixBase<Product<LhsNested, RhsNested, DiagonalProduct> >
84 {
85     typedef typename ei_traits<Product>::_LhsNested _LhsNested;
86     typedef typename ei_traits<Product>::_RhsNested _RhsNested;
87
88     enum {
89       RhsIsDiagonal = (_RhsNested::Flags&Diagonal)==Diagonal
90     };
91
92   public:
93
94     EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
95
96     template<typename Lhs, typename Rhs>
97     inline Product(const Lhs& lhs, const Rhs& rhs)
98       : m_lhs(lhs), m_rhs(rhs)
99     {
100       ei_assert(lhs.cols() == rhs.rows());
101     }
102
103     inline int rows() const { return m_lhs.rows(); }
104     inline int cols() const { return m_rhs.cols(); }
105
106     const Scalar coeff(int row, int col) const
107     {
108       const int unique = RhsIsDiagonal ? col : row;
109       return m_lhs.coeff(row, unique) * m_rhs.coeff(unique, col);
110     }
111
112     template<int LoadMode>
113     const PacketScalar packet(int row, int col) const
114     {
115       if (RhsIsDiagonal)
116       {
117         return ei_pmul(m_lhs.template packet<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col)));
118       }
119       else
120       {
121         return ei_pmul(ei_pset1(m_lhs.coeff(row, row)), m_rhs.template packet<LoadMode>(row, col));
122       }
123     }
124
125   protected:
126     const LhsNested m_lhs;
127     const RhsNested m_rhs;
128 };
129
130 #endif // EIGEN_DIAGONALPRODUCT_H