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