TensorTrace.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2017 Gagan Goel <gagan.nith@gmail.com>
5 // Copyright (C) 2017 Benoit Steiner <benoit.steiner.goog@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_CXX11_TENSOR_TENSOR_TRACE_H
12 #define EIGEN_CXX11_TENSOR_TENSOR_TRACE_H
13 
14 // IWYU pragma: private
15 #include "./InternalHeaderCheck.h"
16 
17 namespace Eigen {
18 
27 namespace internal {
28 template <typename Dims, typename XprType>
29 struct traits<TensorTraceOp<Dims, XprType> > : public traits<XprType> {
30  typedef typename XprType::Scalar Scalar;
32  typedef typename XprTraits::StorageKind StorageKind;
33  typedef typename XprTraits::Index Index;
34  typedef typename XprType::Nested Nested;
35  typedef std::remove_reference_t<Nested> Nested_;
36  static constexpr int NumDimensions = XprTraits::NumDimensions - array_size<Dims>::value;
37  static constexpr int Layout = XprTraits::Layout;
38 };
39 
40 template <typename Dims, typename XprType>
41 struct eval<TensorTraceOp<Dims, XprType>, Eigen::Dense> {
43 };
44 
45 template <typename Dims, typename XprType>
46 struct nested<TensorTraceOp<Dims, XprType>, 1, typename eval<TensorTraceOp<Dims, XprType> >::type> {
48 };
49 
50 } // end namespace internal
51 
52 template <typename Dims, typename XprType>
53 class TensorTraceOp : public TensorBase<TensorTraceOp<Dims, XprType> > {
54  public:
57  typedef typename XprType::CoeffReturnType CoeffReturnType;
61 
63  : m_xpr(expr), m_dims(dims) {}
64 
65  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dims& dims() const { return m_dims; }
66 
68  return m_xpr;
69  }
70 
71  protected:
72  typename XprType::Nested m_xpr;
73  const Dims m_dims;
74 };
75 
76 // Eval as rvalue
77 template <typename Dims, typename ArgType, typename Device>
78 struct TensorEvaluator<const TensorTraceOp<Dims, ArgType>, Device> {
80  static constexpr int NumInputDims =
82  static constexpr int NumReducedDims = internal::array_size<Dims>::value;
83  static constexpr int NumOutputDims = NumInputDims - NumReducedDims;
84  typedef typename XprType::Index Index;
86  typedef typename XprType::Scalar Scalar;
92 
94  enum {
95  IsAligned = false,
97  BlockAccess = false,
99  CoordAccess = false,
100  RawAccess = false
101  };
102 
103  //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
105  //===--------------------------------------------------------------------===//
106 
107  EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
108  : m_impl(op.expression(), device), m_traceDim(1), m_device(device) {
109  EIGEN_STATIC_ASSERT((NumOutputDims >= 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
110  EIGEN_STATIC_ASSERT((NumReducedDims >= 2) || ((NumReducedDims == 0) && (NumInputDims == 0)),
111  YOU_MADE_A_PROGRAMMING_MISTAKE);
112 
113  for (int i = 0; i < NumInputDims; ++i) {
114  m_reduced[i] = false;
115  }
116 
117  const Dims& op_dims = op.dims();
118  for (int i = 0; i < NumReducedDims; ++i) {
119  eigen_assert(op_dims[i] >= 0);
120  eigen_assert(op_dims[i] < NumInputDims);
121  m_reduced[op_dims[i]] = true;
122  }
123 
124  // All the dimensions should be distinct to compute the trace
125  int num_distinct_reduce_dims = 0;
126  for (int i = 0; i < NumInputDims; ++i) {
127  if (m_reduced[i]) {
128  ++num_distinct_reduce_dims;
129  }
130  }
131 
132  EIGEN_ONLY_USED_FOR_DEBUG(num_distinct_reduce_dims);
133  eigen_assert(num_distinct_reduce_dims == NumReducedDims);
134 
135  // Compute the dimensions of the result.
136  const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
137 
138  int output_index = 0;
139  int reduced_index = 0;
140  for (int i = 0; i < NumInputDims; ++i) {
141  if (m_reduced[i]) {
142  m_reducedDims[reduced_index] = input_dims[i];
143  if (reduced_index > 0) {
144  // All the trace dimensions must have the same size
145  eigen_assert(m_reducedDims[0] == m_reducedDims[reduced_index]);
146  }
147  ++reduced_index;
148  } else {
149  m_dimensions[output_index] = input_dims[i];
150  ++output_index;
151  }
152  }
153 
154  if (NumReducedDims != 0) {
155  m_traceDim = m_reducedDims[0];
156  }
157 
158  // Compute the output strides
159  if (NumOutputDims > 0) {
160  if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
161  m_outputStrides[0] = 1;
162  for (int i = 1; i < NumOutputDims; ++i) {
163  m_outputStrides[i] = m_outputStrides[i - 1] * m_dimensions[i - 1];
164  }
165  } else {
166  m_outputStrides.back() = 1;
167  for (int i = NumOutputDims - 2; i >= 0; --i) {
168  m_outputStrides[i] = m_outputStrides[i + 1] * m_dimensions[i + 1];
169  }
170  }
171  }
172 
173  // Compute the input strides
174  if (NumInputDims > 0) {
175  array<Index, NumInputDims> input_strides;
176  if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
177  input_strides[0] = 1;
178  for (int i = 1; i < NumInputDims; ++i) {
179  input_strides[i] = input_strides[i - 1] * input_dims[i - 1];
180  }
181  } else {
182  input_strides.back() = 1;
183  for (int i = NumInputDims - 2; i >= 0; --i) {
184  input_strides[i] = input_strides[i + 1] * input_dims[i + 1];
185  }
186  }
187 
188  output_index = 0;
189  reduced_index = 0;
190  for (int i = 0; i < NumInputDims; ++i) {
191  if (m_reduced[i]) {
192  m_reducedStrides[reduced_index] = input_strides[i];
193  ++reduced_index;
194  } else {
195  m_preservedStrides[output_index] = input_strides[i];
196  ++output_index;
197  }
198  }
199  }
200  }
201 
202  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }
203 
205  m_impl.evalSubExprsIfNeeded(NULL);
206  return true;
207  }
208 
209  EIGEN_STRONG_INLINE void cleanup() { m_impl.cleanup(); }
210 
212  // Initialize the result
213  CoeffReturnType result = internal::cast<int, CoeffReturnType>(0);
214  Index index_stride = 0;
215  for (int i = 0; i < NumReducedDims; ++i) {
216  index_stride += m_reducedStrides[i];
217  }
218 
219  // If trace is requested along all dimensions, starting index would be 0
220  Index cur_index = 0;
221  if (NumOutputDims != 0) cur_index = firstInput(index);
222  for (Index i = 0; i < m_traceDim; ++i) {
223  result += m_impl.coeff(cur_index);
224  cur_index += index_stride;
225  }
226 
227  return result;
228  }
229 
230  template <int LoadMode>
232  eigen_assert(index + PacketSize - 1 < dimensions().TotalSize());
233 
234  EIGEN_ALIGN_MAX std::remove_const_t<CoeffReturnType> values[PacketSize];
235  for (int i = 0; i < PacketSize; ++i) {
236  values[i] = coeff(index + i);
237  }
238  PacketReturnType result = internal::ploadt<PacketReturnType, LoadMode>(values);
239  return result;
240  }
241 
242  protected:
243  // Given the output index, finds the first index in the input tensor used to compute the trace
245  Index startInput = 0;
246  if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
247  for (int i = NumOutputDims - 1; i > 0; --i) {
248  const Index idx = index / m_outputStrides[i];
249  startInput += idx * m_preservedStrides[i];
250  index -= idx * m_outputStrides[i];
251  }
252  startInput += index * m_preservedStrides[0];
253  } else {
254  for (int i = 0; i < NumOutputDims - 1; ++i) {
255  const Index idx = index / m_outputStrides[i];
256  startInput += idx * m_preservedStrides[i];
257  index -= idx * m_outputStrides[i];
258  }
259  startInput += index * m_preservedStrides[NumOutputDims - 1];
260  }
261  return startInput;
262  }
263 
266  // Initialize the size of the trace dimension
274 };
275 
276 } // End namespace Eigen
277 
278 #endif // EIGEN_CXX11_TENSOR_TENSOR_TRACE_H
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define EIGEN_ALIGN_MAX
Definition: ConfigureVectorization.h:146
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:892
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
Definition: Macros.h:922
#define eigen_assert(x)
Definition: Macros.h:910
#define EIGEN_STRONG_INLINE
Definition: Macros.h:834
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
#define EIGEN_DEVICE_REF
Definition: TensorMacros.h:34
SCALAR Scalar
Definition: bench_gemm.cpp:45
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseBinaryOp.h:79
The tensor base class.
Definition: TensorBase.h:1026
Definition: TensorTrace.h:53
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t< typename XprType::Nested > & expression() const
Definition: TensorTrace.h:67
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dims & dims() const
Definition: TensorTrace.h:65
Eigen::internal::nested< TensorTraceOp >::type Nested
Definition: TensorTrace.h:58
const Dims m_dims
Definition: TensorTrace.h:73
XprType::Nested m_xpr
Definition: TensorTrace.h:72
XprType::CoeffReturnType CoeffReturnType
Definition: TensorTrace.h:57
Eigen::internal::traits< TensorTraceOp >::StorageKind StorageKind
Definition: TensorTrace.h:59
Eigen::internal::traits< TensorTraceOp >::Scalar Scalar
Definition: TensorTrace.h:55
Eigen::NumTraits< Scalar >::Real RealScalar
Definition: TensorTrace.h:56
Eigen::internal::traits< TensorTraceOp >::Index Index
Definition: TensorTrace.h:60
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorTraceOp(const XprType &expr, const Dims &dims)
Definition: TensorTrace.h:62
Definition: TensorBlock.h:566
@ ColMajor
Definition: Constants.h:318
char char * op
Definition: level2_impl.h:374
typename remove_all< T >::type remove_all_t
Definition: Meta.h:142
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
std::array< T, N > array
Definition: EmulateArray.h:231
squared absolute value
Definition: GlobalFunctions.h:87
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
Definition: Eigen_Colamd.h:49
Definition: Constants.h:519
T Real
Definition: NumTraits.h:183
Definition: TensorForwardDeclarations.h:42
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
Definition: TensorTrace.h:211
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions & dimensions() const
Definition: TensorTrace.h:202
internal::TensorBlockNotImplemented TensorBlock
Definition: TensorTrace.h:104
array< Index, NumOutputDims > m_preservedStrides
Definition: TensorTrace.h:273
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index firstInput(Index index) const
Definition: TensorTrace.h:244
array< Index, NumReducedDims > m_reducedDims
Definition: TensorTrace.h:270
array< bool, NumInputDims > m_reduced
Definition: TensorTrace.h:269
PacketType< CoeffReturnType, Device >::type PacketReturnType
Definition: TensorTrace.h:88
EIGEN_STRONG_INLINE void cleanup()
Definition: TensorTrace.h:209
Storage::Type EvaluatorPointerType
Definition: TensorTrace.h:91
TensorTraceOp< Dims, ArgType > XprType
Definition: TensorTrace.h:79
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
Definition: TensorTrace.h:231
array< Index, NumReducedDims > m_reducedStrides
Definition: TensorTrace.h:272
const Device EIGEN_DEVICE_REF m_device
Definition: TensorTrace.h:268
XprType::CoeffReturnType CoeffReturnType
Definition: TensorTrace.h:87
array< Index, NumOutputDims > m_outputStrides
Definition: TensorTrace.h:271
EIGEN_STRONG_INLINE TensorEvaluator(const XprType &op, const Device &device)
Definition: TensorTrace.h:107
TensorEvaluator< ArgType, Device > m_impl
Definition: TensorTrace.h:265
StorageMemory< CoeffReturnType, Device > Storage
Definition: TensorTrace.h:90
EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(EvaluatorPointerType)
Definition: TensorTrace.h:204
DSizes< Index, NumOutputDims > Dimensions
Definition: TensorTrace.h:85
A cost model used to limit the number of threads used for evaluating tensor expression.
Definition: TensorEvaluator.h:31
static constexpr int Layout
Definition: TensorEvaluator.h:46
const Device EIGEN_DEVICE_REF m_device
Definition: TensorEvaluator.h:170
@ PacketAccess
Definition: TensorEvaluator.h:50
@ IsAligned
Definition: TensorEvaluator.h:49
static constexpr int PacketSize
Definition: TensorEvaluator.h:38
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
Definition: TensorEvaluator.h:89
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions & dimensions() const
Definition: TensorEvaluator.h:69
Definition: Meta.h:305
const TensorTraceOp< Dims, XprType > & type
Definition: TensorTrace.h:42
Definition: XprHelper.h:427
Definition: TensorTraits.h:152
ref_selector< T >::type type
Definition: TensorTraits.h:153
std::remove_reference_t< Nested > Nested_
Definition: TensorTrace.h:35
XprType::Scalar Scalar
Definition: TensorTrace.h:30
XprType::Nested Nested
Definition: TensorTrace.h:34
XprTraits::StorageKind StorageKind
Definition: TensorTrace.h:32
traits< XprType > XprTraits
Definition: TensorTrace.h:31
XprTraits::Index Index
Definition: TensorTrace.h:33
Definition: ForwardDeclarations.h:21
Definition: GenericPacketMath.h:134