1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_CXX11_TENSOR_TENSOR_BASE_H
11 #define EIGEN_CXX11_TENSOR_TENSOR_BASE_H
12 
13 // clang-format off
14 
15 namespace Eigen {
16 
17 /** \class TensorBase
18   * \ingroup CXX11_Tensor_Module
19   *
20   * \brief The tensor base class.
21   *
22   * This class is the common parent of the Tensor and TensorMap class, thus
23   * making it possible to use either class interchangably in expressions.
24   */
25 
26 template<typename Derived>
27 class TensorBase<Derived, ReadOnlyAccessors>
28 {
29   public:
30     typedef internal::traits<Derived> DerivedTraits;
31     typedef typename DerivedTraits::Scalar Scalar;
32     typedef typename DerivedTraits::Index Index;
33     typedef typename internal::remove_const<Scalar>::type CoeffReturnType;
34     static const int NumDimensions = DerivedTraits::NumDimensions;
35 
36     // Generic nullary operation support.
37     template <typename CustomNullaryOp> EIGEN_DEVICE_FUNC
38     EIGEN_STRONG_INLINE const TensorCwiseNullaryOp<CustomNullaryOp, const Derived>
nullaryExpr(const CustomNullaryOp & func)39     nullaryExpr(const CustomNullaryOp& func) const {
40       return TensorCwiseNullaryOp<CustomNullaryOp, const Derived>(derived(), func);
41     }
42 
43     // Coefficient-wise nullary operators
44     EIGEN_DEVICE_FUNC
45     EIGEN_STRONG_INLINE const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived>
constant(const Scalar & value)46     constant(const Scalar& value) const {
47       return nullaryExpr(internal::scalar_constant_op<Scalar>(value));
48     }
49 
50     EIGEN_DEVICE_FUNC
51     EIGEN_STRONG_INLINE const TensorCwiseNullaryOp<internal::UniformRandomGenerator<Scalar>, const Derived>
random()52     random() const {
53       return nullaryExpr(internal::UniformRandomGenerator<Scalar>());
54     }
55     template <typename RandomGenerator> EIGEN_DEVICE_FUNC
56     EIGEN_STRONG_INLINE const TensorCwiseNullaryOp<RandomGenerator, const Derived>
57     random(const RandomGenerator& gen = RandomGenerator()) const {
58       return nullaryExpr(gen);
59     }
60 
61     // Tensor generation
62     template <typename Generator> EIGEN_DEVICE_FUNC
63     EIGEN_STRONG_INLINE const TensorGeneratorOp<Generator, const Derived>
generate(const Generator & generator)64     generate(const Generator& generator) const {
65       return TensorGeneratorOp<Generator, const Derived>(derived(), generator);
66     }
67 
68     // Generic unary operation support.
69     template <typename CustomUnaryOp> EIGEN_DEVICE_FUNC
70     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<CustomUnaryOp, const Derived>
unaryExpr(const CustomUnaryOp & func)71     unaryExpr(const CustomUnaryOp& func) const {
72       return TensorCwiseUnaryOp<CustomUnaryOp, const Derived>(derived(), func);
73     }
74 
75     // Coefficient-wise unary operators
76     EIGEN_DEVICE_FUNC
77     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const Derived>
78     operator-() const {
79       return unaryExpr(internal::scalar_opposite_op<Scalar>());
80     }
81 
82     EIGEN_DEVICE_FUNC
83     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_sqrt_op<Scalar>, const Derived>
sqrt()84     sqrt() const {
85       return unaryExpr(internal::scalar_sqrt_op<Scalar>());
86     }
87 
88     EIGEN_DEVICE_FUNC
89     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_sign_op<Scalar>, const Derived>
sign()90     sign() const {
91       return unaryExpr(internal::scalar_sign_op<Scalar>());
92     }
93 
94     EIGEN_DEVICE_FUNC
95     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_rsqrt_op<Scalar>, const Derived>
rsqrt()96     rsqrt() const {
97       return unaryExpr(internal::scalar_rsqrt_op<Scalar>());
98     }
99 
100     EIGEN_DEVICE_FUNC
101     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_square_op<Scalar>, const Derived>
square()102     square() const {
103       return unaryExpr(internal::scalar_square_op<Scalar>());
104     }
105 
106     EIGEN_DEVICE_FUNC
107     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_cube_op<Scalar>, const Derived>
cube()108     cube() const {
109       return unaryExpr(internal::scalar_cube_op<Scalar>());
110     }
111 
112     EIGEN_DEVICE_FUNC
113     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const Derived>
inverse()114     inverse() const {
115       return unaryExpr(internal::scalar_inverse_op<Scalar>());
116     }
117 
118     EIGEN_DEVICE_FUNC
119     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_tanh_op<Scalar>, const Derived>
tanh()120     tanh() const {
121       return unaryExpr(internal::scalar_tanh_op<Scalar>());
122     }
123 
124     EIGEN_DEVICE_FUNC
125     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_lgamma_op<Scalar>, const Derived>
lgamma()126     lgamma() const {
127       return unaryExpr(internal::scalar_lgamma_op<Scalar>());
128     }
129 
130     EIGEN_DEVICE_FUNC
131     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_digamma_op<Scalar>, const Derived>
digamma()132     digamma() const {
133       return unaryExpr(internal::scalar_digamma_op<Scalar>());
134     }
135 
136     // igamma(a = this, x = other)
137     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
138     const TensorCwiseBinaryOp<internal::scalar_igamma_op<Scalar>, const Derived, const OtherDerived>
igamma(const OtherDerived & other)139     igamma(const OtherDerived& other) const {
140       return binaryExpr(other.derived(), internal::scalar_igamma_op<Scalar>());
141     }
142 
143     // igammac(a = this, x = other)
144     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
145     const TensorCwiseBinaryOp<internal::scalar_igammac_op<Scalar>, const Derived, const OtherDerived>
igammac(const OtherDerived & other)146     igammac(const OtherDerived& other) const {
147       return binaryExpr(other.derived(), internal::scalar_igammac_op<Scalar>());
148     }
149 
150     // zeta(x = this, q = other)
151     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
152     const TensorCwiseBinaryOp<internal::scalar_zeta_op<Scalar>, const Derived, const OtherDerived>
zeta(const OtherDerived & other)153     zeta(const OtherDerived& other) const {
154       return binaryExpr(other.derived(), internal::scalar_zeta_op<Scalar>());
155     }
156 
157     // polygamma(n = this, x = other)
158     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
159     const TensorCwiseBinaryOp<internal::scalar_polygamma_op<Scalar>, const Derived, const OtherDerived>
polygamma(const OtherDerived & other)160     polygamma(const OtherDerived& other) const {
161       return binaryExpr(other.derived(), internal::scalar_polygamma_op<Scalar>());
162     }
163 
164     EIGEN_DEVICE_FUNC
165     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_erf_op<Scalar>, const Derived>
erf()166     erf() const {
167       return unaryExpr(internal::scalar_erf_op<Scalar>());
168     }
169 
170     EIGEN_DEVICE_FUNC
171     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_erfc_op<Scalar>, const Derived>
erfc()172     erfc() const {
173       return unaryExpr(internal::scalar_erfc_op<Scalar>());
174     }
175 
176     EIGEN_DEVICE_FUNC
177     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_sigmoid_op<Scalar>, const Derived>
sigmoid()178     sigmoid() const {
179       return unaryExpr(internal::scalar_sigmoid_op<Scalar>());
180     }
181 
182     EIGEN_DEVICE_FUNC
183     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_exp_op<Scalar>, const Derived>
exp()184     exp() const {
185       return unaryExpr(internal::scalar_exp_op<Scalar>());
186     }
187 
188     EIGEN_DEVICE_FUNC
189     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_log_op<Scalar>, const Derived>
log()190     log() const {
191       return unaryExpr(internal::scalar_log_op<Scalar>());
192     }
193 
194     EIGEN_DEVICE_FUNC
195     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_log1p_op<Scalar>, const Derived>
log1p()196     log1p() const {
197       return unaryExpr(internal::scalar_log1p_op<Scalar>());
198     }
199 
200     EIGEN_DEVICE_FUNC
201     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_abs_op<Scalar>, const Derived>
abs()202     abs() const {
203       return unaryExpr(internal::scalar_abs_op<Scalar>());
204     }
205 
206     EIGEN_DEVICE_FUNC
207     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Derived>
conjugate()208     conjugate() const {
209       return unaryExpr(internal::scalar_conjugate_op<Scalar>());
210     }
211 
212     EIGEN_DEVICE_FUNC
213     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_pow_op<Scalar,Scalar> >, const Derived>
pow(Scalar exponent)214     pow(Scalar exponent) const {
215       return unaryExpr(internal::bind2nd_op<internal::scalar_pow_op<Scalar,Scalar> >(exponent));
216     }
217 
218     EIGEN_DEVICE_FUNC
219     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_real_op<Scalar>, const Derived>
real()220     real() const {
221       return unaryExpr(internal::scalar_real_op<Scalar>());
222     }
223 
224     EIGEN_DEVICE_FUNC
225     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_imag_op<Scalar>, const Derived>
imag()226     imag() const {
227       return unaryExpr(internal::scalar_imag_op<Scalar>());
228     }
229 
230     EIGEN_DEVICE_FUNC
231     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_sum_op<Scalar,Scalar> >, const Derived>
232     operator+ (Scalar rhs) const {
233       return unaryExpr(internal::bind2nd_op<internal::scalar_sum_op<Scalar,Scalar> >(rhs));
234     }
235 
236     EIGEN_DEVICE_FUNC
237     EIGEN_STRONG_INLINE friend
238     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_sum_op<Scalar> >, const Derived>
239     operator+ (Scalar lhs, const Derived& rhs) {
240       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_sum_op<Scalar> >(lhs));
241     }
242 
243     EIGEN_DEVICE_FUNC
244     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_difference_op<Scalar,Scalar> >, const Derived>
245     operator- (Scalar rhs) const {
246       EIGEN_STATIC_ASSERT((NumTraits<Scalar>::IsSigned || internal::is_same<Scalar, const std::complex<float> >::value), YOU_MADE_A_PROGRAMMING_MISTAKE);
247       return unaryExpr(internal::bind2nd_op<internal::scalar_difference_op<Scalar,Scalar> >(rhs));
248     }
249 
250     EIGEN_DEVICE_FUNC
251     EIGEN_STRONG_INLINE friend
252     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_difference_op<Scalar> >, const Derived>
253     operator- (Scalar lhs, const Derived& rhs) {
254       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_difference_op<Scalar> >(lhs));
255     }
256 
257     EIGEN_DEVICE_FUNC
258     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_product_op<Scalar,Scalar> >, const Derived>
259     operator* (Scalar rhs) const {
260       return unaryExpr(internal::bind2nd_op<internal::scalar_product_op<Scalar,Scalar> >(rhs));
261     }
262 
263     EIGEN_DEVICE_FUNC
264     EIGEN_STRONG_INLINE friend
265     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_product_op<Scalar> >, const Derived>
266     operator* (Scalar lhs, const Derived& rhs) {
267       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_product_op<Scalar> >(lhs));
268     }
269 
270     EIGEN_DEVICE_FUNC
271     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_quotient_op<Scalar,Scalar> >, const Derived>
272     operator/ (Scalar rhs) const {
273       return unaryExpr(internal::bind2nd_op<internal::scalar_quotient_op<Scalar,Scalar> >(rhs));
274     }
275 
276     EIGEN_DEVICE_FUNC
277     EIGEN_STRONG_INLINE friend
278     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_quotient_op<Scalar> >, const Derived>
279     operator/ (Scalar lhs, const Derived& rhs) {
280       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_quotient_op<Scalar> >(lhs));
281     }
282 
283     EIGEN_DEVICE_FUNC
284     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_mod_op<Scalar>, const Derived>
285     operator% (Scalar rhs) const {
286       EIGEN_STATIC_ASSERT(NumTraits<Scalar>::IsInteger, YOU_MADE_A_PROGRAMMING_MISTAKE_TRY_MOD);
287       return unaryExpr(internal::scalar_mod_op<Scalar>(rhs));
288     }
289 
290     EIGEN_DEVICE_FUNC
291     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
cwiseMax(Scalar threshold)292     cwiseMax(Scalar threshold) const {
293       return cwiseMax(constant(threshold));
294     }
295 
296     EIGEN_DEVICE_FUNC
297     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
cwiseMin(Scalar threshold)298     cwiseMin(Scalar threshold) const {
299       return cwiseMin(constant(threshold));
300     }
301 
302     template <typename NewType> EIGEN_DEVICE_FUNC
303     EIGEN_STRONG_INLINE const TensorConversionOp<NewType, const Derived>
cast()304     cast() const {
305       return TensorConversionOp<NewType, const Derived>(derived());
306     }
307 
308     EIGEN_DEVICE_FUNC
309     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_round_op<Scalar>, const Derived>
round()310     round() const {
311       return unaryExpr(internal::scalar_round_op<Scalar>());
312     }
313 
314     EIGEN_DEVICE_FUNC
315     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_ceil_op<Scalar>, const Derived>
ceil()316     ceil() const {
317       return unaryExpr(internal::scalar_ceil_op<Scalar>());
318     }
319 
320     EIGEN_DEVICE_FUNC
321     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_floor_op<Scalar>, const Derived>
floor()322     floor() const {
323       return unaryExpr(internal::scalar_floor_op<Scalar>());
324     }
325 
326     // Generic binary operation support.
327     template <typename CustomBinaryOp, typename OtherDerived> EIGEN_DEVICE_FUNC
328     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<CustomBinaryOp, const Derived, const OtherDerived>
binaryExpr(const OtherDerived & other,const CustomBinaryOp & func)329     binaryExpr(const OtherDerived& other, const CustomBinaryOp& func) const {
330       return TensorCwiseBinaryOp<CustomBinaryOp, const Derived, const OtherDerived>(derived(), other, func);
331     }
332 
333     // Coefficient-wise binary operators.
334     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
335     const TensorCwiseBinaryOp<internal::scalar_sum_op<Scalar>, const Derived, const OtherDerived>
336     operator+(const OtherDerived& other) const {
337       return binaryExpr(other.derived(), internal::scalar_sum_op<Scalar>());
338     }
339 
340     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
341     const TensorCwiseBinaryOp<internal::scalar_difference_op<Scalar>, const Derived, const OtherDerived>
342     operator-(const OtherDerived& other) const {
343       return binaryExpr(other.derived(), internal::scalar_difference_op<Scalar>());
344     }
345 
346     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
347     const TensorCwiseBinaryOp<internal::scalar_product_op<Scalar>, const Derived, const OtherDerived>
348     operator*(const OtherDerived& other) const {
349       return binaryExpr(other.derived(), internal::scalar_product_op<Scalar>());
350     }
351 
352     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
353     const TensorCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>
354     operator/(const OtherDerived& other) const {
355       return binaryExpr(other.derived(), internal::scalar_quotient_op<Scalar>());
356     }
357 
358     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
359     const TensorCwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived, const OtherDerived>
cwiseMax(const OtherDerived & other)360     cwiseMax(const OtherDerived& other) const {
361       return binaryExpr(other.derived(), internal::scalar_max_op<Scalar>());
362     }
363 
364     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
365     const TensorCwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived, const OtherDerived>
cwiseMin(const OtherDerived & other)366     cwiseMin(const OtherDerived& other) const {
367       return binaryExpr(other.derived(), internal::scalar_min_op<Scalar>());
368     }
369 
370     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
371     const TensorCwiseBinaryOp<internal::scalar_boolean_and_op, const Derived, const OtherDerived>
372     operator&&(const OtherDerived& other) const {
373       return binaryExpr(other.derived(), internal::scalar_boolean_and_op());
374     }
375 
376     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
377     const TensorCwiseBinaryOp<internal::scalar_boolean_or_op, const Derived, const OtherDerived>
378     operator||(const OtherDerived& other) const {
379       return binaryExpr(other.derived(), internal::scalar_boolean_or_op());
380     }
381 
382     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
383     const TensorCwiseBinaryOp<internal::scalar_boolean_xor_op, const Derived, const OtherDerived>
384     operator^(const OtherDerived& other) const {
385       return binaryExpr(other.derived(), internal::scalar_boolean_xor_op());
386     }
387 
388     // Comparisons and tests.
389     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
390     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LT>, const Derived, const OtherDerived>
391     operator<(const OtherDerived& other) const {
392       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LT>());
393     }
394     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
395     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LE>, const Derived, const OtherDerived>
396     operator<=(const OtherDerived& other) const {
397       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LE>());
398     }
399     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
400     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GT>, const Derived, const OtherDerived>
401     operator>(const OtherDerived& other) const {
402       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GT>());
403     }
404     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
405     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GE>, const Derived, const OtherDerived>
406     operator>=(const OtherDerived& other) const {
407       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GE>());
408     }
409 
410     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
411     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_EQ>, const Derived, const OtherDerived>
412     operator==(const OtherDerived& other) const {
413       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_EQ>());
414     }
415 
416     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
417     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_NEQ>, const Derived, const OtherDerived>
418     operator!=(const OtherDerived& other) const {
419       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_NEQ>());
420     }
421 
422     // comparisons and tests for Scalars
423     EIGEN_DEVICE_FUNC
424     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LT>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
425     operator<(Scalar threshold) const {
426       return operator<(constant(threshold));
427     }
428     EIGEN_DEVICE_FUNC
429     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LE>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
430     operator<=(Scalar threshold) const {
431       return operator<=(constant(threshold));
432     }
433     EIGEN_DEVICE_FUNC
434     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GT>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
435     operator>(Scalar threshold) const {
436       return operator>(constant(threshold));
437     }
438     EIGEN_DEVICE_FUNC
439     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GE>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
440     operator>=(Scalar threshold) const {
441       return operator>=(constant(threshold));
442     }
443     EIGEN_DEVICE_FUNC
444     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_EQ>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
445     operator==(Scalar threshold) const {
446       return operator==(constant(threshold));
447     }
448     EIGEN_DEVICE_FUNC
449     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_NEQ>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
450     operator!=(Scalar threshold) const {
451       return operator!=(constant(threshold));
452     }
453 
454     // Checks
455     EIGEN_DEVICE_FUNC
456     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_isnan_op<Scalar>, const Derived>
457     (isnan)() const {
458       return unaryExpr(internal::scalar_isnan_op<Scalar>());
459     }
460     EIGEN_DEVICE_FUNC
461     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_isinf_op<Scalar>, const Derived>
462     (isinf)() const {
463       return unaryExpr(internal::scalar_isinf_op<Scalar>());
464     }
465     EIGEN_DEVICE_FUNC
466     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_isfinite_op<Scalar>, const Derived>
467     (isfinite)() const {
468       return unaryExpr(internal::scalar_isfinite_op<Scalar>());
469     }
470 
471     // Coefficient-wise ternary operators.
472     template<typename ThenDerived, typename ElseDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
473     const TensorSelectOp<const Derived, const ThenDerived, const ElseDerived>
select(const ThenDerived & thenTensor,const ElseDerived & elseTensor)474     select(const ThenDerived& thenTensor, const ElseDerived& elseTensor) const {
475       return TensorSelectOp<const Derived, const ThenDerived, const ElseDerived>(derived(), thenTensor.derived(), elseTensor.derived());
476     }
477 
478     // Contractions.
479     typedef Eigen::IndexPair<Index> DimensionPair;
480 
481     template<typename OtherDerived, typename Dimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
482     const TensorContractionOp<const Dimensions, const Derived, const OtherDerived>
contract(const OtherDerived & other,const Dimensions & dims)483     contract(const OtherDerived& other, const Dimensions& dims) const {
484       return TensorContractionOp<const Dimensions, const Derived, const OtherDerived>(derived(), other.derived(), dims);
485     }
486 
487     // Convolutions.
488     template<typename KernelDerived, typename Dimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
489     const TensorConvolutionOp<const Dimensions, const Derived, const KernelDerived>
convolve(const KernelDerived & kernel,const Dimensions & dims)490     convolve(const KernelDerived& kernel, const Dimensions& dims) const {
491       return TensorConvolutionOp<const Dimensions, const Derived, const KernelDerived>(derived(), kernel.derived(), dims);
492     }
493 
494     // Fourier transforms
495     template <int FFTDataType, int FFTDirection, typename FFT> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
496     const TensorFFTOp<const FFT, const Derived, FFTDataType, FFTDirection>
fft(const FFT & fft)497     fft(const FFT& fft) const {
498       return TensorFFTOp<const FFT, const Derived, FFTDataType, FFTDirection>(derived(), fft);
499     }
500 
501     // Scan.
502     typedef TensorScanOp<internal::SumReducer<CoeffReturnType>, const Derived> TensorScanSumOp;
503     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
504     const TensorScanSumOp
505     cumsum(const Index& axis, bool exclusive = false) const {
506       return TensorScanSumOp(derived(), axis, exclusive);
507     }
508 
509     typedef TensorScanOp<internal::ProdReducer<CoeffReturnType>, const Derived> TensorScanProdOp;
510     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
511     const TensorScanProdOp
512     cumprod(const Index& axis, bool exclusive = false) const {
513       return TensorScanProdOp(derived(), axis, exclusive);
514     }
515 
516     template <typename Reducer>
517     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
518     const TensorScanOp<Reducer, const Derived>
519     scan(const Index& axis, const Reducer& reducer, bool exclusive = false) const {
520       return TensorScanOp<Reducer, const Derived>(derived(), axis, exclusive, reducer);
521     }
522 
523     // Reductions.
524     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
525     const TensorReductionOp<internal::SumReducer<CoeffReturnType>, const Dims, const Derived>
sum(const Dims & dims)526     sum(const Dims& dims) const {
527       return TensorReductionOp<internal::SumReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::SumReducer<CoeffReturnType>());
528     }
529 
530     const TensorReductionOp<internal::SumReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
sum()531     sum() const {
532       DimensionList<Index, NumDimensions> in_dims;
533       return TensorReductionOp<internal::SumReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::SumReducer<CoeffReturnType>());
534     }
535 
536     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
537     const TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const Dims, const Derived>
mean(const Dims & dims)538     mean(const Dims& dims) const {
539       return TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::MeanReducer<CoeffReturnType>());
540     }
541 
542     const TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
mean()543     mean() const {
544       DimensionList<Index, NumDimensions> in_dims;
545       return TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::MeanReducer<CoeffReturnType>());
546     }
547 
548     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
549     const TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const Dims, const Derived>
prod(const Dims & dims)550     prod(const Dims& dims) const {
551       return TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::ProdReducer<CoeffReturnType>());
552     }
553 
554     const TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
prod()555     prod() const {
556       DimensionList<Index, NumDimensions> in_dims;
557       return TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::ProdReducer<CoeffReturnType>());
558     }
559 
560     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
561     const TensorReductionOp<internal::MaxReducer<CoeffReturnType>, const Dims, const Derived>
maximum(const Dims & dims)562     maximum(const Dims& dims) const {
563       return TensorReductionOp<internal::MaxReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::MaxReducer<CoeffReturnType>());
564     }
565 
566     const TensorReductionOp<internal::MaxReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
maximum()567     maximum() const {
568       DimensionList<Index, NumDimensions> in_dims;
569       return TensorReductionOp<internal::MaxReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::MaxReducer<CoeffReturnType>());
570     }
571 
572     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
573     const TensorReductionOp<internal::MinReducer<CoeffReturnType>, const Dims, const Derived>
minimum(const Dims & dims)574     minimum(const Dims& dims) const {
575       return TensorReductionOp<internal::MinReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::MinReducer<CoeffReturnType>());
576     }
577 
578     const TensorReductionOp<internal::MinReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
minimum()579     minimum() const {
580       DimensionList<Index, NumDimensions> in_dims;
581       return TensorReductionOp<internal::MinReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::MinReducer<CoeffReturnType>());
582     }
583 
584     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
585     const TensorReductionOp<internal::AndReducer, const Dims, const TensorConversionOp<bool, const Derived> >
all(const Dims & dims)586     all(const Dims& dims) const {
587       return cast<bool>().reduce(dims, internal::AndReducer());
588     }
589 
590     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
591     const TensorReductionOp<internal::AndReducer, const DimensionList<Index, NumDimensions>, const TensorConversionOp<bool, const Derived> >
all()592     all() const {
593       DimensionList<Index, NumDimensions> in_dims;
594       return cast<bool>().reduce(in_dims, internal::AndReducer());
595     }
596 
597     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
598     const TensorReductionOp<internal::OrReducer, const Dims, const TensorConversionOp<bool, const Derived> >
any(const Dims & dims)599     any(const Dims& dims) const {
600       return cast<bool>().reduce(dims, internal::OrReducer());
601     }
602 
603     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
604     const TensorReductionOp<internal::OrReducer, const DimensionList<Index, NumDimensions>, const TensorConversionOp<bool, const Derived> >
any()605     any() const {
606       DimensionList<Index, NumDimensions> in_dims;
607       return cast<bool>().reduce(in_dims, internal::OrReducer());
608     }
609 
610    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
611     const TensorTupleReducerOp<
612       internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
613       const array<Index, NumDimensions>, const Derived>
argmax()614     argmax() const {
615       array<Index, NumDimensions> in_dims;
616       for (int d = 0; d < NumDimensions; ++d) in_dims[d] = d;
617       return TensorTupleReducerOp<
618         internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
619         const array<Index, NumDimensions>,
620         const Derived>(derived(), internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >(), -1, in_dims);
621     }
622 
623     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
624     const TensorTupleReducerOp<
625       internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
626       const array<Index, NumDimensions>, const Derived>
argmin()627     argmin() const {
628       array<Index, NumDimensions> in_dims;
629       for (int d = 0; d < NumDimensions; ++d) in_dims[d] = d;
630       return TensorTupleReducerOp<
631         internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
632         const array<Index, NumDimensions>,
633         const Derived>(derived(), internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >(), -1, in_dims);
634     }
635 
636     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
637     const TensorTupleReducerOp<
638       internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
639       const array<Index, 1>, const Derived>
argmax(const int return_dim)640     argmax(const int return_dim) const {
641       array<Index, 1> in_dims;
642       in_dims[0] = return_dim;
643       return TensorTupleReducerOp<
644         internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
645         const array<Index, 1>,
646         const Derived>(derived(), internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >(), return_dim, in_dims);
647     }
648 
649     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
650     const TensorTupleReducerOp<
651       internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
652       const array<Index, 1>, const Derived>
argmin(const int return_dim)653     argmin(const int return_dim) const {
654       array<Index, 1> in_dims;
655       in_dims[0] = return_dim;
656       return TensorTupleReducerOp<
657         internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
658         const array<Index, 1>,
659         const Derived>(derived(), internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >(), return_dim, in_dims);
660     }
661 
662     template <typename Reducer, typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
663     const TensorReductionOp<Reducer, const Dims, const Derived>
reduce(const Dims & dims,const Reducer & reducer)664     reduce(const Dims& dims, const Reducer& reducer) const {
665       return TensorReductionOp<Reducer, const Dims, const Derived>(derived(), dims, reducer);
666     }
667 
668     template <typename Broadcast> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
669     const TensorBroadcastingOp<const Broadcast, const Derived>
broadcast(const Broadcast & broadcast)670     broadcast(const Broadcast& broadcast) const {
671       return TensorBroadcastingOp<const Broadcast, const Derived>(derived(), broadcast);
672     }
673 
674     template <typename Axis, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
675     const TensorConcatenationOp<Axis, const Derived, const OtherDerived>
concatenate(const OtherDerived & other,Axis axis)676     concatenate(const OtherDerived& other, Axis axis) const {
677       return TensorConcatenationOp<Axis, const Derived, const OtherDerived>(derived(), other.derived(), axis);
678     }
679 
680     template <typename PatchDims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
681     const TensorPatchOp<const PatchDims, const Derived>
extract_patches(const PatchDims & patch_dims)682     extract_patches(const PatchDims& patch_dims) const {
683       return TensorPatchOp<const PatchDims, const Derived>(derived(), patch_dims);
684     }
685 
686     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
687     const TensorImagePatchOp<Dynamic, Dynamic, const Derived>
688     extract_image_patches(const Index patch_rows = 1, const Index patch_cols = 1,
689                           const Index row_stride = 1, const Index col_stride = 1,
690                           const Index in_row_stride = 1, const Index in_col_stride = 1,
691                           const PaddingType padding_type = PADDING_SAME, const Scalar padding_value = Scalar(0)) const {
692       return TensorImagePatchOp<Dynamic, Dynamic, const Derived>(derived(), patch_rows, patch_cols, row_stride, col_stride,
693                                                                  in_row_stride, in_col_stride, 1, 1, padding_type, padding_value);
694     }
695 
696     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
697     const TensorImagePatchOp<Dynamic, Dynamic, const Derived>
extract_image_patches(const Index patch_rows,const Index patch_cols,const Index row_stride,const Index col_stride,const Index in_row_stride,const Index in_col_stride,const Index row_inflate_stride,const Index col_inflate_stride,const Index padding_top,const Index padding_bottom,const Index padding_left,const Index padding_right,const Scalar padding_value)698     extract_image_patches(const Index patch_rows, const Index patch_cols,
699                           const Index row_stride, const Index col_stride,
700                           const Index in_row_stride, const Index in_col_stride,
701                           const Index row_inflate_stride, const Index col_inflate_stride,
702                           const Index padding_top, const Index padding_bottom,
703                           const Index padding_left,const Index padding_right,
704                           const Scalar padding_value) const {
705       return TensorImagePatchOp<Dynamic, Dynamic, const Derived>(derived(), patch_rows, patch_cols, row_stride, col_stride,
706                                                                  in_row_stride, in_col_stride, row_inflate_stride, col_inflate_stride,
707                                                                  padding_top, padding_bottom, padding_left, padding_right, padding_value);
708     }
709 
710     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
711     const TensorVolumePatchOp<Dynamic, Dynamic, Dynamic, const Derived>
712     extract_volume_patches(const Index patch_planes, const Index patch_rows, const Index patch_cols,
713                            const Index plane_stride = 1, const Index row_stride = 1, const Index col_stride = 1,
714                            const PaddingType padding_type = PADDING_SAME, const Scalar padding_value = Scalar(0)) const {
715       return TensorVolumePatchOp<Dynamic, Dynamic, Dynamic, const Derived>(derived(), patch_planes, patch_rows, patch_cols, plane_stride, row_stride, col_stride, 1, 1, 1, 1, 1, 1, padding_type, padding_value);
716     }
717 
718 
719     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
720     const TensorVolumePatchOp<Dynamic, Dynamic, Dynamic, const Derived>
721     extract_volume_patches(const Index patch_planes, const Index patch_rows, const Index patch_cols,
722                            const Index plane_stride, const Index row_stride, const Index col_stride,
723                            const Index plane_inflate_stride, const Index row_inflate_stride, const Index col_inflate_stride,
724                            const Index padding_top_z, const Index padding_bottom_z,
725                            const Index padding_top, const Index padding_bottom,
726                            const Index padding_left, const Index padding_right, const Scalar padding_value = Scalar(0)) const {
727       return TensorVolumePatchOp<Dynamic, Dynamic, Dynamic, const Derived>(derived(), patch_planes, patch_rows, patch_cols, plane_stride, row_stride, col_stride, 1, 1, 1, plane_inflate_stride, row_inflate_stride, col_inflate_stride, padding_top_z, padding_bottom_z, padding_top, padding_bottom, padding_left, padding_right, padding_value);
728     }
729 
730     // Morphing operators.
731     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
732     const TensorLayoutSwapOp<const Derived>
swap_layout()733     swap_layout() const {
734       return TensorLayoutSwapOp<const Derived>(derived());
735     }
736     template <typename NewDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
737     const TensorReshapingOp<const NewDimensions, const Derived>
reshape(const NewDimensions & newDimensions)738     reshape(const NewDimensions& newDimensions) const {
739       return TensorReshapingOp<const NewDimensions, const Derived>(derived(), newDimensions);
740     }
741     template <typename StartIndices, typename Sizes> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
742     const TensorSlicingOp<const StartIndices, const Sizes, const Derived>
slice(const StartIndices & startIndices,const Sizes & sizes)743     slice(const StartIndices& startIndices, const Sizes& sizes) const {
744       return TensorSlicingOp<const StartIndices, const Sizes, const Derived>(derived(), startIndices, sizes);
745     }
746     template <typename StartIndices, typename StopIndices, typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
747     const TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides, const Derived>
stridedSlice(const StartIndices & startIndices,const StopIndices & stopIndices,const Strides & strides)748     stridedSlice(const StartIndices& startIndices, const StopIndices& stopIndices, const Strides& strides) const {
749       return TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides,
750                                 const Derived>(derived(), startIndices, stopIndices, strides);
751     }
752     template <Index DimId> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
753     const TensorChippingOp<DimId, const Derived>
chip(const Index offset)754     chip(const Index offset) const {
755       return TensorChippingOp<DimId, const Derived>(derived(), offset, DimId);
756     }
757     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
758     const TensorChippingOp<Dynamic, const Derived>
chip(const Index offset,const Index dim)759     chip(const Index offset, const Index dim) const {
760       return TensorChippingOp<Dynamic, const Derived>(derived(), offset, dim);
761     }
762     template <typename ReverseDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
763     const TensorReverseOp<const ReverseDimensions, const Derived>
reverse(const ReverseDimensions & rev)764     reverse(const ReverseDimensions& rev) const {
765       return TensorReverseOp<const ReverseDimensions, const Derived>(derived(), rev);
766     }
767     template <typename PaddingDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
768     const TensorPaddingOp<const PaddingDimensions, const Derived>
pad(const PaddingDimensions & padding)769     pad(const PaddingDimensions& padding) const {
770       return TensorPaddingOp<const PaddingDimensions, const Derived>(derived(), padding, internal::scalar_cast_op<int, Scalar>()(0));
771     }
772     template <typename PaddingDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
773     const TensorPaddingOp<const PaddingDimensions, const Derived>
pad(const PaddingDimensions & padding,const Scalar padding_value)774     pad(const PaddingDimensions& padding, const Scalar padding_value) const {
775       return TensorPaddingOp<const PaddingDimensions, const Derived>(derived(), padding, padding_value);
776     }
777     template <typename Shuffle> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
778     const TensorShufflingOp<const Shuffle, const Derived>
shuffle(const Shuffle & shuffle)779     shuffle(const Shuffle& shuffle) const {
780       return TensorShufflingOp<const Shuffle, const Derived>(derived(), shuffle);
781     }
782     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
783     const TensorStridingOp<const Strides, const Derived>
stride(const Strides & strides)784     stride(const Strides& strides) const {
785       return TensorStridingOp<const Strides, const Derived>(derived(), strides);
786     }
787     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
788     const TensorInflationOp<const Strides, const Derived>
inflate(const Strides & strides)789     inflate(const Strides& strides) const {
790       return TensorInflationOp<const Strides, const Derived>(derived(), strides);
791     }
792 
793     // Returns a tensor containing index/value tuples
794     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
795     const TensorIndexTupleOp<const Derived>
index_tuples()796     index_tuples() const {
797       return TensorIndexTupleOp<const Derived>(derived());
798     }
799 
800     // Support for custom unary and binary operations
801     template <typename CustomUnaryFunc>
802     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
customOp(const CustomUnaryFunc & op)803     const TensorCustomUnaryOp<const CustomUnaryFunc, const Derived> customOp(const CustomUnaryFunc& op) const {
804       return TensorCustomUnaryOp<const CustomUnaryFunc, const Derived>(derived(), op);
805     }
806     template <typename OtherDerived, typename CustomBinaryFunc>
807     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
customOp(const OtherDerived & other,const CustomBinaryFunc & op)808     const TensorCustomBinaryOp<const CustomBinaryFunc, const Derived, const OtherDerived> customOp(const OtherDerived& other, const CustomBinaryFunc& op) const {
809       return TensorCustomBinaryOp<const CustomBinaryFunc, const Derived, const OtherDerived>(derived(), other, op);
810     }
811 
812     // Force the evaluation of the expression.
813     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
eval()814     const TensorForcedEvalOp<const Derived> eval() const {
815       return TensorForcedEvalOp<const Derived>(derived());
816     }
817 
818   protected:
819     template <typename Scalar, int NumIndices, int Options, typename IndexType> friend class Tensor;
820     template <typename Scalar, typename Dimensions, int Option, typename IndexTypes> friend class TensorFixedSize;
821     template <typename OtherDerived, int AccessLevel> friend class TensorBase;
822     EIGEN_DEVICE_FUNC
derived()823     EIGEN_STRONG_INLINE const Derived& derived() const { return *static_cast<const Derived*>(this); }
824 };
825 
826 template<typename Derived, int AccessLevel = internal::accessors_level<Derived>::value>
827 class TensorBase : public TensorBase<Derived, ReadOnlyAccessors> {
828  public:
829     typedef internal::traits<Derived> DerivedTraits;
830     typedef typename DerivedTraits::Scalar Scalar;
831     typedef typename DerivedTraits::Index Index;
832     typedef Scalar CoeffReturnType;
833     static const int NumDimensions = DerivedTraits::NumDimensions;
834 
835     template <typename Scalar, int NumIndices, int Options, typename IndexType> friend class Tensor;
836     template <typename Scalar, typename Dimensions, int Option, typename IndexTypes> friend class TensorFixedSize;
837     template <typename OtherDerived, int OtherAccessLevel> friend class TensorBase;
838 
839     EIGEN_DEVICE_FUNC
setZero()840     EIGEN_STRONG_INLINE Derived& setZero() {
841       return setConstant(Scalar(0));
842     }
843     EIGEN_DEVICE_FUNC
setConstant(const Scalar & val)844     EIGEN_STRONG_INLINE Derived& setConstant(const Scalar& val) {
845       return derived() = this->constant(val);
846     }
847     EIGEN_DEVICE_FUNC
setRandom()848     EIGEN_STRONG_INLINE Derived& setRandom() {
849       return derived() = this->random();
850     }
851     template <typename RandomGenerator> EIGEN_DEVICE_FUNC
setRandom()852     EIGEN_STRONG_INLINE Derived& setRandom() {
853       return derived() = this->template random<RandomGenerator>();
854     }
855 
856 #if EIGEN_HAS_VARIADIC_TEMPLATES
857     EIGEN_DEVICE_FUNC
setValues(const typename internal::Initializer<Derived,NumDimensions>::InitList & vals)858     EIGEN_STRONG_INLINE Derived& setValues(
859         const typename internal::Initializer<Derived, NumDimensions>::InitList& vals) {
860       TensorEvaluator<Derived, DefaultDevice> eval(derived(), DefaultDevice());
861       internal::initialize_tensor<Derived, NumDimensions>(eval, vals);
862       return derived();
863     }
864 #endif  // EIGEN_HAS_VARIADIC_TEMPLATES
865 
866     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
867     Derived& operator+=(const OtherDerived& other) {
868       return derived() = derived() + other.derived();
869     }
870     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
871     Derived& operator-=(const OtherDerived& other) {
872       return derived() = derived() - other.derived();
873     }
874     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
875     Derived& operator*=(const OtherDerived& other) {
876       return derived() = derived() * other.derived();
877     }
878     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
879     Derived& operator/=(const OtherDerived& other) {
880       return derived() = derived() / other.derived();
881     }
882 
883     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
884     const TensorLayoutSwapOp<const Derived>
swap_layout()885     swap_layout() const {
886       return TensorLayoutSwapOp<const Derived>(derived());
887     }
888     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
889     TensorLayoutSwapOp<Derived>
swap_layout()890     swap_layout() {
891       return TensorLayoutSwapOp<Derived>(derived());
892     }
893 
894     template <typename Axis, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
895     const TensorConcatenationOp<const Axis, const Derived, const OtherDerived>
concatenate(const OtherDerived & other,const Axis & axis)896     concatenate(const OtherDerived& other, const Axis& axis) const {
897       return TensorConcatenationOp<const Axis, const Derived, const OtherDerived>(derived(), other, axis);
898     }
899     template <typename Axis, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
900     TensorConcatenationOp<const Axis, Derived, OtherDerived>
concatenate(const OtherDerived & other,const Axis & axis)901     concatenate(const OtherDerived& other, const Axis& axis) {
902       return TensorConcatenationOp<const Axis, Derived, OtherDerived>(derived(), other, axis);
903     }
904 
905     template <typename NewDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
906     const TensorReshapingOp<const NewDimensions, const Derived>
reshape(const NewDimensions & newDimensions)907     reshape(const NewDimensions& newDimensions) const {
908       return TensorReshapingOp<const NewDimensions, const Derived>(derived(), newDimensions);
909     }
910     template <typename NewDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
911     TensorReshapingOp<const NewDimensions, Derived>
reshape(const NewDimensions & newDimensions)912     reshape(const NewDimensions& newDimensions) {
913       return TensorReshapingOp<const NewDimensions, Derived>(derived(), newDimensions);
914     }
915 
916     template <typename StartIndices, typename Sizes> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
917     const TensorSlicingOp<const StartIndices, const Sizes, const Derived>
slice(const StartIndices & startIndices,const Sizes & sizes)918     slice(const StartIndices& startIndices, const Sizes& sizes) const {
919       return TensorSlicingOp<const StartIndices, const Sizes, const Derived>(derived(), startIndices, sizes);
920     }
921     template <typename StartIndices, typename Sizes> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
922     TensorSlicingOp<const StartIndices, const Sizes, Derived>
slice(const StartIndices & startIndices,const Sizes & sizes)923     slice(const StartIndices& startIndices, const Sizes& sizes) {
924       return TensorSlicingOp<const StartIndices, const Sizes, Derived>(derived(), startIndices, sizes);
925     }
926 
927     template <typename StartIndices, typename StopIndices, typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
928     const TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides, const Derived>
stridedSlice(const StartIndices & startIndices,const StopIndices & stopIndices,const Strides & strides)929     stridedSlice(const StartIndices& startIndices, const StopIndices& stopIndices, const Strides& strides) const {
930       return TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides,
931                                 const Derived>(derived(), startIndices, stopIndices, strides);
932     }
933     template <typename StartIndices, typename StopIndices, typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
934     TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides, Derived>
stridedSlice(const StartIndices & startIndices,const StopIndices & stopIndices,const Strides & strides)935     stridedSlice(const StartIndices& startIndices, const StopIndices& stopIndices, const Strides& strides) {
936       return TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides,
937                                 Derived>(derived(), startIndices, stopIndices, strides);
938     }
939 
940     template <DenseIndex DimId> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
941     const TensorChippingOp<DimId, const Derived>
chip(const Index offset)942     chip(const Index offset) const {
943       return TensorChippingOp<DimId, const Derived>(derived(), offset, DimId);
944     }
945     template <Index DimId> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
946     TensorChippingOp<DimId, Derived>
chip(const Index offset)947     chip(const Index offset) {
948       return TensorChippingOp<DimId, Derived>(derived(), offset, DimId);
949     }
950 
951     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
952     const TensorChippingOp<Dynamic, const Derived>
chip(const Index offset,const Index dim)953     chip(const Index offset, const Index dim) const {
954       return TensorChippingOp<Dynamic, const Derived>(derived(), offset, dim);
955     }
956     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
957     TensorChippingOp<Dynamic, Derived>
chip(const Index offset,const Index dim)958     chip(const Index offset, const Index dim) {
959       return TensorChippingOp<Dynamic, Derived>(derived(), offset, dim);
960     }
961 
962     template <typename ReverseDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
963     const TensorReverseOp<const ReverseDimensions, const Derived>
reverse(const ReverseDimensions & rev)964     reverse(const ReverseDimensions& rev) const {
965       return TensorReverseOp<const ReverseDimensions, const Derived>(derived(), rev);
966     }
967     template <typename ReverseDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
968     TensorReverseOp<const ReverseDimensions, Derived>
reverse(const ReverseDimensions & rev)969     reverse(const ReverseDimensions& rev) {
970       return TensorReverseOp<const ReverseDimensions, Derived>(derived(), rev);
971     }
972 
973     template <typename Shuffle> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
974     const TensorShufflingOp<const Shuffle, const Derived>
shuffle(const Shuffle & shuffle)975     shuffle(const Shuffle& shuffle) const {
976       return TensorShufflingOp<const Shuffle, const Derived>(derived(), shuffle);
977     }
978     template <typename Shuffle> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
979     TensorShufflingOp<const Shuffle, Derived>
shuffle(const Shuffle & shuffle)980     shuffle(const Shuffle& shuffle) {
981       return TensorShufflingOp<const Shuffle, Derived>(derived(), shuffle);
982     }
983 
984     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
985     const TensorStridingOp<const Strides, const Derived>
stride(const Strides & strides)986     stride(const Strides& strides) const {
987       return TensorStridingOp<const Strides, const Derived>(derived(), strides);
988     }
989     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
990     TensorStridingOp<const Strides, Derived>
stride(const Strides & strides)991     stride(const Strides& strides) {
992       return TensorStridingOp<const Strides, Derived>(derived(), strides);
993     }
994 
995     // Select the device on which to evaluate the expression.
996     template <typename DeviceType>
device(const DeviceType & device)997     TensorDevice<Derived, DeviceType> device(const DeviceType& device) {
998       return TensorDevice<Derived, DeviceType>(device, derived());
999     }
1000 
1001  protected:
1002     EIGEN_DEVICE_FUNC
derived()1003     EIGEN_STRONG_INLINE Derived& derived() { return *static_cast<Derived*>(this); }
1004     EIGEN_DEVICE_FUNC
derived()1005     EIGEN_STRONG_INLINE const Derived& derived() const { return *static_cast<const Derived*>(this); }
1006 };
1007 
1008 } // end namespace Eigen
1009 
1010 #endif // EIGEN_CXX11_TENSOR_TENSOR_BASE_H
1011