VectorwiseOp.h 28.8 KB
Newer Older
LM's avatar
LM committed
1 2 3 4 5 6
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
Don Gagne's avatar
Don Gagne committed
7 8 9
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
LM's avatar
LM committed
10 11 12 13

#ifndef EIGEN_PARTIAL_REDUX_H
#define EIGEN_PARTIAL_REDUX_H

14
namespace Eigen {
Don Gagne's avatar
Don Gagne committed
15

LM's avatar
LM committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/** \class PartialReduxExpr
  * \ingroup Core_Module
  *
  * \brief Generic expression of a partially reduxed matrix
  *
  * \tparam MatrixType the type of the matrix we are applying the redux operation
  * \tparam MemberOp type of the member functor
  * \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal)
  *
  * This class represents an expression of a partial redux operator of a matrix.
  * It is the return type of some VectorwiseOp functions,
  * and most of the time this is the only way it is used.
  *
  * \sa class VectorwiseOp
  */

template< typename MatrixType, typename MemberOp, int Direction>
class PartialReduxExpr;

namespace internal {
template<typename MatrixType, typename MemberOp, int Direction>
struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
 : traits<MatrixType>
{
  typedef typename MemberOp::result_type Scalar;
  typedef typename traits<MatrixType>::StorageKind StorageKind;
  typedef typename traits<MatrixType>::XprKind XprKind;
  typedef typename MatrixType::Scalar InputScalar;
  enum {
    RowsAtCompileTime = Direction==Vertical   ? 1 : MatrixType::RowsAtCompileTime,
    ColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::ColsAtCompileTime,
    MaxRowsAtCompileTime = Direction==Vertical   ? 1 : MatrixType::MaxRowsAtCompileTime,
    MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
49
    Flags = RowsAtCompileTime == 1 ? RowMajorBit : 0,
50
    TraversalSize = Direction==Vertical ? MatrixType::RowsAtCompileTime :  MatrixType::ColsAtCompileTime
LM's avatar
LM committed
51 52 53 54 55
  };
};
}

template< typename MatrixType, typename MemberOp, int Direction>
56 57
class PartialReduxExpr : public internal::dense_xpr_base< PartialReduxExpr<MatrixType, MemberOp, Direction> >::type,
                         internal::no_assignment_operator
LM's avatar
LM committed
58 59 60 61 62 63
{
  public:

    typedef typename internal::dense_xpr_base<PartialReduxExpr>::type Base;
    EIGEN_DENSE_PUBLIC_INTERFACE(PartialReduxExpr)

64 65
    EIGEN_DEVICE_FUNC
    explicit PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp())
LM's avatar
LM committed
66 67
      : m_matrix(mat), m_functor(func) {}

68
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
69
    Index rows() const { return (Direction==Vertical   ? 1 : m_matrix.rows()); }
70
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
71 72
    Index cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); }

73 74
    EIGEN_DEVICE_FUNC
    typename MatrixType::Nested nestedExpression() const { return m_matrix; }
LM's avatar
LM committed
75

76 77
    EIGEN_DEVICE_FUNC
    const MemberOp& functor() const { return m_functor; }
LM's avatar
LM committed
78 79

  protected:
80
    typename MatrixType::Nested m_matrix;
LM's avatar
LM committed
81 82 83 84 85
    const MemberOp m_functor;
};

#define EIGEN_MEMBER_FUNCTOR(MEMBER,COST)                               \
  template <typename ResultType>                                        \
Don Gagne's avatar
Don Gagne committed
86 87
  struct member_##MEMBER {                                              \
    EIGEN_EMPTY_STRUCT_CTOR(member_##MEMBER)                            \
LM's avatar
LM committed
88 89 90 91
    typedef ResultType result_type;                                     \
    template<typename Scalar, int Size> struct Cost                     \
    { enum { value = COST }; };                                         \
    template<typename XprType>                                          \
92 93
    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE                               \
    ResultType operator()(const XprType& mat) const                     \
LM's avatar
LM committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    { return mat.MEMBER(); } \
  }

namespace internal {

EIGEN_MEMBER_FUNCTOR(squaredNorm, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(norm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(stableNorm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(blueNorm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(hypotNorm, (Size-1) * functor_traits<scalar_hypot_op<Scalar> >::Cost );
EIGEN_MEMBER_FUNCTOR(sum, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(mean, (Size-1)*NumTraits<Scalar>::AddCost + NumTraits<Scalar>::MulCost);
EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(all, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(any, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(count, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(prod, (Size-1)*NumTraits<Scalar>::MulCost);

113 114 115 116 117 118 119 120 121 122
template <int p, typename ResultType>
struct member_lpnorm {
  typedef ResultType result_type;
  template<typename Scalar, int Size> struct Cost
  { enum { value = (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost }; };
  EIGEN_DEVICE_FUNC member_lpnorm() {}
  template<typename XprType>
  EIGEN_DEVICE_FUNC inline ResultType operator()(const XprType& mat) const
  { return mat.template lpNorm<p>(); }
};
LM's avatar
LM committed
123 124 125 126

template <typename BinaryOp, typename Scalar>
struct member_redux {
  typedef typename result_of<
127
                     BinaryOp(const Scalar&,const Scalar&)
LM's avatar
LM committed
128 129 130
                   >::type  result_type;
  template<typename _Scalar, int Size> struct Cost
  { enum { value = (Size-1) * functor_traits<BinaryOp>::Cost }; };
131
  EIGEN_DEVICE_FUNC explicit member_redux(const BinaryOp func) : m_functor(func) {}
LM's avatar
LM committed
132
  template<typename Derived>
133
  EIGEN_DEVICE_FUNC inline result_type operator()(const DenseBase<Derived>& mat) const
LM's avatar
LM committed
134 135 136 137 138 139 140 141 142 143
  { return mat.redux(m_functor); }
  const BinaryOp m_functor;
};
}

/** \class VectorwiseOp
  * \ingroup Core_Module
  *
  * \brief Pseudo expression providing partial reduction operations
  *
144 145
  * \tparam ExpressionType the type of the object on which to do partial reductions
  * \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal)
LM's avatar
LM committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
  *
  * This class represents a pseudo expression with partial reduction features.
  * It is the return type of DenseBase::colwise() and DenseBase::rowwise()
  * and most of the time this is the only way it is used.
  *
  * Example: \include MatrixBase_colwise.cpp
  * Output: \verbinclude MatrixBase_colwise.out
  *
  * \sa DenseBase::colwise(), DenseBase::rowwise(), class PartialReduxExpr
  */
template<typename ExpressionType, int Direction> class VectorwiseOp
{
  public:

    typedef typename ExpressionType::Scalar Scalar;
    typedef typename ExpressionType::RealScalar RealScalar;
162 163
    typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
    typedef typename internal::ref_selector<ExpressionType>::non_const_type ExpressionTypeNested;
LM's avatar
LM committed
164 165 166
    typedef typename internal::remove_all<ExpressionTypeNested>::type ExpressionTypeNestedCleaned;

    template<template<typename _Scalar> class Functor,
167
                      typename Scalar_=Scalar> struct ReturnType
LM's avatar
LM committed
168 169
    {
      typedef PartialReduxExpr<ExpressionType,
170
                               Functor<Scalar_>,
LM's avatar
LM committed
171 172 173 174 175 176 177
                               Direction
                              > Type;
    };

    template<typename BinaryOp> struct ReduxReturnType
    {
      typedef PartialReduxExpr<ExpressionType,
178
                               internal::member_redux<BinaryOp,Scalar>,
LM's avatar
LM committed
179 180 181 182 183
                               Direction
                              > Type;
    };

    enum {
184 185
      isVertical   = (Direction==Vertical) ? 1 : 0,
      isHorizontal = (Direction==Horizontal) ? 1 : 0
LM's avatar
LM committed
186 187 188 189
    };

  protected:

190
    typedef typename internal::conditional<isVertical,
LM's avatar
LM committed
191 192
                               typename ExpressionType::ColXpr,
                               typename ExpressionType::RowXpr>::type SubVector;
193 194 195
    /** \internal
      * \returns the i-th subvector according to the \c Direction */
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
196 197 198 199 200 201 202
    SubVector subVector(Index i)
    {
      return SubVector(m_matrix.derived(),i);
    }

    /** \internal
      * \returns the number of subvectors in the direction \c Direction */
203
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
204
    Index subVectors() const
205
    { return isVertical?m_matrix.cols():m_matrix.rows(); }
LM's avatar
LM committed
206 207 208

    template<typename OtherDerived> struct ExtendedType {
      typedef Replicate<OtherDerived,
209 210
                        isVertical   ? 1 : ExpressionType::RowsAtCompileTime,
                        isHorizontal ? 1 : ExpressionType::ColsAtCompileTime> Type;
LM's avatar
LM committed
211 212 213 214 215
    };

    /** \internal
      * Replicates a vector to match the size of \c *this */
    template<typename OtherDerived>
216
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
217 218 219
    typename ExtendedType<OtherDerived>::Type
    extendedTo(const DenseBase<OtherDerived>& other) const
    {
220
      EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(isVertical, OtherDerived::MaxColsAtCompileTime==1),
Don Gagne's avatar
Don Gagne committed
221
                          YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED)
222
      EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(isHorizontal, OtherDerived::MaxRowsAtCompileTime==1),
Don Gagne's avatar
Don Gagne committed
223
                          YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED)
LM's avatar
LM committed
224 225
      return typename ExtendedType<OtherDerived>::Type
                      (other.derived(),
226 227
                       isVertical   ? 1 : m_matrix.rows(),
                       isHorizontal ? 1 : m_matrix.cols());
LM's avatar
LM committed
228
    }
229

Don Gagne's avatar
Don Gagne committed
230 231
    template<typename OtherDerived> struct OppositeExtendedType {
      typedef Replicate<OtherDerived,
232 233
                        isHorizontal ? 1 : ExpressionType::RowsAtCompileTime,
                        isVertical   ? 1 : ExpressionType::ColsAtCompileTime> Type;
Don Gagne's avatar
Don Gagne committed
234 235 236 237 238
    };

    /** \internal
      * Replicates a vector in the opposite direction to match the size of \c *this */
    template<typename OtherDerived>
239
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
240 241 242
    typename OppositeExtendedType<OtherDerived>::Type
    extendedToOpposite(const DenseBase<OtherDerived>& other) const
    {
243
      EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(isHorizontal, OtherDerived::MaxColsAtCompileTime==1),
Don Gagne's avatar
Don Gagne committed
244
                          YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED)
245
      EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(isVertical, OtherDerived::MaxRowsAtCompileTime==1),
Don Gagne's avatar
Don Gagne committed
246 247 248
                          YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED)
      return typename OppositeExtendedType<OtherDerived>::Type
                      (other.derived(),
249 250
                       isHorizontal  ? 1 : m_matrix.rows(),
                       isVertical    ? 1 : m_matrix.cols());
Don Gagne's avatar
Don Gagne committed
251
    }
LM's avatar
LM committed
252 253

  public:
254 255
    EIGEN_DEVICE_FUNC
    explicit inline VectorwiseOp(ExpressionType& matrix) : m_matrix(matrix) {}
LM's avatar
LM committed
256 257

    /** \internal */
258
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
259 260 261 262 263 264 265 266 267 268
    inline const ExpressionType& _expression() const { return m_matrix; }

    /** \returns a row or column vector expression of \c *this reduxed by \a func
      *
      * The template parameter \a BinaryOp is the type of the functor
      * of the custom redux operator. Note that func must be an associative operator.
      *
      * \sa class VectorwiseOp, DenseBase::colwise(), DenseBase::rowwise()
      */
    template<typename BinaryOp>
269
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
270 271
    const typename ReduxReturnType<BinaryOp>::Type
    redux(const BinaryOp& func = BinaryOp()) const
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
    { return typename ReduxReturnType<BinaryOp>::Type(_expression(), internal::member_redux<BinaryOp,Scalar>(func)); }

    typedef typename ReturnType<internal::member_minCoeff>::Type MinCoeffReturnType;
    typedef typename ReturnType<internal::member_maxCoeff>::Type MaxCoeffReturnType;
    typedef typename ReturnType<internal::member_squaredNorm,RealScalar>::Type SquaredNormReturnType;
    typedef typename ReturnType<internal::member_norm,RealScalar>::Type NormReturnType;
    typedef typename ReturnType<internal::member_blueNorm,RealScalar>::Type BlueNormReturnType;
    typedef typename ReturnType<internal::member_stableNorm,RealScalar>::Type StableNormReturnType;
    typedef typename ReturnType<internal::member_hypotNorm,RealScalar>::Type HypotNormReturnType;
    typedef typename ReturnType<internal::member_sum>::Type SumReturnType;
    typedef typename ReturnType<internal::member_mean>::Type MeanReturnType;
    typedef typename ReturnType<internal::member_all>::Type AllReturnType;
    typedef typename ReturnType<internal::member_any>::Type AnyReturnType;
    typedef PartialReduxExpr<ExpressionType, internal::member_count<Index>, Direction> CountReturnType;
    typedef typename ReturnType<internal::member_prod>::Type ProdReturnType;
    typedef Reverse<const ExpressionType, Direction> ConstReverseReturnType;
    typedef Reverse<ExpressionType, Direction> ReverseReturnType;

    template<int p> struct LpNormReturnType {
      typedef PartialReduxExpr<ExpressionType, internal::member_lpnorm<p,RealScalar>,Direction> Type;
    };
LM's avatar
LM committed
293 294 295

    /** \returns a row (or column) vector expression of the smallest coefficient
      * of each column (or row) of the referenced expression.
296
      *
Don Gagne's avatar
Don Gagne committed
297
      * \warning the result is undefined if \c *this contains NaN.
LM's avatar
LM committed
298 299 300 301 302
      *
      * Example: \include PartialRedux_minCoeff.cpp
      * Output: \verbinclude PartialRedux_minCoeff.out
      *
      * \sa DenseBase::minCoeff() */
303 304 305
    EIGEN_DEVICE_FUNC
    const MinCoeffReturnType minCoeff() const
    { return MinCoeffReturnType(_expression()); }
LM's avatar
LM committed
306 307 308

    /** \returns a row (or column) vector expression of the largest coefficient
      * of each column (or row) of the referenced expression.
309
      *
Don Gagne's avatar
Don Gagne committed
310
      * \warning the result is undefined if \c *this contains NaN.
LM's avatar
LM committed
311 312 313 314 315
      *
      * Example: \include PartialRedux_maxCoeff.cpp
      * Output: \verbinclude PartialRedux_maxCoeff.out
      *
      * \sa DenseBase::maxCoeff() */
316 317 318
    EIGEN_DEVICE_FUNC
    const MaxCoeffReturnType maxCoeff() const
    { return MaxCoeffReturnType(_expression()); }
LM's avatar
LM committed
319 320 321

    /** \returns a row (or column) vector expression of the squared norm
      * of each column (or row) of the referenced expression.
322
      * This is a vector with real entries, even if the original matrix has complex entries.
LM's avatar
LM committed
323 324 325 326 327
      *
      * Example: \include PartialRedux_squaredNorm.cpp
      * Output: \verbinclude PartialRedux_squaredNorm.out
      *
      * \sa DenseBase::squaredNorm() */
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
    EIGEN_DEVICE_FUNC
    const SquaredNormReturnType squaredNorm() const
    { return SquaredNormReturnType(_expression()); }

    /** \returns a row (or column) vector expression of the norm
      * of each column (or row) of the referenced expression.
      * This is a vector with real entries, even if the original matrix has complex entries.
      *
      * Example: \include PartialRedux_norm.cpp
      * Output: \verbinclude PartialRedux_norm.out
      *
      * \sa DenseBase::norm() */
    EIGEN_DEVICE_FUNC
    const NormReturnType norm() const
    { return NormReturnType(_expression()); }
LM's avatar
LM committed
343 344 345

    /** \returns a row (or column) vector expression of the norm
      * of each column (or row) of the referenced expression.
346
      * This is a vector with real entries, even if the original matrix has complex entries.
LM's avatar
LM committed
347 348 349 350 351
      *
      * Example: \include PartialRedux_norm.cpp
      * Output: \verbinclude PartialRedux_norm.out
      *
      * \sa DenseBase::norm() */
352 353 354 355
    template<int p>
    EIGEN_DEVICE_FUNC
    const typename LpNormReturnType<p>::Type lpNorm() const
    { return typename LpNormReturnType<p>::Type(_expression()); }
LM's avatar
LM committed
356 357 358 359


    /** \returns a row (or column) vector expression of the norm
      * of each column (or row) of the referenced expression, using
360 361
      * Blue's algorithm.
      * This is a vector with real entries, even if the original matrix has complex entries.
LM's avatar
LM committed
362 363
      *
      * \sa DenseBase::blueNorm() */
364 365 366
    EIGEN_DEVICE_FUNC
    const BlueNormReturnType blueNorm() const
    { return BlueNormReturnType(_expression()); }
LM's avatar
LM committed
367 368 369 370 371


    /** \returns a row (or column) vector expression of the norm
      * of each column (or row) of the referenced expression, avoiding
      * underflow and overflow.
372
      * This is a vector with real entries, even if the original matrix has complex entries.
LM's avatar
LM committed
373 374
      *
      * \sa DenseBase::stableNorm() */
375 376 377
    EIGEN_DEVICE_FUNC
    const StableNormReturnType stableNorm() const
    { return StableNormReturnType(_expression()); }
LM's avatar
LM committed
378 379 380 381 382


    /** \returns a row (or column) vector expression of the norm
      * of each column (or row) of the referenced expression, avoiding
      * underflow and overflow using a concatenation of hypot() calls.
383
      * This is a vector with real entries, even if the original matrix has complex entries.
LM's avatar
LM committed
384 385
      *
      * \sa DenseBase::hypotNorm() */
386 387 388
    EIGEN_DEVICE_FUNC
    const HypotNormReturnType hypotNorm() const
    { return HypotNormReturnType(_expression()); }
LM's avatar
LM committed
389 390 391 392 393 394 395 396

    /** \returns a row (or column) vector expression of the sum
      * of each column (or row) of the referenced expression.
      *
      * Example: \include PartialRedux_sum.cpp
      * Output: \verbinclude PartialRedux_sum.out
      *
      * \sa DenseBase::sum() */
397 398 399
    EIGEN_DEVICE_FUNC
    const SumReturnType sum() const
    { return SumReturnType(_expression()); }
LM's avatar
LM committed
400 401 402 403 404

    /** \returns a row (or column) vector expression of the mean
    * of each column (or row) of the referenced expression.
    *
    * \sa DenseBase::mean() */
405 406 407
    EIGEN_DEVICE_FUNC
    const MeanReturnType mean() const
    { return MeanReturnType(_expression()); }
LM's avatar
LM committed
408 409 410

    /** \returns a row (or column) vector expression representing
      * whether \b all coefficients of each respective column (or row) are \c true.
411
      * This expression can be assigned to a vector with entries of type \c bool.
LM's avatar
LM committed
412 413
      *
      * \sa DenseBase::all() */
414 415 416
    EIGEN_DEVICE_FUNC
    const AllReturnType all() const
    { return AllReturnType(_expression()); }
LM's avatar
LM committed
417 418 419

    /** \returns a row (or column) vector expression representing
      * whether \b at \b least one coefficient of each respective column (or row) is \c true.
420
      * This expression can be assigned to a vector with entries of type \c bool.
LM's avatar
LM committed
421 422
      *
      * \sa DenseBase::any() */
423 424 425
    EIGEN_DEVICE_FUNC
    const AnyReturnType any() const
    { return AnyReturnType(_expression()); }
LM's avatar
LM committed
426 427 428

    /** \returns a row (or column) vector expression representing
      * the number of \c true coefficients of each respective column (or row).
429 430
      * This expression can be assigned to a vector whose entries have the same type as is used to
      * index entries of the original matrix; for dense matrices, this is \c std::ptrdiff_t .
LM's avatar
LM committed
431 432 433 434 435
      *
      * Example: \include PartialRedux_count.cpp
      * Output: \verbinclude PartialRedux_count.out
      *
      * \sa DenseBase::count() */
436 437 438
    EIGEN_DEVICE_FUNC
    const CountReturnType count() const
    { return CountReturnType(_expression()); }
LM's avatar
LM committed
439 440 441 442 443 444 445 446

    /** \returns a row (or column) vector expression of the product
      * of each column (or row) of the referenced expression.
      *
      * Example: \include PartialRedux_prod.cpp
      * Output: \verbinclude PartialRedux_prod.out
      *
      * \sa DenseBase::prod() */
447 448 449
    EIGEN_DEVICE_FUNC
    const ProdReturnType prod() const
    { return ProdReturnType(_expression()); }
LM's avatar
LM committed
450 451 452 453 454 455 456 457 458


    /** \returns a matrix expression
      * where each column (or row) are reversed.
      *
      * Example: \include Vectorwise_reverse.cpp
      * Output: \verbinclude Vectorwise_reverse.out
      *
      * \sa DenseBase::reverse() */
459 460 461
    EIGEN_DEVICE_FUNC
    const ConstReverseReturnType reverse() const
    { return ConstReverseReturnType( _expression() ); }
LM's avatar
LM committed
462

463 464 465 466 467 468 469 470 471 472
    /** \returns a writable matrix expression
      * where each column (or row) are reversed.
      *
      * \sa reverse() const */
    EIGEN_DEVICE_FUNC
    ReverseReturnType reverse()
    { return ReverseReturnType( _expression() ); }

    typedef Replicate<ExpressionType,(isVertical?Dynamic:1),(isHorizontal?Dynamic:1)> ReplicateReturnType;
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
473 474 475 476 477 478 479 480 481 482 483
    const ReplicateReturnType replicate(Index factor) const;

    /**
      * \return an expression of the replication of each column (or row) of \c *this
      *
      * Example: \include DirectionWise_replicate.cpp
      * Output: \verbinclude DirectionWise_replicate.out
      *
      * \sa VectorwiseOp::replicate(Index), DenseBase::replicate(), class Replicate
      */
    // NOTE implemented here because of sunstudio's compilation errors
484 485 486
    // isVertical*Factor+isHorizontal instead of (isVertical?Factor:1) to handle CUDA bug with ternary operator
    template<int Factor> const Replicate<ExpressionType,isVertical*Factor+isHorizontal,isHorizontal*Factor+isVertical>
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
487 488
    replicate(Index factor = Factor) const
    {
489 490
      return Replicate<ExpressionType,(isVertical?Factor:1),(isHorizontal?Factor:1)>
          (_expression(),isVertical?factor:1,isHorizontal?factor:1);
LM's avatar
LM committed
491 492 493 494 495 496
    }

/////////// Artithmetic operators ///////////

    /** Copies the vector \a other to each subvector of \c *this */
    template<typename OtherDerived>
497
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
498 499 500
    ExpressionType& operator=(const DenseBase<OtherDerived>& other)
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
Don Gagne's avatar
Don Gagne committed
501
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
LM's avatar
LM committed
502
      //eigen_assert((m_matrix.isNull()) == (other.isNull())); FIXME
Don Gagne's avatar
Don Gagne committed
503
      return const_cast<ExpressionType&>(m_matrix = extendedTo(other.derived()));
LM's avatar
LM committed
504 505 506 507
    }

    /** Adds the vector \a other to each subvector of \c *this */
    template<typename OtherDerived>
508
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
509 510 511
    ExpressionType& operator+=(const DenseBase<OtherDerived>& other)
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
Don Gagne's avatar
Don Gagne committed
512 513
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
      return const_cast<ExpressionType&>(m_matrix += extendedTo(other.derived()));
LM's avatar
LM committed
514 515 516 517
    }

    /** Substracts the vector \a other to each subvector of \c *this */
    template<typename OtherDerived>
518
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
519 520 521
    ExpressionType& operator-=(const DenseBase<OtherDerived>& other)
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
Don Gagne's avatar
Don Gagne committed
522 523 524 525 526 527
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
      return const_cast<ExpressionType&>(m_matrix -= extendedTo(other.derived()));
    }

    /** Multiples each subvector of \c *this by the vector \a other */
    template<typename OtherDerived>
528
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
529 530 531 532 533 534 535 536 537 538 539
    ExpressionType& operator*=(const DenseBase<OtherDerived>& other)
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
      EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
      m_matrix *= extendedTo(other.derived());
      return const_cast<ExpressionType&>(m_matrix);
    }

    /** Divides each subvector of \c *this by the vector \a other */
    template<typename OtherDerived>
540
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
541 542 543 544 545 546
    ExpressionType& operator/=(const DenseBase<OtherDerived>& other)
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
      EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
      m_matrix /= extendedTo(other.derived());
LM's avatar
LM committed
547 548 549 550
      return const_cast<ExpressionType&>(m_matrix);
    }

    /** Returns the expression of the sum of the vector \a other to each subvector of \c *this */
551 552
    template<typename OtherDerived> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
    CwiseBinaryOp<internal::scalar_sum_op<Scalar,typename OtherDerived::Scalar>,
LM's avatar
LM committed
553 554 555 556
                  const ExpressionTypeNestedCleaned,
                  const typename ExtendedType<OtherDerived>::Type>
    operator+(const DenseBase<OtherDerived>& other) const
    {
Don Gagne's avatar
Don Gagne committed
557 558
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
LM's avatar
LM committed
559 560 561 562 563
      return m_matrix + extendedTo(other.derived());
    }

    /** Returns the expression of the difference between each subvector of \c *this and the vector \a other */
    template<typename OtherDerived>
564 565
    EIGEN_DEVICE_FUNC
    CwiseBinaryOp<internal::scalar_difference_op<Scalar,typename OtherDerived::Scalar>,
LM's avatar
LM committed
566 567 568 569
                  const ExpressionTypeNestedCleaned,
                  const typename ExtendedType<OtherDerived>::Type>
    operator-(const DenseBase<OtherDerived>& other) const
    {
Don Gagne's avatar
Don Gagne committed
570 571
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
LM's avatar
LM committed
572 573 574
      return m_matrix - extendedTo(other.derived());
    }

Don Gagne's avatar
Don Gagne committed
575 576
    /** Returns the expression where each subvector is the product of the vector \a other
      * by the corresponding subvector of \c *this */
577
    template<typename OtherDerived> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
578 579 580
    CwiseBinaryOp<internal::scalar_product_op<Scalar>,
                  const ExpressionTypeNestedCleaned,
                  const typename ExtendedType<OtherDerived>::Type>
581
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
582 583 584 585 586 587 588 589 590 591 592
    operator*(const DenseBase<OtherDerived>& other) const
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
      EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
      return m_matrix * extendedTo(other.derived());
    }

    /** Returns the expression where each subvector is the quotient of the corresponding
      * subvector of \c *this by the vector \a other */
    template<typename OtherDerived>
593
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
594 595 596 597 598 599 600 601 602 603
    CwiseBinaryOp<internal::scalar_quotient_op<Scalar>,
                  const ExpressionTypeNestedCleaned,
                  const typename ExtendedType<OtherDerived>::Type>
    operator/(const DenseBase<OtherDerived>& other) const
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
      EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
      EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
      return m_matrix / extendedTo(other.derived());
    }
604 605

    /** \returns an expression where each column (or row) of the referenced matrix are normalized.
Don Gagne's avatar
Don Gagne committed
606 607 608
      * The referenced matrix is \b not modified.
      * \sa MatrixBase::normalized(), normalize()
      */
609
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
610 611 612 613
    CwiseBinaryOp<internal::scalar_quotient_op<Scalar>,
                  const ExpressionTypeNestedCleaned,
                  const typename OppositeExtendedType<typename ReturnType<internal::member_norm,RealScalar>::Type>::Type>
    normalized() const { return m_matrix.cwiseQuotient(extendedToOpposite(this->norm())); }
614 615


Don Gagne's avatar
Don Gagne committed
616 617 618
    /** Normalize in-place each row or columns of the referenced matrix.
      * \sa MatrixBase::normalize(), normalized()
      */
619
    EIGEN_DEVICE_FUNC void normalize() {
Don Gagne's avatar
Don Gagne committed
620 621 622
      m_matrix = this->normalized();
    }

623 624
    EIGEN_DEVICE_FUNC inline void reverseInPlace();

LM's avatar
LM committed
625 626
/////////// Geometry module ///////////

627 628 629
    typedef Homogeneous<ExpressionType,Direction> HomogeneousReturnType;
    EIGEN_DEVICE_FUNC
    HomogeneousReturnType homogeneous() const;
LM's avatar
LM committed
630 631 632

    typedef typename ExpressionType::PlainObject CrossReturnType;
    template<typename OtherDerived>
633
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
    const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const;

    enum {
      HNormalized_Size = Direction==Vertical ? internal::traits<ExpressionType>::RowsAtCompileTime
                                             : internal::traits<ExpressionType>::ColsAtCompileTime,
      HNormalized_SizeMinusOne = HNormalized_Size==Dynamic ? Dynamic : HNormalized_Size-1
    };
    typedef Block<const ExpressionType,
                  Direction==Vertical   ? int(HNormalized_SizeMinusOne)
                                        : int(internal::traits<ExpressionType>::RowsAtCompileTime),
                  Direction==Horizontal ? int(HNormalized_SizeMinusOne)
                                        : int(internal::traits<ExpressionType>::ColsAtCompileTime)>
            HNormalized_Block;
    typedef Block<const ExpressionType,
                  Direction==Vertical   ? 1 : int(internal::traits<ExpressionType>::RowsAtCompileTime),
                  Direction==Horizontal ? 1 : int(internal::traits<ExpressionType>::ColsAtCompileTime)>
            HNormalized_Factors;
    typedef CwiseBinaryOp<internal::scalar_quotient_op<typename internal::traits<ExpressionType>::Scalar>,
                const HNormalized_Block,
                const Replicate<HNormalized_Factors,
                  Direction==Vertical   ? HNormalized_SizeMinusOne : 1,
                  Direction==Horizontal ? HNormalized_SizeMinusOne : 1> >
            HNormalizedReturnType;

658
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
659 660 661 662 663 664
    const HNormalizedReturnType hnormalized() const;

  protected:
    ExpressionTypeNested m_matrix;
};

665 666
//const colwise moved to DenseBase.h due to CUDA compiler bug

LM's avatar
LM committed
667 668 669

/** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations
  *
Don Gagne's avatar
Don Gagne committed
670
  * \sa rowwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting
LM's avatar
LM committed
671 672 673 674 675
  */
template<typename Derived>
inline typename DenseBase<Derived>::ColwiseReturnType
DenseBase<Derived>::colwise()
{
676
  return ColwiseReturnType(derived());
LM's avatar
LM committed
677 678
}

679 680
//const rowwise moved to DenseBase.h due to CUDA compiler bug

LM's avatar
LM committed
681 682 683

/** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations
  *
Don Gagne's avatar
Don Gagne committed
684
  * \sa colwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting
LM's avatar
LM committed
685 686 687 688 689
  */
template<typename Derived>
inline typename DenseBase<Derived>::RowwiseReturnType
DenseBase<Derived>::rowwise()
{
690
  return RowwiseReturnType(derived());
LM's avatar
LM committed
691 692
}

Don Gagne's avatar
Don Gagne committed
693 694
} // end namespace Eigen

LM's avatar
LM committed
695
#endif // EIGEN_PARTIAL_REDUX_H