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 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #ifndef EIGEN_PARTIAL_REDUX_H 12 #define EIGEN_PARTIAL_REDUX_H 13 14 namespace Eigen { 15 16 /** \class PartialReduxExpr 17 * \ingroup Core_Module 18 * 19 * \brief Generic expression of a partially reduxed matrix 20 * 21 * \tparam MatrixType the type of the matrix we are applying the redux operation 22 * \tparam MemberOp type of the member functor 23 * \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal) 24 * 25 * This class represents an expression of a partial redux operator of a matrix. 26 * It is the return type of some VectorwiseOp functions, 27 * and most of the time this is the only way it is used. 28 * 29 * \sa class VectorwiseOp 30 */ 31 32 template< typename MatrixType, typename MemberOp, int Direction> 33 class PartialReduxExpr; 34 35 namespace internal { 36 template<typename MatrixType, typename MemberOp, int Direction> 37 struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> > 38 : traits<MatrixType> 39 { 40 typedef typename MemberOp::result_type Scalar; 41 typedef typename traits<MatrixType>::StorageKind StorageKind; 42 typedef typename traits<MatrixType>::XprKind XprKind; 43 typedef typename MatrixType::Scalar InputScalar; 44 typedef typename nested<MatrixType>::type MatrixTypeNested; 45 typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested; 46 enum { 47 RowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::RowsAtCompileTime, 48 ColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::ColsAtCompileTime, 49 MaxRowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::MaxRowsAtCompileTime, 50 MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime, 51 Flags0 = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits, 52 Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0), 53 TraversalSize = Direction==Vertical ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime 54 }; 55 #if EIGEN_GNUC_AT_LEAST(3,4) 56 typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType; 57 #else 58 typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType; 59 #endif 60 enum { 61 CoeffReadCost = TraversalSize==Dynamic ? Dynamic 62 : TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value) 63 }; 64 }; 65 } 66 67 template< typename MatrixType, typename MemberOp, int Direction> 68 class PartialReduxExpr : internal::no_assignment_operator, 69 public internal::dense_xpr_base< PartialReduxExpr<MatrixType, MemberOp, Direction> >::type 70 { 71 public: 72 73 typedef typename internal::dense_xpr_base<PartialReduxExpr>::type Base; 74 EIGEN_DENSE_PUBLIC_INTERFACE(PartialReduxExpr) 75 typedef typename internal::traits<PartialReduxExpr>::MatrixTypeNested MatrixTypeNested; 76 typedef typename internal::traits<PartialReduxExpr>::_MatrixTypeNested _MatrixTypeNested; 77 78 PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp()) 79 : m_matrix(mat), m_functor(func) {} 80 81 Index rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); } 82 Index cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); } 83 84 EIGEN_STRONG_INLINE const Scalar coeff(Index i, Index j) const 85 { 86 if (Direction==Vertical) 87 return m_functor(m_matrix.col(j)); 88 else 89 return m_functor(m_matrix.row(i)); 90 } 91 92 const Scalar coeff(Index index) const 93 { 94 if (Direction==Vertical) 95 return m_functor(m_matrix.col(index)); 96 else 97 return m_functor(m_matrix.row(index)); 98 } 99 100 protected: 101 MatrixTypeNested m_matrix; 102 const MemberOp m_functor; 103 }; 104 105 #define EIGEN_MEMBER_FUNCTOR(MEMBER,COST) \ 106 template <typename ResultType> \ 107 struct member_##MEMBER { \ 108 EIGEN_EMPTY_STRUCT_CTOR(member_##MEMBER) \ 109 typedef ResultType result_type; \ 110 template<typename Scalar, int Size> struct Cost \ 111 { enum { value = COST }; }; \ 112 template<typename XprType> \ 113 EIGEN_STRONG_INLINE ResultType operator()(const XprType& mat) const \ 114 { return mat.MEMBER(); } \ 115 } 116 117 namespace internal { 118 119 EIGEN_MEMBER_FUNCTOR(squaredNorm, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost); 120 EIGEN_MEMBER_FUNCTOR(norm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost); 121 EIGEN_MEMBER_FUNCTOR(stableNorm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost); 122 EIGEN_MEMBER_FUNCTOR(blueNorm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost); 123 EIGEN_MEMBER_FUNCTOR(hypotNorm, (Size-1) * functor_traits<scalar_hypot_op<Scalar> >::Cost ); 124 EIGEN_MEMBER_FUNCTOR(sum, (Size-1)*NumTraits<Scalar>::AddCost); 125 EIGEN_MEMBER_FUNCTOR(mean, (Size-1)*NumTraits<Scalar>::AddCost + NumTraits<Scalar>::MulCost); 126 EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost); 127 EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost); 128 EIGEN_MEMBER_FUNCTOR(all, (Size-1)*NumTraits<Scalar>::AddCost); 129 EIGEN_MEMBER_FUNCTOR(any, (Size-1)*NumTraits<Scalar>::AddCost); 130 EIGEN_MEMBER_FUNCTOR(count, (Size-1)*NumTraits<Scalar>::AddCost); 131 EIGEN_MEMBER_FUNCTOR(prod, (Size-1)*NumTraits<Scalar>::MulCost); 132 133 134 template <typename BinaryOp, typename Scalar> 135 struct member_redux { 136 typedef typename result_of< 137 BinaryOp(Scalar) 138 >::type result_type; 139 template<typename _Scalar, int Size> struct Cost 140 { enum { value = (Size-1) * functor_traits<BinaryOp>::Cost }; }; 141 member_redux(const BinaryOp func) : m_functor(func) {} 142 template<typename Derived> 143 inline result_type operator()(const DenseBase<Derived>& mat) const 144 { return mat.redux(m_functor); } 145 const BinaryOp m_functor; 146 }; 147 } 148 149 /** \class VectorwiseOp 150 * \ingroup Core_Module 151 * 152 * \brief Pseudo expression providing partial reduction operations 153 * 154 * \param ExpressionType the type of the object on which to do partial reductions 155 * \param Direction indicates the direction of the redux (#Vertical or #Horizontal) 156 * 157 * This class represents a pseudo expression with partial reduction features. 158 * It is the return type of DenseBase::colwise() and DenseBase::rowwise() 159 * and most of the time this is the only way it is used. 160 * 161 * Example: \include MatrixBase_colwise.cpp 162 * Output: \verbinclude MatrixBase_colwise.out 163 * 164 * \sa DenseBase::colwise(), DenseBase::rowwise(), class PartialReduxExpr 165 */ 166 template<typename ExpressionType, int Direction> class VectorwiseOp 167 { 168 public: 169 170 typedef typename ExpressionType::Scalar Scalar; 171 typedef typename ExpressionType::RealScalar RealScalar; 172 typedef typename ExpressionType::Index Index; 173 typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret, 174 ExpressionType, ExpressionType&>::type ExpressionTypeNested; 175 typedef typename internal::remove_all<ExpressionTypeNested>::type ExpressionTypeNestedCleaned; 176 177 template<template<typename _Scalar> class Functor, 178 typename Scalar=typename internal::traits<ExpressionType>::Scalar> struct ReturnType 179 { 180 typedef PartialReduxExpr<ExpressionType, 181 Functor<Scalar>, 182 Direction 183 > Type; 184 }; 185 186 template<typename BinaryOp> struct ReduxReturnType 187 { 188 typedef PartialReduxExpr<ExpressionType, 189 internal::member_redux<BinaryOp,typename internal::traits<ExpressionType>::Scalar>, 190 Direction 191 > Type; 192 }; 193 194 enum { 195 IsVertical = (Direction==Vertical) ? 1 : 0, 196 IsHorizontal = (Direction==Horizontal) ? 1 : 0 197 }; 198 199 protected: 200 201 /** \internal 202 * \returns the i-th subvector according to the \c Direction */ 203 typedef typename internal::conditional<Direction==Vertical, 204 typename ExpressionType::ColXpr, 205 typename ExpressionType::RowXpr>::type SubVector; 206 SubVector subVector(Index i) 207 { 208 return SubVector(m_matrix.derived(),i); 209 } 210 211 /** \internal 212 * \returns the number of subvectors in the direction \c Direction */ 213 Index subVectors() const 214 { return Direction==Vertical?m_matrix.cols():m_matrix.rows(); } 215 216 template<typename OtherDerived> struct ExtendedType { 217 typedef Replicate<OtherDerived, 218 Direction==Vertical ? 1 : ExpressionType::RowsAtCompileTime, 219 Direction==Horizontal ? 1 : ExpressionType::ColsAtCompileTime> Type; 220 }; 221 222 /** \internal 223 * Replicates a vector to match the size of \c *this */ 224 template<typename OtherDerived> 225 typename ExtendedType<OtherDerived>::Type 226 extendedTo(const DenseBase<OtherDerived>& other) const 227 { 228 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Vertical, OtherDerived::MaxColsAtCompileTime==1), 229 YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED) 230 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Horizontal, OtherDerived::MaxRowsAtCompileTime==1), 231 YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED) 232 return typename ExtendedType<OtherDerived>::Type 233 (other.derived(), 234 Direction==Vertical ? 1 : m_matrix.rows(), 235 Direction==Horizontal ? 1 : m_matrix.cols()); 236 } 237 238 template<typename OtherDerived> struct OppositeExtendedType { 239 typedef Replicate<OtherDerived, 240 Direction==Horizontal ? 1 : ExpressionType::RowsAtCompileTime, 241 Direction==Vertical ? 1 : ExpressionType::ColsAtCompileTime> Type; 242 }; 243 244 /** \internal 245 * Replicates a vector in the opposite direction to match the size of \c *this */ 246 template<typename OtherDerived> 247 typename OppositeExtendedType<OtherDerived>::Type 248 extendedToOpposite(const DenseBase<OtherDerived>& other) const 249 { 250 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Horizontal, OtherDerived::MaxColsAtCompileTime==1), 251 YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED) 252 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Vertical, OtherDerived::MaxRowsAtCompileTime==1), 253 YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED) 254 return typename OppositeExtendedType<OtherDerived>::Type 255 (other.derived(), 256 Direction==Horizontal ? 1 : m_matrix.rows(), 257 Direction==Vertical ? 1 : m_matrix.cols()); 258 } 259 260 public: 261 262 inline VectorwiseOp(ExpressionType& matrix) : m_matrix(matrix) {} 263 264 /** \internal */ 265 inline const ExpressionType& _expression() const { return m_matrix; } 266 267 /** \returns a row or column vector expression of \c *this reduxed by \a func 268 * 269 * The template parameter \a BinaryOp is the type of the functor 270 * of the custom redux operator. Note that func must be an associative operator. 271 * 272 * \sa class VectorwiseOp, DenseBase::colwise(), DenseBase::rowwise() 273 */ 274 template<typename BinaryOp> 275 const typename ReduxReturnType<BinaryOp>::Type 276 redux(const BinaryOp& func = BinaryOp()) const 277 { return typename ReduxReturnType<BinaryOp>::Type(_expression(), func); } 278 279 /** \returns a row (or column) vector expression of the smallest coefficient 280 * of each column (or row) of the referenced expression. 281 * 282 * \warning the result is undefined if \c *this contains NaN. 283 * 284 * Example: \include PartialRedux_minCoeff.cpp 285 * Output: \verbinclude PartialRedux_minCoeff.out 286 * 287 * \sa DenseBase::minCoeff() */ 288 const typename ReturnType<internal::member_minCoeff>::Type minCoeff() const 289 { return _expression(); } 290 291 /** \returns a row (or column) vector expression of the largest coefficient 292 * of each column (or row) of the referenced expression. 293 * 294 * \warning the result is undefined if \c *this contains NaN. 295 * 296 * Example: \include PartialRedux_maxCoeff.cpp 297 * Output: \verbinclude PartialRedux_maxCoeff.out 298 * 299 * \sa DenseBase::maxCoeff() */ 300 const typename ReturnType<internal::member_maxCoeff>::Type maxCoeff() const 301 { return _expression(); } 302 303 /** \returns a row (or column) vector expression of the squared norm 304 * of each column (or row) of the referenced expression. 305 * 306 * Example: \include PartialRedux_squaredNorm.cpp 307 * Output: \verbinclude PartialRedux_squaredNorm.out 308 * 309 * \sa DenseBase::squaredNorm() */ 310 const typename ReturnType<internal::member_squaredNorm,RealScalar>::Type squaredNorm() const 311 { return _expression(); } 312 313 /** \returns a row (or column) vector expression of the norm 314 * of each column (or row) of the referenced expression. 315 * 316 * Example: \include PartialRedux_norm.cpp 317 * Output: \verbinclude PartialRedux_norm.out 318 * 319 * \sa DenseBase::norm() */ 320 const typename ReturnType<internal::member_norm,RealScalar>::Type norm() const 321 { return _expression(); } 322 323 324 /** \returns a row (or column) vector expression of the norm 325 * of each column (or row) of the referenced expression, using 326 * blue's algorithm. 327 * 328 * \sa DenseBase::blueNorm() */ 329 const typename ReturnType<internal::member_blueNorm,RealScalar>::Type blueNorm() const 330 { return _expression(); } 331 332 333 /** \returns a row (or column) vector expression of the norm 334 * of each column (or row) of the referenced expression, avoiding 335 * underflow and overflow. 336 * 337 * \sa DenseBase::stableNorm() */ 338 const typename ReturnType<internal::member_stableNorm,RealScalar>::Type stableNorm() const 339 { return _expression(); } 340 341 342 /** \returns a row (or column) vector expression of the norm 343 * of each column (or row) of the referenced expression, avoiding 344 * underflow and overflow using a concatenation of hypot() calls. 345 * 346 * \sa DenseBase::hypotNorm() */ 347 const typename ReturnType<internal::member_hypotNorm,RealScalar>::Type hypotNorm() const 348 { return _expression(); } 349 350 /** \returns a row (or column) vector expression of the sum 351 * of each column (or row) of the referenced expression. 352 * 353 * Example: \include PartialRedux_sum.cpp 354 * Output: \verbinclude PartialRedux_sum.out 355 * 356 * \sa DenseBase::sum() */ 357 const typename ReturnType<internal::member_sum>::Type sum() const 358 { return _expression(); } 359 360 /** \returns a row (or column) vector expression of the mean 361 * of each column (or row) of the referenced expression. 362 * 363 * \sa DenseBase::mean() */ 364 const typename ReturnType<internal::member_mean>::Type mean() const 365 { return _expression(); } 366 367 /** \returns a row (or column) vector expression representing 368 * whether \b all coefficients of each respective column (or row) are \c true. 369 * 370 * \sa DenseBase::all() */ 371 const typename ReturnType<internal::member_all>::Type all() const 372 { return _expression(); } 373 374 /** \returns a row (or column) vector expression representing 375 * whether \b at \b least one coefficient of each respective column (or row) is \c true. 376 * 377 * \sa DenseBase::any() */ 378 const typename ReturnType<internal::member_any>::Type any() const 379 { return _expression(); } 380 381 /** \returns a row (or column) vector expression representing 382 * the number of \c true coefficients of each respective column (or row). 383 * 384 * Example: \include PartialRedux_count.cpp 385 * Output: \verbinclude PartialRedux_count.out 386 * 387 * \sa DenseBase::count() */ 388 const PartialReduxExpr<ExpressionType, internal::member_count<Index>, Direction> count() const 389 { return _expression(); } 390 391 /** \returns a row (or column) vector expression of the product 392 * of each column (or row) of the referenced expression. 393 * 394 * Example: \include PartialRedux_prod.cpp 395 * Output: \verbinclude PartialRedux_prod.out 396 * 397 * \sa DenseBase::prod() */ 398 const typename ReturnType<internal::member_prod>::Type prod() const 399 { return _expression(); } 400 401 402 /** \returns a matrix expression 403 * where each column (or row) are reversed. 404 * 405 * Example: \include Vectorwise_reverse.cpp 406 * Output: \verbinclude Vectorwise_reverse.out 407 * 408 * \sa DenseBase::reverse() */ 409 const Reverse<ExpressionType, Direction> reverse() const 410 { return Reverse<ExpressionType, Direction>( _expression() ); } 411 412 typedef Replicate<ExpressionType,Direction==Vertical?Dynamic:1,Direction==Horizontal?Dynamic:1> ReplicateReturnType; 413 const ReplicateReturnType replicate(Index factor) const; 414 415 /** 416 * \return an expression of the replication of each column (or row) of \c *this 417 * 418 * Example: \include DirectionWise_replicate.cpp 419 * Output: \verbinclude DirectionWise_replicate.out 420 * 421 * \sa VectorwiseOp::replicate(Index), DenseBase::replicate(), class Replicate 422 */ 423 // NOTE implemented here because of sunstudio's compilation errors 424 template<int Factor> const Replicate<ExpressionType,(IsVertical?Factor:1),(IsHorizontal?Factor:1)> 425 replicate(Index factor = Factor) const 426 { 427 return Replicate<ExpressionType,Direction==Vertical?Factor:1,Direction==Horizontal?Factor:1> 428 (_expression(),Direction==Vertical?factor:1,Direction==Horizontal?factor:1); 429 } 430 431 /////////// Artithmetic operators /////////// 432 433 /** Copies the vector \a other to each subvector of \c *this */ 434 template<typename OtherDerived> 435 ExpressionType& operator=(const DenseBase<OtherDerived>& other) 436 { 437 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 438 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 439 //eigen_assert((m_matrix.isNull()) == (other.isNull())); FIXME 440 return const_cast<ExpressionType&>(m_matrix = extendedTo(other.derived())); 441 } 442 443 /** Adds the vector \a other to each subvector of \c *this */ 444 template<typename OtherDerived> 445 ExpressionType& operator+=(const DenseBase<OtherDerived>& other) 446 { 447 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 448 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 449 return const_cast<ExpressionType&>(m_matrix += extendedTo(other.derived())); 450 } 451 452 /** Substracts the vector \a other to each subvector of \c *this */ 453 template<typename OtherDerived> 454 ExpressionType& operator-=(const DenseBase<OtherDerived>& other) 455 { 456 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 457 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 458 return const_cast<ExpressionType&>(m_matrix -= extendedTo(other.derived())); 459 } 460 461 /** Multiples each subvector of \c *this by the vector \a other */ 462 template<typename OtherDerived> 463 ExpressionType& operator*=(const DenseBase<OtherDerived>& other) 464 { 465 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 466 EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) 467 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 468 m_matrix *= extendedTo(other.derived()); 469 return const_cast<ExpressionType&>(m_matrix); 470 } 471 472 /** Divides each subvector of \c *this by the vector \a other */ 473 template<typename OtherDerived> 474 ExpressionType& operator/=(const DenseBase<OtherDerived>& other) 475 { 476 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 477 EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) 478 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 479 m_matrix /= extendedTo(other.derived()); 480 return const_cast<ExpressionType&>(m_matrix); 481 } 482 483 /** Returns the expression of the sum of the vector \a other to each subvector of \c *this */ 484 template<typename OtherDerived> EIGEN_STRONG_INLINE 485 CwiseBinaryOp<internal::scalar_sum_op<Scalar>, 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 495 /** Returns the expression of the difference between each subvector of \c *this and the vector \a other */ 496 template<typename OtherDerived> 497 CwiseBinaryOp<internal::scalar_difference_op<Scalar>, 498 const ExpressionTypeNestedCleaned, 499 const typename ExtendedType<OtherDerived>::Type> 500 operator-(const DenseBase<OtherDerived>& other) const 501 { 502 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 503 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 504 return m_matrix - extendedTo(other.derived()); 505 } 506 507 /** Returns the expression where each subvector is the product of the vector \a other 508 * by the corresponding subvector of \c *this */ 509 template<typename OtherDerived> EIGEN_STRONG_INLINE 510 CwiseBinaryOp<internal::scalar_product_op<Scalar>, 511 const ExpressionTypeNestedCleaned, 512 const typename ExtendedType<OtherDerived>::Type> 513 operator*(const DenseBase<OtherDerived>& other) const 514 { 515 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 516 EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) 517 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 518 return m_matrix * extendedTo(other.derived()); 519 } 520 521 /** Returns the expression where each subvector is the quotient of the corresponding 522 * subvector of \c *this by the vector \a other */ 523 template<typename OtherDerived> 524 CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, 525 const ExpressionTypeNestedCleaned, 526 const typename ExtendedType<OtherDerived>::Type> 527 operator/(const DenseBase<OtherDerived>& other) const 528 { 529 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) 530 EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) 531 EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) 532 return m_matrix / extendedTo(other.derived()); 533 } 534 535 /** \returns an expression where each column of row of the referenced matrix are normalized. 536 * The referenced matrix is \b not modified. 537 * \sa MatrixBase::normalized(), normalize() 538 */ 539 CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, 540 const ExpressionTypeNestedCleaned, 541 const typename OppositeExtendedType<typename ReturnType<internal::member_norm,RealScalar>::Type>::Type> 542 normalized() const { return m_matrix.cwiseQuotient(extendedToOpposite(this->norm())); } 543 544 545 /** Normalize in-place each row or columns of the referenced matrix. 546 * \sa MatrixBase::normalize(), normalized() 547 */ 548 void normalize() { 549 m_matrix = this->normalized(); 550 } 551 552 /////////// Geometry module /////////// 553 554 #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS 555 Homogeneous<ExpressionType,Direction> homogeneous() const; 556 #endif 557 558 typedef typename ExpressionType::PlainObject CrossReturnType; 559 template<typename OtherDerived> 560 const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const; 561 562 enum { 563 HNormalized_Size = Direction==Vertical ? internal::traits<ExpressionType>::RowsAtCompileTime 564 : internal::traits<ExpressionType>::ColsAtCompileTime, 565 HNormalized_SizeMinusOne = HNormalized_Size==Dynamic ? Dynamic : HNormalized_Size-1 566 }; 567 typedef Block<const ExpressionType, 568 Direction==Vertical ? int(HNormalized_SizeMinusOne) 569 : int(internal::traits<ExpressionType>::RowsAtCompileTime), 570 Direction==Horizontal ? int(HNormalized_SizeMinusOne) 571 : int(internal::traits<ExpressionType>::ColsAtCompileTime)> 572 HNormalized_Block; 573 typedef Block<const ExpressionType, 574 Direction==Vertical ? 1 : int(internal::traits<ExpressionType>::RowsAtCompileTime), 575 Direction==Horizontal ? 1 : int(internal::traits<ExpressionType>::ColsAtCompileTime)> 576 HNormalized_Factors; 577 typedef CwiseBinaryOp<internal::scalar_quotient_op<typename internal::traits<ExpressionType>::Scalar>, 578 const HNormalized_Block, 579 const Replicate<HNormalized_Factors, 580 Direction==Vertical ? HNormalized_SizeMinusOne : 1, 581 Direction==Horizontal ? HNormalized_SizeMinusOne : 1> > 582 HNormalizedReturnType; 583 584 const HNormalizedReturnType hnormalized() const; 585 586 protected: 587 ExpressionTypeNested m_matrix; 588 }; 589 590 /** \returns a VectorwiseOp wrapper of *this providing additional partial reduction operations 591 * 592 * Example: \include MatrixBase_colwise.cpp 593 * Output: \verbinclude MatrixBase_colwise.out 594 * 595 * \sa rowwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting 596 */ 597 template<typename Derived> 598 inline const typename DenseBase<Derived>::ConstColwiseReturnType 599 DenseBase<Derived>::colwise() const 600 { 601 return derived(); 602 } 603 604 /** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations 605 * 606 * \sa rowwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting 607 */ 608 template<typename Derived> 609 inline typename DenseBase<Derived>::ColwiseReturnType 610 DenseBase<Derived>::colwise() 611 { 612 return derived(); 613 } 614 615 /** \returns a VectorwiseOp wrapper of *this providing additional partial reduction operations 616 * 617 * Example: \include MatrixBase_rowwise.cpp 618 * Output: \verbinclude MatrixBase_rowwise.out 619 * 620 * \sa colwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting 621 */ 622 template<typename Derived> 623 inline const typename DenseBase<Derived>::ConstRowwiseReturnType 624 DenseBase<Derived>::rowwise() const 625 { 626 return derived(); 627 } 628 629 /** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations 630 * 631 * \sa colwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting 632 */ 633 template<typename Derived> 634 inline typename DenseBase<Derived>::RowwiseReturnType 635 DenseBase<Derived>::rowwise() 636 { 637 return derived(); 638 } 639 640 } // end namespace Eigen 641 642 #endif // EIGEN_PARTIAL_REDUX_H 643