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