VectorwiseOp.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2010 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_PARTIAL_REDUX_H
27 #define EIGEN_PARTIAL_REDUX_H
28 
29 namespace Eigen {
30 
47 template< typename MatrixType, typename MemberOp, int Direction>
48 class PartialReduxExpr;
49 
50 namespace internal {
51 template<typename MatrixType, typename MemberOp, int Direction>
52 struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
53  : traits<MatrixType>
54 {
55  typedef typename MemberOp::result_type Scalar;
56  typedef typename traits<MatrixType>::StorageKind StorageKind;
57  typedef typename traits<MatrixType>::XprKind XprKind;
58  typedef typename MatrixType::Scalar InputScalar;
59  typedef typename nested<MatrixType>::type MatrixTypeNested;
60  typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
61  enum {
62  RowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::RowsAtCompileTime,
63  ColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::ColsAtCompileTime,
64  MaxRowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::MaxRowsAtCompileTime,
65  MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
66  Flags0 = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
67  Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0),
68  TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime
69  };
70  #if EIGEN_GNUC_AT_LEAST(3,4)
71  typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
72  #else
73  typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
74  #endif
75  enum {
76  CoeffReadCost = TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
77  };
78 };
79 }
80 
81 template< typename MatrixType, typename MemberOp, int Direction>
82 class PartialReduxExpr : internal::no_assignment_operator,
83  public internal::dense_xpr_base< PartialReduxExpr<MatrixType, MemberOp, Direction> >::type
84 {
85  public:
86 
87  typedef typename internal::dense_xpr_base<PartialReduxExpr>::type Base;
91 
92  PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp())
93  : m_matrix(mat), m_functor(func) {}
94 
95  Index rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); }
96  Index cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); }
97 
98  EIGEN_STRONG_INLINE const Scalar coeff(Index i, Index j) const
99  {
100  if (Direction==Vertical)
101  return m_functor(m_matrix.col(j));
102  else
103  return m_functor(m_matrix.row(i));
104  }
105 
106  const Scalar coeff(Index index) const
107  {
108  if (Direction==Vertical)
109  return m_functor(m_matrix.col(index));
110  else
111  return m_functor(m_matrix.row(index));
112  }
113 
114  protected:
116  const MemberOp m_functor;
117 };
118 
119 #define EIGEN_MEMBER_FUNCTOR(MEMBER,COST) \
120  template <typename ResultType> \
121  struct member_##MEMBER { \
122  EIGEN_EMPTY_STRUCT_CTOR(member_##MEMBER) \
123  typedef ResultType result_type; \
124  template<typename Scalar, int Size> struct Cost \
125  { enum { value = COST }; }; \
126  template<typename XprType> \
127  EIGEN_STRONG_INLINE ResultType operator()(const XprType& mat) const \
128  { return mat.MEMBER(); } \
129  }
130 
131 namespace internal {
132 
137 EIGEN_MEMBER_FUNCTOR(hypotNorm, (Size-1) * functor_traits<scalar_hypot_op<Scalar> >::Cost );
146 
147 
148 template <typename BinaryOp, typename Scalar>
149 struct member_redux {
150  typedef typename result_of<
151  BinaryOp(Scalar)
152  >::type result_type;
153  template<typename _Scalar, int Size> struct Cost
154  { enum { value = (Size-1) * functor_traits<BinaryOp>::Cost }; };
155  member_redux(const BinaryOp func) : m_functor(func) {}
156  template<typename Derived>
157  inline result_type operator()(const DenseBase<Derived>& mat) const
158  { return mat.redux(m_functor); }
159  const BinaryOp m_functor;
160 };
161 }
162 
180 template<typename ExpressionType, int Direction> class VectorwiseOp
181 {
182  public:
183 
184  typedef typename ExpressionType::Scalar Scalar;
185  typedef typename ExpressionType::RealScalar RealScalar;
186  typedef typename ExpressionType::Index Index;
187  typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
188  ExpressionType, ExpressionType&>::type ExpressionTypeNested;
189  typedef typename internal::remove_all<ExpressionTypeNested>::type ExpressionTypeNestedCleaned;
190 
191  template<template<typename _Scalar> class Functor,
192  typename Scalar=typename internal::traits<ExpressionType>::Scalar> struct ReturnType
193  {
194  typedef PartialReduxExpr<ExpressionType,
195  Functor<Scalar>,
196  Direction
197  > Type;
198  };
199 
200  template<typename BinaryOp> struct ReduxReturnType
201  {
202  typedef PartialReduxExpr<ExpressionType,
203  internal::member_redux<BinaryOp,typename internal::traits<ExpressionType>::Scalar>,
204  Direction
205  > Type;
206  };
207 
208  enum {
209  IsVertical = (Direction==Vertical) ? 1 : 0,
210  IsHorizontal = (Direction==Horizontal) ? 1 : 0
211  };
212 
213  protected:
214 
217  typedef typename internal::conditional<Direction==Vertical,
218  typename ExpressionType::ColXpr,
219  typename ExpressionType::RowXpr>::type SubVector;
220  SubVector subVector(Index i)
221  {
222  return SubVector(m_matrix.derived(),i);
223  }
224 
227  Index subVectors() const
228  { return Direction==Vertical?m_matrix.cols():m_matrix.rows(); }
229 
230  template<typename OtherDerived> struct ExtendedType {
231  typedef Replicate<OtherDerived,
232  Direction==Vertical ? 1 : ExpressionType::RowsAtCompileTime,
233  Direction==Horizontal ? 1 : ExpressionType::ColsAtCompileTime> Type;
234  };
235 
238  template<typename OtherDerived>
240  extendedTo(const DenseBase<OtherDerived>& other) const
241  {
242  EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Vertical, OtherDerived::MaxColsAtCompileTime==1),
243  YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED)
244  EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Horizontal, OtherDerived::MaxRowsAtCompileTime==1),
245  YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED)
246  return typename ExtendedType<OtherDerived>::Type
247  (other.derived(),
248  Direction==Vertical ? 1 : m_matrix.rows(),
249  Direction==Horizontal ? 1 : m_matrix.cols());
250  }
251 
252  public:
253 
254  inline VectorwiseOp(ExpressionType& matrix) : m_matrix(matrix) {}
255 
257  inline const ExpressionType& _expression() const { return m_matrix; }
258 
266  template<typename BinaryOp>
267  const typename ReduxReturnType<BinaryOp>::Type
268  redux(const BinaryOp& func = BinaryOp()) const
269  { return typename ReduxReturnType<BinaryOp>::Type(_expression(), func); }
270 
278  const typename ReturnType<internal::member_minCoeff>::Type minCoeff() const
279  { return _expression(); }
280 
288  const typename ReturnType<internal::member_maxCoeff>::Type maxCoeff() const
289  { return _expression(); }
290 
299  { return _expression(); }
300 
309  { return _expression(); }
310 
311 
318  { return _expression(); }
319 
320 
327  { return _expression(); }
328 
329 
336  { return _expression(); }
337 
345  const typename ReturnType<internal::member_sum>::Type sum() const
346  { return _expression(); }
347 
352  const typename ReturnType<internal::member_mean>::Type mean() const
353  { return _expression(); }
354 
359  const typename ReturnType<internal::member_all>::Type all() const
360  { return _expression(); }
361 
366  const typename ReturnType<internal::member_any>::Type any() const
367  { return _expression(); }
368 
377  { return _expression(); }
378 
386  const typename ReturnType<internal::member_prod>::Type prod() const
387  { return _expression(); }
388 
389 
398  { return Reverse<ExpressionType, Direction>( _expression() ); }
399 
401  const ReplicateReturnType replicate(Index factor) const;
402 
411  // NOTE implemented here because of sunstudio's compilation errors
413  replicate(Index factor = Factor) const
414  {
416  (_expression(),Direction==Vertical?factor:1,Direction==Horizontal?factor:1);
417  }
418 
420 
422  template<typename OtherDerived>
423  ExpressionType& operator=(const DenseBase<OtherDerived>& other)
424  {
425  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
426  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
427  //eigen_assert((m_matrix.isNull()) == (other.isNull())); FIXME
428  return const_cast<ExpressionType&>(m_matrix = extendedTo(other.derived()));
429  }
430 
432  template<typename OtherDerived>
433  ExpressionType& operator+=(const DenseBase<OtherDerived>& other)
434  {
435  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
436  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
437  return const_cast<ExpressionType&>(m_matrix += extendedTo(other.derived()));
438  }
439 
441  template<typename OtherDerived>
442  ExpressionType& operator-=(const DenseBase<OtherDerived>& other)
443  {
444  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
445  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
446  return const_cast<ExpressionType&>(m_matrix -= extendedTo(other.derived()));
447  }
448 
450  template<typename OtherDerived>
451  ExpressionType& operator*=(const DenseBase<OtherDerived>& other)
452  {
453  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
454  EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
455  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
456  m_matrix *= extendedTo(other.derived());
457  return const_cast<ExpressionType&>(m_matrix);
458  }
459 
461  template<typename OtherDerived>
462  ExpressionType& operator/=(const DenseBase<OtherDerived>& other)
463  {
464  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
465  EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
466  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
467  m_matrix /= extendedTo(other.derived());
468  return const_cast<ExpressionType&>(m_matrix);
469  }
470 
472  template<typename OtherDerived> EIGEN_STRONG_INLINE
474  const ExpressionTypeNestedCleaned,
475  const typename ExtendedType<OtherDerived>::Type>
476  operator+(const DenseBase<OtherDerived>& other) const
477  {
478  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
479  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
480  return m_matrix + extendedTo(other.derived());
481  }
482 
484  template<typename OtherDerived>
486  const ExpressionTypeNestedCleaned,
487  const typename ExtendedType<OtherDerived>::Type>
488  operator-(const DenseBase<OtherDerived>& other) const
489  {
490  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
491  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
492  return m_matrix - extendedTo(other.derived());
493  }
494 
497  template<typename OtherDerived> EIGEN_STRONG_INLINE
499  const ExpressionTypeNestedCleaned,
500  const typename ExtendedType<OtherDerived>::Type>
501  operator*(const DenseBase<OtherDerived>& other) const
502  {
503  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
504  EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
505  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
506  return m_matrix * extendedTo(other.derived());
507  }
508 
511  template<typename OtherDerived>
513  const ExpressionTypeNestedCleaned,
514  const typename ExtendedType<OtherDerived>::Type>
515  operator/(const DenseBase<OtherDerived>& other) const
516  {
517  EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
518  EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
519  EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
520  return m_matrix / extendedTo(other.derived());
521  }
522 
524 
525  #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
526  Homogeneous<ExpressionType,Direction> homogeneous() const;
527  #endif
528 
529  typedef typename ExpressionType::PlainObject CrossReturnType;
530  template<typename OtherDerived>
531  const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const;
532 
533  enum {
534  HNormalized_Size = Direction==Vertical ? internal::traits<ExpressionType>::RowsAtCompileTime
535  : internal::traits<ExpressionType>::ColsAtCompileTime,
536  HNormalized_SizeMinusOne = HNormalized_Size==Dynamic ? Dynamic : HNormalized_Size-1
537  };
538  typedef Block<const ExpressionType,
539  Direction==Vertical ? int(HNormalized_SizeMinusOne)
540  : int(internal::traits<ExpressionType>::RowsAtCompileTime),
541  Direction==Horizontal ? int(HNormalized_SizeMinusOne)
542  : int(internal::traits<ExpressionType>::ColsAtCompileTime)>
544  typedef Block<const ExpressionType,
545  Direction==Vertical ? 1 : int(internal::traits<ExpressionType>::RowsAtCompileTime),
546  Direction==Horizontal ? 1 : int(internal::traits<ExpressionType>::ColsAtCompileTime)>
549  const HNormalized_Block,
551  Direction==Vertical ? HNormalized_SizeMinusOne : 1,
552  Direction==Horizontal ? HNormalized_SizeMinusOne : 1> >
554 
555  const HNormalizedReturnType hnormalized() const;
556 
557  protected:
559 };
560 
568 template<typename Derived>
569 inline const typename DenseBase<Derived>::ConstColwiseReturnType
571 {
572  return derived();
573 }
574 
579 template<typename Derived>
582 {
583  return derived();
584 }
585 
593 template<typename Derived>
594 inline const typename DenseBase<Derived>::ConstRowwiseReturnType
596 {
597  return derived();
598 }
599 
604 template<typename Derived>
607 {
608  return derived();
609 }
610 
611 } // end namespace Eigen
612 
613 #endif // EIGEN_PARTIAL_REDUX_H