Teh first one
[mldemos:kalians-mldemos.git] / _AlgorithmsPlugins / KPCA / Eigen / src / Core / CwiseBinaryOp.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.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_CWISE_BINARY_OP_H
27 #define EIGEN_CWISE_BINARY_OP_H
28
29 /** \class CwiseBinaryOp
30   * \ingroup Core_Module
31   *
32   * \brief Generic expression where a coefficient-wise binary operator is applied to two expressions
33   *
34   * \param BinaryOp template functor implementing the operator
35   * \param Lhs the type of the left-hand side
36   * \param Rhs the type of the right-hand side
37   *
38   * This class represents an expression  where a coefficient-wise binary operator is applied to two expressions.
39   * It is the return type of binary operators, by which we mean only those binary operators where
40   * both the left-hand side and the right-hand side are Eigen expressions.
41   * For example, the return type of matrix1+matrix2 is a CwiseBinaryOp.
42   *
43   * Most of the time, this is the only way that it is used, so you typically don't have to name
44   * CwiseBinaryOp types explicitly.
45   *
46   * \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp
47   */
48
49 namespace internal {
50 template<typename BinaryOp, typename Lhs, typename Rhs>
51 struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
52 {
53   // we must not inherit from traits<Lhs> since it has
54   // the potential to cause problems with MSVC
55   typedef typename remove_all<Lhs>::type Ancestor;
56   typedef typename traits<Ancestor>::XprKind XprKind;
57   enum {
58     RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime,
59     ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime,
60     MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime,
61     MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime
62   };
63
64   // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor),
65   // we still want to handle the case when the result type is different.
66   typedef typename result_of<
67                      BinaryOp(
68                        typename Lhs::Scalar,
69                        typename Rhs::Scalar
70                      )
71                    >::type Scalar;
72   typedef typename promote_storage_type<typename traits<Lhs>::StorageKind,
73                                            typename traits<Rhs>::StorageKind>::ret StorageKind;
74   typedef typename promote_index_type<typename traits<Lhs>::Index,
75                                          typename traits<Rhs>::Index>::type Index;
76   typedef typename Lhs::Nested LhsNested;
77   typedef typename Rhs::Nested RhsNested;
78   typedef typename remove_reference<LhsNested>::type _LhsNested;
79   typedef typename remove_reference<RhsNested>::type _RhsNested;
80   enum {
81     LhsCoeffReadCost = _LhsNested::CoeffReadCost,
82     RhsCoeffReadCost = _RhsNested::CoeffReadCost,
83     LhsFlags = _LhsNested::Flags,
84     RhsFlags = _RhsNested::Flags,
85     SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value,
86     StorageOrdersAgree = (int(Lhs::Flags)&RowMajorBit)==(int(Rhs::Flags)&RowMajorBit),
87     Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
88         HereditaryBits
89       | (int(LhsFlags) & int(RhsFlags) &
90            ( AlignedBit
91            | (StorageOrdersAgree ? LinearAccessBit : 0)
92            | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
93            )
94         )
95      ),
96     Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
97     CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost
98   };
99 };
100 } // end namespace internal
101
102 // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
103 // that would take two operands of different types. If there were such an example, then this check should be
104 // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
105 // currently they take only one typename Scalar template parameter.
106 // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
107 // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
108 // add together a float matrix and a double matrix.
109 #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
110   EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \
111                         ? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \
112                         : int(internal::is_same<LHS, RHS>::value)), \
113     YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
114
115 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
116 class CwiseBinaryOpImpl;
117
118 template<typename BinaryOp, typename Lhs, typename Rhs>
119 class CwiseBinaryOp : internal::no_assignment_operator,
120   public CwiseBinaryOpImpl<
121           BinaryOp, Lhs, Rhs,
122           typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
123                                            typename internal::traits<Rhs>::StorageKind>::ret>
124 {
125   public:
126
127     typedef typename CwiseBinaryOpImpl<
128         BinaryOp, Lhs, Rhs,
129         typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
130                                          typename internal::traits<Rhs>::StorageKind>::ret>::Base Base;
131     EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
132
133     typedef typename internal::nested<Lhs>::type LhsNested;
134     typedef typename internal::nested<Rhs>::type RhsNested;
135     typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
136     typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
137
138     EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
139       : m_lhs(lhs), m_rhs(rhs), m_functor(func)
140     {
141       EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
142       // require the sizes to match
143       EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
144       eigen_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
145     }
146
147     EIGEN_STRONG_INLINE Index rows() const {
148       // return the fixed size type if available to enable compile time optimizations
149       if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic)
150         return m_rhs.rows();
151       else
152         return m_lhs.rows();
153     }
154     EIGEN_STRONG_INLINE Index cols() const {
155       // return the fixed size type if available to enable compile time optimizations
156       if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic)
157         return m_rhs.cols();
158       else
159         return m_lhs.cols();
160     }
161
162     /** \returns the left hand side nested expression */
163     const _LhsNested& lhs() const { return m_lhs; }
164     /** \returns the right hand side nested expression */
165     const _RhsNested& rhs() const { return m_rhs; }
166     /** \returns the functor representing the binary operation */
167     const BinaryOp& functor() const { return m_functor; }
168
169   protected:
170     const LhsNested m_lhs;
171     const RhsNested m_rhs;
172     const BinaryOp m_functor;
173 };
174
175 template<typename BinaryOp, typename Lhs, typename Rhs>
176 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
177   : public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
178 {
179     typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
180   public:
181
182     typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
183     EIGEN_DENSE_PUBLIC_INTERFACE( Derived )
184
185     EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
186     {
187       return derived().functor()(derived().lhs().coeff(row, col),
188                                  derived().rhs().coeff(row, col));
189     }
190
191     template<int LoadMode>
192     EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
193     {
194       return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(row, col),
195                                           derived().rhs().template packet<LoadMode>(row, col));
196     }
197
198     EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
199     {
200       return derived().functor()(derived().lhs().coeff(index),
201                                  derived().rhs().coeff(index));
202     }
203
204     template<int LoadMode>
205     EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
206     {
207       return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(index),
208                                           derived().rhs().template packet<LoadMode>(index));
209     }
210 };
211
212 /** replaces \c *this by \c *this - \a other.
213   *
214   * \returns a reference to \c *this
215   */
216 template<typename Derived>
217 template<typename OtherDerived>
218 EIGEN_STRONG_INLINE Derived &
219 MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
220 {
221   SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived());
222   tmp = other.derived();
223   return derived();
224 }
225
226 /** replaces \c *this by \c *this + \a other.
227   *
228   * \returns a reference to \c *this
229   */
230 template<typename Derived>
231 template<typename OtherDerived>
232 EIGEN_STRONG_INLINE Derived &
233 MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
234 {
235   SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived());
236   tmp = other.derived();
237   return derived();
238 }
239
240 #endif // EIGEN_CWISE_BINARY_OP_H