1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library 2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra. 3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> 6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla 8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed 9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_REDUX_H 12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_REDUX_H 13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen { 15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal { 17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// TODO 19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// * implement other kind of vectorization 20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// * factorize code 21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*************************************************************************** 23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* Part 1 : the logic deciding a strategy for vectorization and unrolling 24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath***************************************************************************/ 25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived> 27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_traits 28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic: 30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath PacketSize = packet_traits<typename Derived::Scalar>::size, 32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath InnerMaxSize = int(Derived::IsRowMajor) 33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ? Derived::MaxColsAtCompileTime 34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : Derived::MaxRowsAtCompileTime 35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MightVectorize = (int(Derived::Flags)&ActualPacketAccessBit) 39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath && (functor_traits<Func>::PacketAccess), 40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MayLinearVectorize = MightVectorize && (int(Derived::Flags)&LinearAccessBit), 41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MaySliceVectorize = MightVectorize && int(InnerMaxSize)>=3*PacketSize 42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic: 45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Traversal = int(MayLinearVectorize) ? int(LinearVectorizedTraversal) 47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : int(MaySliceVectorize) ? int(SliceVectorizedTraversal) 48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : int(DefaultTraversal) 49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic: 52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cost = ( Derived::SizeAtCompileTime == Dynamic 54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath || Derived::CoeffReadCost == Dynamic 55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath || (Derived::SizeAtCompileTime!=1 && functor_traits<Func>::Cost == Dynamic) 56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ) ? Dynamic 57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : Derived::SizeAtCompileTime * Derived::CoeffReadCost 58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath + (Derived::SizeAtCompileTime-1) * functor_traits<Func>::Cost, 59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize)) 60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic: 63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Unrolling = Cost != Dynamic && Cost <= UnrollingLimit 65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ? CompleteUnrolling 66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : NoUnrolling 67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*************************************************************************** 71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* Part 2 : unrollers 72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath***************************************************************************/ 73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*** no vectorization ***/ 75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived, int Start, int Length> 77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_novec_unroller 78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath HalfLength = Length/2 81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func) 86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func), 88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath redux_novec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func)); 89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived, int Start> 93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_novec_unroller<Func, Derived, Start, 1> 94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath outer = Start / Derived::InnerSizeAtCompileTime, 97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath inner = Start % Derived::InnerSizeAtCompileTime 98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func&) 103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return mat.coeffByOuterInner(outer, inner); 105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This is actually dead code and will never be called. It is required 109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// to prevent false warnings regarding failed inlining though 110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for 0 length run() will never be called at all. 111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived, int Start> 112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_novec_unroller<Func, Derived, Start, 0> 113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE Scalar run(const Derived&, const Func&) { return Scalar(); } 116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*** vectorization ***/ 119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived, int Start, int Length> 121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_vec_unroller 122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath PacketSize = packet_traits<typename Derived::Scalar>::size, 125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath HalfLength = Length/2 126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename packet_traits<Scalar>::type PacketScalar; 130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE PacketScalar run(const Derived &mat, const Func& func) 132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return func.packetOp( 134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath redux_vec_unroller<Func, Derived, Start, HalfLength>::run(mat,func), 135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath redux_vec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func) ); 136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived, int Start> 140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_vec_unroller<Func, Derived, Start, 1> 141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath index = Start * packet_traits<typename Derived::Scalar>::size, 144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath outer = index / int(Derived::InnerSizeAtCompileTime), 145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath inner = index % int(Derived::InnerSizeAtCompileTime), 146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath alignment = (Derived::Flags & AlignedBit) ? Aligned : Unaligned 147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename packet_traits<Scalar>::type PacketScalar; 151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE PacketScalar run(const Derived &mat, const Func&) 153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return mat.template packetByOuterInner<alignment>(outer, inner); 155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*************************************************************************** 159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* Part 3 : implementation of all cases 160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath***************************************************************************/ 161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived, 163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int Traversal = redux_traits<Func, Derived>::Traversal, 164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int Unrolling = redux_traits<Func, Derived>::Unrolling 165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath> 166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_impl; 167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived> 169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_impl<Func, Derived, DefaultTraversal, NoUnrolling> 170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Index Index; 173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func) 174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); 176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Scalar res; 177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = mat.coeffByOuterInner(0, 0); 178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index i = 1; i < mat.innerSize(); ++i) 179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res, mat.coeffByOuterInner(0, i)); 180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index i = 1; i < mat.outerSize(); ++i) 181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index j = 0; j < mat.innerSize(); ++j) 182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res, mat.coeffByOuterInner(i, j)); 183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return res; 184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived> 188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_impl<Func,Derived, DefaultTraversal, CompleteUnrolling> 189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : public redux_novec_unroller<Func,Derived, 0, Derived::SizeAtCompileTime> 190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{}; 191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived> 193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling> 194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename packet_traits<Scalar>::type PacketScalar; 197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Index Index; 198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static Scalar run(const Derived& mat, const Func& func) 200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index size = mat.size(); 202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath eigen_assert(size && "you are using an empty matrix"); 203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index packetSize = packet_traits<Scalar>::size; 204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index alignedStart = internal::first_aligned(mat); 205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath alignment = bool(Derived::Flags & DirectAccessBit) || bool(Derived::Flags & AlignedBit) 207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ? Aligned : Unaligned 208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize); 210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index alignedSize = ((size-alignedStart)/(packetSize))*(packetSize); 211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index alignedEnd2 = alignedStart + alignedSize2; 212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index alignedEnd = alignedStart + alignedSize; 213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Scalar res; 214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(alignedSize) 215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath PacketScalar packet_res0 = mat.template packet<alignment>(alignedStart); 217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(alignedSize>packetSize) // we have at least two packets to partly unroll the loop 218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath PacketScalar packet_res1 = mat.template packet<alignment>(alignedStart+packetSize); 220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index index = alignedStart + 2*packetSize; index < alignedEnd2; index += 2*packetSize) 221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment>(index)); 223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath packet_res1 = func.packetOp(packet_res1, mat.template packet<alignment>(index+packetSize)); 224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath packet_res0 = func.packetOp(packet_res0,packet_res1); 227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(alignedEnd>alignedEnd2) 228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment>(alignedEnd2)); 229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func.predux(packet_res0); 231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index index = 0; index < alignedStart; ++index) 233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res,mat.coeff(index)); 234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index index = alignedEnd; index < size; ++index) 236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res,mat.coeff(index)); 237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else // too small to vectorize anything. 239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize. 240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = mat.coeff(0); 242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index index = 1; index < size; ++index) 243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res,mat.coeff(index)); 244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return res; 247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived> 251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_impl<Func, Derived, SliceVectorizedTraversal, NoUnrolling> 252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename packet_traits<Scalar>::type PacketScalar; 255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Index Index; 256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static Scalar run(const Derived& mat, const Func& func) 258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); 260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index innerSize = mat.innerSize(); 261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index outerSize = mat.outerSize(); 262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath packetSize = packet_traits<Scalar>::size 264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Index packetedInnerSize = ((innerSize)/packetSize)*packetSize; 266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Scalar res; 267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(packetedInnerSize) 268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath PacketScalar packet_res = mat.template packet<Unaligned>(0,0); 270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index j=0; j<outerSize; ++j) 271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index i=(j==0?packetSize:0); i<packetedInnerSize; i+=Index(packetSize)) 272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath packet_res = func.packetOp(packet_res, mat.template packetByOuterInner<Unaligned>(j,i)); 273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func.predux(packet_res); 275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index j=0; j<outerSize; ++j) 276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(Index i=packetedInnerSize; i<innerSize; ++i) 277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res, mat.coeffByOuterInner(j,i)); 278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else // too small to vectorize anything. 280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize. 281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>::run(mat, func); 283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return res; 286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func, typename Derived> 290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct redux_impl<Func, Derived, LinearVectorizedTraversal, CompleteUnrolling> 291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename Derived::Scalar Scalar; 293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename packet_traits<Scalar>::type PacketScalar; 294c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 295c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath PacketSize = packet_traits<Scalar>::size, 296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Size = Derived::SizeAtCompileTime, 297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VectorizedSize = (Size / PacketSize) * PacketSize 298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func) 300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); 302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Scalar res = func.predux(redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func)); 303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (VectorizedSize != Size) 304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func)); 305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return res; 306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 308c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 309c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace internal 310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 311c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*************************************************************************** 312c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* Part 4 : public API 313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath***************************************************************************/ 314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the result of a full redux operation on the whole matrix or vector using \a func 317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * The template parameter \a BinaryOp is the type of the functor \a func which must be 319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * an associative operator. Both current STL and TR1 functor styles are handled. 320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \sa DenseBase::sum(), DenseBase::minCoeff(), DenseBase::maxCoeff(), MatrixBase::colwise(), MatrixBase::rowwise() 322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */ 323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Func> 325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::result_of<Func(typename internal::traits<Derived>::Scalar)>::type 326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathDenseBase<Derived>::redux(const Func& func) const 327c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 328c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename internal::remove_all<typename Derived::Nested>::type ThisNested; 329c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return internal::redux_impl<Func, ThisNested> 330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ::run(derived(), func); 331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 3337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** \returns the minimum of all coefficients of \c *this. 3347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \warning the result is undefined if \c *this contains NaN. 335c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */ 336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar 338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathDenseBase<Derived>::minCoeff() const 339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return this->redux(Eigen::internal::scalar_min_op<Scalar>()); 341c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 3437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** \returns the maximum of all coefficients of \c *this. 3447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \warning the result is undefined if \c *this contains NaN. 345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */ 346c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 347c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar 348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathDenseBase<Derived>::maxCoeff() const 349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return this->redux(Eigen::internal::scalar_max_op<Scalar>()); 351c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 352c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 353c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the sum of all coefficients of *this 354c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 355c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \sa trace(), prod(), mean() 356c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */ 357c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 358c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar 359c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathDenseBase<Derived>::sum() const 360c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 361c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0)) 362c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return Scalar(0); 363c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return this->redux(Eigen::internal::scalar_sum_op<Scalar>()); 364c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 365c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 366c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the mean of all coefficients of *this 367c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* 368c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* \sa trace(), prod(), sum() 369c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath*/ 370c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 371c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar 372c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathDenseBase<Derived>::mean() const 373c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 374c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return Scalar(this->redux(Eigen::internal::scalar_sum_op<Scalar>())) / Scalar(this->size()); 375c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 376c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 377c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the product of all coefficients of *this 378c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 379c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * Example: \include MatrixBase_prod.cpp 380c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * Output: \verbinclude MatrixBase_prod.out 381c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 382c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \sa sum(), mean(), trace() 383c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */ 384c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 385c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar 386c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathDenseBase<Derived>::prod() const 387c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 388c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0)) 389c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return Scalar(1); 390c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return this->redux(Eigen::internal::scalar_product_op<Scalar>()); 391c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 392c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 393c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the trace of \c *this, i.e. the sum of the coefficients on the main diagonal. 394c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 395c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \c *this can be any matrix, not necessarily square. 396c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * 397c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \sa diagonal(), sum() 398c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */ 399c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived> 400c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar 401c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathMatrixBase<Derived>::trace() const 402c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 403c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return derived().diagonal().sum(); 404c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 405c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 406c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen 407c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 408c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_REDUX_H 409