xref: /aosp_15_r20/external/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <[email protected]>
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 interchangeably 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     EIGEN_DEVICE_FUNC
139     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_i0_op<Scalar>, const Derived>
bessel_i0()140     bessel_i0() const {
141       return unaryExpr(internal::scalar_bessel_i0_op<Scalar>());
142     }
143 
144     EIGEN_DEVICE_FUNC
145     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_i0e_op<Scalar>, const Derived>
bessel_i0e()146     bessel_i0e() const {
147       return unaryExpr(internal::scalar_bessel_i0e_op<Scalar>());
148     }
149 
150     EIGEN_DEVICE_FUNC
151     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_i1_op<Scalar>, const Derived>
bessel_i1()152     bessel_i1() const {
153       return unaryExpr(internal::scalar_bessel_i1_op<Scalar>());
154     }
155 
156     EIGEN_DEVICE_FUNC
157     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_i1e_op<Scalar>, const Derived>
bessel_i1e()158     bessel_i1e() const {
159       return unaryExpr(internal::scalar_bessel_i1e_op<Scalar>());
160     }
161 
162     EIGEN_DEVICE_FUNC
163     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_j0_op<Scalar>, const Derived>
bessel_j0()164     bessel_j0() const {
165       return unaryExpr(internal::scalar_bessel_j0_op<Scalar>());
166     }
167 
168     EIGEN_DEVICE_FUNC
169     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_y0_op<Scalar>, const Derived>
bessel_y0()170     bessel_y0() const {
171       return unaryExpr(internal::scalar_bessel_y0_op<Scalar>());
172     }
173 
174     EIGEN_DEVICE_FUNC
175     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_j1_op<Scalar>, const Derived>
bessel_j1()176     bessel_j1() const {
177       return unaryExpr(internal::scalar_bessel_j1_op<Scalar>());
178     }
179 
180     EIGEN_DEVICE_FUNC
181     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_y1_op<Scalar>, const Derived>
bessel_y1()182     bessel_y1() const {
183       return unaryExpr(internal::scalar_bessel_y1_op<Scalar>());
184     }
185 
186     EIGEN_DEVICE_FUNC
187     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_k0_op<Scalar>, const Derived>
bessel_k0()188     bessel_k0() const {
189       return unaryExpr(internal::scalar_bessel_k0_op<Scalar>());
190     }
191 
192     EIGEN_DEVICE_FUNC
193     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_k0e_op<Scalar>, const Derived>
bessel_k0e()194     bessel_k0e() const {
195       return unaryExpr(internal::scalar_bessel_k0e_op<Scalar>());
196     }
197 
198     EIGEN_DEVICE_FUNC
199     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_k1_op<Scalar>, const Derived>
bessel_k1()200     bessel_k1() const {
201       return unaryExpr(internal::scalar_bessel_k1_op<Scalar>());
202     }
203 
204     EIGEN_DEVICE_FUNC
205     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_bessel_k1e_op<Scalar>, const Derived>
bessel_k1e()206     bessel_k1e() const {
207       return unaryExpr(internal::scalar_bessel_k1e_op<Scalar>());
208     }
209 
210     // igamma(a = this, x = other)
211     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
212     const TensorCwiseBinaryOp<internal::scalar_igamma_op<Scalar>, const Derived, const OtherDerived>
igamma(const OtherDerived & other)213     igamma(const OtherDerived& other) const {
214       return binaryExpr(other.derived(), internal::scalar_igamma_op<Scalar>());
215     }
216 
217     // igamma_der_a(a = this, x = other)
218     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
219     const TensorCwiseBinaryOp<internal::scalar_igamma_der_a_op<Scalar>, const Derived, const OtherDerived>
igamma_der_a(const OtherDerived & other)220     igamma_der_a(const OtherDerived& other) const {
221       return binaryExpr(other.derived(), internal::scalar_igamma_der_a_op<Scalar>());
222     }
223 
224     // gamma_sample_der_alpha(alpha = this, sample = other)
225     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
226     const TensorCwiseBinaryOp<internal::scalar_gamma_sample_der_alpha_op<Scalar>, const Derived, const OtherDerived>
gamma_sample_der_alpha(const OtherDerived & other)227     gamma_sample_der_alpha(const OtherDerived& other) const {
228       return binaryExpr(other.derived(), internal::scalar_gamma_sample_der_alpha_op<Scalar>());
229     }
230 
231     // igammac(a = this, x = other)
232     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
233     const TensorCwiseBinaryOp<internal::scalar_igammac_op<Scalar>, const Derived, const OtherDerived>
igammac(const OtherDerived & other)234     igammac(const OtherDerived& other) const {
235       return binaryExpr(other.derived(), internal::scalar_igammac_op<Scalar>());
236     }
237 
238     // zeta(x = this, q = other)
239     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
240     const TensorCwiseBinaryOp<internal::scalar_zeta_op<Scalar>, const Derived, const OtherDerived>
zeta(const OtherDerived & other)241     zeta(const OtherDerived& other) const {
242       return binaryExpr(other.derived(), internal::scalar_zeta_op<Scalar>());
243     }
244 
245     // polygamma(n = this, x = other)
246     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
247     const TensorCwiseBinaryOp<internal::scalar_polygamma_op<Scalar>, const Derived, const OtherDerived>
polygamma(const OtherDerived & other)248     polygamma(const OtherDerived& other) const {
249       return binaryExpr(other.derived(), internal::scalar_polygamma_op<Scalar>());
250     }
251 
252     EIGEN_DEVICE_FUNC
253     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_erf_op<Scalar>, const Derived>
erf()254     erf() const {
255       return unaryExpr(internal::scalar_erf_op<Scalar>());
256     }
257 
258     EIGEN_DEVICE_FUNC
259     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_erfc_op<Scalar>, const Derived>
erfc()260     erfc() const {
261       return unaryExpr(internal::scalar_erfc_op<Scalar>());
262     }
263 
264     EIGEN_DEVICE_FUNC
265     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_ndtri_op<Scalar>, const Derived>
ndtri()266     ndtri() const {
267       return unaryExpr(internal::scalar_ndtri_op<Scalar>());
268     }
269 
270     EIGEN_DEVICE_FUNC
271     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_logistic_op<Scalar>, const Derived>
sigmoid()272     sigmoid() const {
273       return unaryExpr(internal::scalar_logistic_op<Scalar>());
274     }
275 
276     EIGEN_DEVICE_FUNC
277     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_exp_op<Scalar>, const Derived>
exp()278     exp() const {
279       return unaryExpr(internal::scalar_exp_op<Scalar>());
280     }
281 
282     EIGEN_DEVICE_FUNC
283     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_expm1_op<Scalar>, const Derived>
expm1()284     expm1() const {
285       return unaryExpr(internal::scalar_expm1_op<Scalar>());
286     }
287 
288     EIGEN_DEVICE_FUNC
289     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_log_op<Scalar>, const Derived>
log()290     log() const {
291       return unaryExpr(internal::scalar_log_op<Scalar>());
292     }
293 
294     EIGEN_DEVICE_FUNC
295     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_log1p_op<Scalar>, const Derived>
log1p()296     log1p() const {
297       return unaryExpr(internal::scalar_log1p_op<Scalar>());
298     }
299 
300     EIGEN_DEVICE_FUNC
301     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_log2_op<Scalar>, const Derived>
log2()302     log2() const {
303       return unaryExpr(internal::scalar_log2_op<Scalar>());
304     }
305 
306     EIGEN_DEVICE_FUNC
307     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_abs_op<Scalar>, const Derived>
abs()308     abs() const {
309       return unaryExpr(internal::scalar_abs_op<Scalar>());
310     }
311 
312     EIGEN_DEVICE_FUNC
313     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_clamp_op<Scalar>, const Derived>
clip(Scalar min,Scalar max)314     clip(Scalar min, Scalar max) const {
315       return unaryExpr(internal::scalar_clamp_op<Scalar>(min, max));
316     }
317 
318     EIGEN_DEVICE_FUNC
319     EIGEN_STRONG_INLINE const typename internal::conditional<NumTraits<CoeffReturnType>::IsComplex,
320                                                              TensorCwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Derived>,
321                                                              Derived>::type
conjugate()322     conjugate() const {
323       return choose(Cond<NumTraits<CoeffReturnType>::IsComplex>(), unaryExpr(internal::scalar_conjugate_op<Scalar>()), derived());
324     }
325 
326     EIGEN_DEVICE_FUNC
327     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_pow_op<Scalar,Scalar> >, const Derived>
pow(Scalar exponent)328     pow(Scalar exponent) const {
329       return unaryExpr(internal::bind2nd_op<internal::scalar_pow_op<Scalar,Scalar> >(exponent));
330     }
331 
332     EIGEN_DEVICE_FUNC
333     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_real_op<Scalar>, const Derived>
real()334     real() const {
335       return unaryExpr(internal::scalar_real_op<Scalar>());
336     }
337 
338     EIGEN_DEVICE_FUNC
339     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_imag_op<Scalar>, const Derived>
imag()340     imag() const {
341       return unaryExpr(internal::scalar_imag_op<Scalar>());
342     }
343 
344     EIGEN_DEVICE_FUNC
345     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_sum_op<Scalar,Scalar> >, const Derived>
346     operator+ (Scalar rhs) const {
347       return unaryExpr(internal::bind2nd_op<internal::scalar_sum_op<Scalar,Scalar> >(rhs));
348     }
349 
350     EIGEN_DEVICE_FUNC
351     EIGEN_STRONG_INLINE friend
352     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_sum_op<Scalar> >, const Derived>
353     operator+ (Scalar lhs, const Derived& rhs) {
354       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_sum_op<Scalar> >(lhs));
355     }
356 
357     EIGEN_DEVICE_FUNC
358     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_difference_op<Scalar,Scalar> >, const Derived>
359     operator- (Scalar rhs) const {
360       EIGEN_STATIC_ASSERT((NumTraits<Scalar>::IsSigned || internal::is_same<Scalar, const std::complex<float> >::value), YOU_MADE_A_PROGRAMMING_MISTAKE);
361       return unaryExpr(internal::bind2nd_op<internal::scalar_difference_op<Scalar,Scalar> >(rhs));
362     }
363 
364     EIGEN_DEVICE_FUNC
365     EIGEN_STRONG_INLINE friend
366     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_difference_op<Scalar> >, const Derived>
367     operator- (Scalar lhs, const Derived& rhs) {
368       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_difference_op<Scalar> >(lhs));
369     }
370 
371     EIGEN_DEVICE_FUNC
372     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_product_op<Scalar,Scalar> >, const Derived>
373     operator* (Scalar rhs) const {
374       return unaryExpr(internal::bind2nd_op<internal::scalar_product_op<Scalar,Scalar> >(rhs));
375     }
376 
377     EIGEN_DEVICE_FUNC
378     EIGEN_STRONG_INLINE friend
379     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_product_op<Scalar> >, const Derived>
380     operator* (Scalar lhs, const Derived& rhs) {
381       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_product_op<Scalar> >(lhs));
382     }
383 
384     EIGEN_DEVICE_FUNC
385     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::bind2nd_op<internal::scalar_quotient_op<Scalar,Scalar> >, const Derived>
386     operator/ (Scalar rhs) const {
387       return unaryExpr(internal::bind2nd_op<internal::scalar_quotient_op<Scalar,Scalar> >(rhs));
388     }
389 
390     EIGEN_DEVICE_FUNC
391     EIGEN_STRONG_INLINE friend
392     const TensorCwiseUnaryOp<internal::bind1st_op<internal::scalar_quotient_op<Scalar> >, const Derived>
393     operator/ (Scalar lhs, const Derived& rhs) {
394       return rhs.unaryExpr(internal::bind1st_op<internal::scalar_quotient_op<Scalar> >(lhs));
395     }
396 
397     EIGEN_DEVICE_FUNC
398     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_mod_op<Scalar>, const Derived>
399     operator% (Scalar rhs) const {
400       EIGEN_STATIC_ASSERT(NumTraits<Scalar>::IsInteger, YOU_MADE_A_PROGRAMMING_MISTAKE_TRY_MOD);
401       return unaryExpr(internal::scalar_mod_op<Scalar>(rhs));
402     }
403 
404     template <int NanPropagation=PropagateFast>
405     EIGEN_DEVICE_FUNC
406         EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_max_op<Scalar,Scalar,NanPropagation>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
cwiseMax(Scalar threshold)407     cwiseMax(Scalar threshold) const {
408       return cwiseMax<NanPropagation>(constant(threshold));
409     }
410 
411     template <int NanPropagation=PropagateFast>
412     EIGEN_DEVICE_FUNC
413         EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<internal::scalar_min_op<Scalar,Scalar,NanPropagation>, const Derived, const TensorCwiseNullaryOp<internal::scalar_constant_op<Scalar>, const Derived> >
cwiseMin(Scalar threshold)414     cwiseMin(Scalar threshold) const {
415       return cwiseMin<NanPropagation>(constant(threshold));
416     }
417 
418     template<typename NewType>
419     EIGEN_DEVICE_FUNC
420     EIGEN_STRONG_INLINE const typename internal::conditional<internal::is_same<NewType, CoeffReturnType>::value,
421                                                              Derived,
422                                                              TensorConversionOp<NewType, const Derived> >::type
cast()423     cast() const {
424       return choose(Cond<internal::is_same<NewType, CoeffReturnType>::value>(), derived(), TensorConversionOp<NewType, const Derived>(derived()));
425     }
426 
427     EIGEN_DEVICE_FUNC
428     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_round_op<Scalar>, const Derived>
round()429     round() const {
430       return unaryExpr(internal::scalar_round_op<Scalar>());
431     }
432 
433     EIGEN_DEVICE_FUNC
434     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_rint_op<Scalar>, const Derived>
rint()435     rint() const {
436       return unaryExpr(internal::scalar_rint_op<Scalar>());
437     }
438 
439     EIGEN_DEVICE_FUNC
440     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_ceil_op<Scalar>, const Derived>
ceil()441     ceil() const {
442       return unaryExpr(internal::scalar_ceil_op<Scalar>());
443     }
444 
445     EIGEN_DEVICE_FUNC
446     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_floor_op<Scalar>, const Derived>
floor()447     floor() const {
448       return unaryExpr(internal::scalar_floor_op<Scalar>());
449     }
450 
451     // Generic binary operation support.
452     template <typename CustomBinaryOp, typename OtherDerived> EIGEN_DEVICE_FUNC
453     EIGEN_STRONG_INLINE const TensorCwiseBinaryOp<CustomBinaryOp, const Derived, const OtherDerived>
binaryExpr(const OtherDerived & other,const CustomBinaryOp & func)454     binaryExpr(const OtherDerived& other, const CustomBinaryOp& func) const {
455       return TensorCwiseBinaryOp<CustomBinaryOp, const Derived, const OtherDerived>(derived(), other, func);
456     }
457 
458     // Coefficient-wise binary operators.
459     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
460     const TensorCwiseBinaryOp<internal::scalar_sum_op<Scalar>, const Derived, const OtherDerived>
461     operator+(const OtherDerived& other) const {
462       return binaryExpr(other.derived(), internal::scalar_sum_op<Scalar>());
463     }
464 
465     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
466     const TensorCwiseBinaryOp<internal::scalar_difference_op<Scalar>, const Derived, const OtherDerived>
467     operator-(const OtherDerived& other) const {
468       return binaryExpr(other.derived(), internal::scalar_difference_op<Scalar>());
469     }
470 
471     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
472     const TensorCwiseBinaryOp<internal::scalar_product_op<Scalar>, const Derived, const OtherDerived>
473     operator*(const OtherDerived& other) const {
474       return binaryExpr(other.derived(), internal::scalar_product_op<Scalar>());
475     }
476 
477     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
478     const TensorCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>
479     operator/(const OtherDerived& other) const {
480       return binaryExpr(other.derived(), internal::scalar_quotient_op<Scalar>());
481     }
482 
483   template<int NaNPropagation=PropagateFast, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
484       const TensorCwiseBinaryOp<internal::scalar_max_op<Scalar,Scalar, NaNPropagation>, const Derived, const OtherDerived>
cwiseMax(const OtherDerived & other)485     cwiseMax(const OtherDerived& other) const {
486     return binaryExpr(other.derived(), internal::scalar_max_op<Scalar,Scalar, NaNPropagation>());
487     }
488 
489   template<int NaNPropagation=PropagateFast, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
490     const TensorCwiseBinaryOp<internal::scalar_min_op<Scalar,Scalar, NaNPropagation>, const Derived, const OtherDerived>
cwiseMin(const OtherDerived & other)491     cwiseMin(const OtherDerived& other) const {
492       return binaryExpr(other.derived(), internal::scalar_min_op<Scalar,Scalar, NaNPropagation>());
493     }
494 
495     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
496     const TensorCwiseBinaryOp<internal::scalar_boolean_and_op, const Derived, const OtherDerived>
497     operator&&(const OtherDerived& other) const {
498       return binaryExpr(other.derived(), internal::scalar_boolean_and_op());
499     }
500 
501     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
502     const TensorCwiseBinaryOp<internal::scalar_boolean_or_op, const Derived, const OtherDerived>
503     operator||(const OtherDerived& other) const {
504       return binaryExpr(other.derived(), internal::scalar_boolean_or_op());
505     }
506 
507     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
508     const TensorCwiseBinaryOp<internal::scalar_boolean_xor_op, const Derived, const OtherDerived>
509     operator^(const OtherDerived& other) const {
510       return binaryExpr(other.derived(), internal::scalar_boolean_xor_op());
511     }
512 
513     // Comparisons and tests.
514     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
515     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LT>, const Derived, const OtherDerived>
516     operator<(const OtherDerived& other) const {
517       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LT>());
518     }
519     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
520     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LE>, const Derived, const OtherDerived>
521     operator<=(const OtherDerived& other) const {
522       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_LE>());
523     }
524     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
525     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GT>, const Derived, const OtherDerived>
526     operator>(const OtherDerived& other) const {
527       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GT>());
528     }
529     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
530     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GE>, const Derived, const OtherDerived>
531     operator>=(const OtherDerived& other) const {
532       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_GE>());
533     }
534 
535     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
536     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_EQ>, const Derived, const OtherDerived>
537     operator==(const OtherDerived& other) const {
538       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_EQ>());
539     }
540 
541     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
542     const TensorCwiseBinaryOp<internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_NEQ>, const Derived, const OtherDerived>
543     operator!=(const OtherDerived& other) const {
544       return binaryExpr(other.derived(), internal::scalar_cmp_op<Scalar, Scalar, internal::cmp_NEQ>());
545     }
546 
547     // comparisons and tests for Scalars
548     EIGEN_DEVICE_FUNC
549     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> >
550     operator<(Scalar threshold) const {
551       return operator<(constant(threshold));
552     }
553     EIGEN_DEVICE_FUNC
554     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> >
555     operator<=(Scalar threshold) const {
556       return operator<=(constant(threshold));
557     }
558     EIGEN_DEVICE_FUNC
559     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> >
560     operator>(Scalar threshold) const {
561       return operator>(constant(threshold));
562     }
563     EIGEN_DEVICE_FUNC
564     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> >
565     operator>=(Scalar threshold) const {
566       return operator>=(constant(threshold));
567     }
568     EIGEN_DEVICE_FUNC
569     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> >
570     operator==(Scalar threshold) const {
571       return operator==(constant(threshold));
572     }
573     EIGEN_DEVICE_FUNC
574     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> >
575     operator!=(Scalar threshold) const {
576       return operator!=(constant(threshold));
577     }
578 
579     // Checks
580     EIGEN_DEVICE_FUNC
581     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_isnan_op<Scalar>, const Derived>
582     (isnan)() const {
583       return unaryExpr(internal::scalar_isnan_op<Scalar>());
584     }
585     EIGEN_DEVICE_FUNC
586     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_isinf_op<Scalar>, const Derived>
587     (isinf)() const {
588       return unaryExpr(internal::scalar_isinf_op<Scalar>());
589     }
590     EIGEN_DEVICE_FUNC
591     EIGEN_STRONG_INLINE const TensorCwiseUnaryOp<internal::scalar_isfinite_op<Scalar>, const Derived>
592     (isfinite)() const {
593       return unaryExpr(internal::scalar_isfinite_op<Scalar>());
594     }
595 
596     // Coefficient-wise ternary operators.
597     template<typename ThenDerived, typename ElseDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
598     const TensorSelectOp<const Derived, const ThenDerived, const ElseDerived>
select(const ThenDerived & thenTensor,const ElseDerived & elseTensor)599     select(const ThenDerived& thenTensor, const ElseDerived& elseTensor) const {
600       return TensorSelectOp<const Derived, const ThenDerived, const ElseDerived>(derived(), thenTensor.derived(), elseTensor.derived());
601     }
602 
603     // Contractions.
604     typedef Eigen::IndexPair<Index> DimensionPair;
605 
606     template<typename OtherDerived, typename Dimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
607     const TensorContractionOp<const Dimensions, const Derived, const OtherDerived, const NoOpOutputKernel>
contract(const OtherDerived & other,const Dimensions & dims)608     contract(const OtherDerived& other, const Dimensions& dims) const {
609       return TensorContractionOp<const Dimensions, const Derived, const OtherDerived, const NoOpOutputKernel>(derived(), other.derived(), dims);
610     }
611 
612     template<typename OtherDerived, typename Dimensions, typename OutputKernel> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
613     const TensorContractionOp<const Dimensions, const Derived, const OtherDerived, const OutputKernel>
contract(const OtherDerived & other,const Dimensions & dims,const OutputKernel & output_kernel)614     contract(const OtherDerived& other, const Dimensions& dims, const OutputKernel& output_kernel) const {
615       return TensorContractionOp<const Dimensions, const Derived, const OtherDerived, const OutputKernel>(derived(), other.derived(), dims, output_kernel);
616     }
617 
618     // Convolutions.
619     template<typename KernelDerived, typename Dimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
620     const TensorConvolutionOp<const Dimensions, const Derived, const KernelDerived>
convolve(const KernelDerived & kernel,const Dimensions & dims)621     convolve(const KernelDerived& kernel, const Dimensions& dims) const {
622       return TensorConvolutionOp<const Dimensions, const Derived, const KernelDerived>(derived(), kernel.derived(), dims);
623     }
624 
625     // Fourier transforms
626     template <int FFTDataType, int FFTDirection, typename FFT> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
627     const TensorFFTOp<const FFT, const Derived, FFTDataType, FFTDirection>
fft(const FFT & dims)628     fft(const FFT& dims) const {
629       return TensorFFTOp<const FFT, const Derived, FFTDataType, FFTDirection>(derived(), dims);
630     }
631 
632     // Scan.
633     typedef TensorScanOp<internal::SumReducer<CoeffReturnType>, const Derived> TensorScanSumOp;
634     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
635     const TensorScanSumOp
636     cumsum(const Index& axis, bool exclusive = false) const {
637       return TensorScanSumOp(derived(), axis, exclusive);
638     }
639 
640     typedef TensorScanOp<internal::ProdReducer<CoeffReturnType>, const Derived> TensorScanProdOp;
641     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
642     const TensorScanProdOp
643     cumprod(const Index& axis, bool exclusive = false) const {
644       return TensorScanProdOp(derived(), axis, exclusive);
645     }
646 
647     template <typename Reducer>
648     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
649     const TensorScanOp<Reducer, const Derived>
650     scan(const Index& axis, const Reducer& reducer, bool exclusive = false) const {
651       return TensorScanOp<Reducer, const Derived>(derived(), axis, exclusive, reducer);
652     }
653 
654     // Reductions.
655     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
656     const TensorReductionOp<internal::SumReducer<CoeffReturnType>, const Dims, const Derived>
sum(const Dims & dims)657     sum(const Dims& dims) const {
658       return TensorReductionOp<internal::SumReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::SumReducer<CoeffReturnType>());
659     }
660 
661     const TensorReductionOp<internal::SumReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
sum()662     sum() const {
663       DimensionList<Index, NumDimensions> in_dims;
664       return TensorReductionOp<internal::SumReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::SumReducer<CoeffReturnType>());
665     }
666 
667     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
668     const TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const Dims, const Derived>
mean(const Dims & dims)669     mean(const Dims& dims) const {
670       return TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::MeanReducer<CoeffReturnType>());
671     }
672 
673     const TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
mean()674     mean() const {
675       DimensionList<Index, NumDimensions> in_dims;
676       return TensorReductionOp<internal::MeanReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::MeanReducer<CoeffReturnType>());
677     }
678 
679     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
680     const TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const Dims, const Derived>
prod(const Dims & dims)681     prod(const Dims& dims) const {
682       return TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const Dims, const Derived>(derived(), dims, internal::ProdReducer<CoeffReturnType>());
683     }
684 
685     const TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>
prod()686     prod() const {
687       DimensionList<Index, NumDimensions> in_dims;
688       return TensorReductionOp<internal::ProdReducer<CoeffReturnType>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::ProdReducer<CoeffReturnType>());
689     }
690 
691     template <typename Dims,int NanPropagation=PropagateFast> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
692     const TensorReductionOp<internal::MaxReducer<CoeffReturnType,NanPropagation>, const Dims, const Derived>
maximum(const Dims & dims)693     maximum(const Dims& dims) const {
694       return TensorReductionOp<internal::MaxReducer<CoeffReturnType,NanPropagation>, const Dims, const Derived>(derived(), dims, internal::MaxReducer<CoeffReturnType,NanPropagation>());
695     }
696 
697     template <int NanPropagation=PropagateFast>
698     const TensorReductionOp<internal::MaxReducer<CoeffReturnType,NanPropagation>, const DimensionList<Index, NumDimensions>, const Derived>
maximum()699     maximum() const {
700       DimensionList<Index, NumDimensions> in_dims;
701       return TensorReductionOp<internal::MaxReducer<CoeffReturnType,NanPropagation>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::MaxReducer<CoeffReturnType,NanPropagation>());
702     }
703 
704     template <typename Dims,int NanPropagation=PropagateFast> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
705     const TensorReductionOp<internal::MinReducer<CoeffReturnType,NanPropagation>, const Dims, const Derived>
minimum(const Dims & dims)706     minimum(const Dims& dims) const {
707       return TensorReductionOp<internal::MinReducer<CoeffReturnType,NanPropagation>, const Dims, const Derived>(derived(), dims, internal::MinReducer<CoeffReturnType,NanPropagation>());
708     }
709 
710     template <int NanPropagation=PropagateFast>
711     const TensorReductionOp<internal::MinReducer<CoeffReturnType,NanPropagation>, const DimensionList<Index, NumDimensions>, const Derived>
minimum()712     minimum() const {
713       DimensionList<Index, NumDimensions> in_dims;
714       return TensorReductionOp<internal::MinReducer<CoeffReturnType,NanPropagation>, const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims, internal::MinReducer<CoeffReturnType,NanPropagation>());
715     }
716 
717     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
718     const TensorReductionOp<internal::AndReducer, const Dims, const typename internal::conditional<internal::is_same<bool, CoeffReturnType>::value, Derived, TensorConversionOp<bool, const Derived> >::type >
all(const Dims & dims)719     all(const Dims& dims) const {
720       return cast<bool>().reduce(dims, internal::AndReducer());
721     }
722 
723     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
724     const TensorReductionOp<internal::AndReducer, const DimensionList<Index, NumDimensions>, const typename internal::conditional<internal::is_same<bool, CoeffReturnType>::value, Derived, TensorConversionOp<bool, const Derived> >::type >
all()725     all() const {
726       DimensionList<Index, NumDimensions> in_dims;
727       return cast<bool>().reduce(in_dims, internal::AndReducer());
728     }
729 
730     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
731     const TensorReductionOp<internal::OrReducer, const Dims, const typename internal::conditional<internal::is_same<bool, CoeffReturnType>::value, Derived, TensorConversionOp<bool, const Derived> >::type >
any(const Dims & dims)732     any(const Dims& dims) const {
733       return cast<bool>().reduce(dims, internal::OrReducer());
734     }
735 
736     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
737     const TensorReductionOp<internal::OrReducer, const DimensionList<Index, NumDimensions>, const typename internal::conditional<internal::is_same<bool, CoeffReturnType>::value, Derived, TensorConversionOp<bool, const Derived> >::type >
any()738     any() const {
739       DimensionList<Index, NumDimensions> in_dims;
740       return cast<bool>().reduce(in_dims, internal::OrReducer());
741     }
742 
743    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
744     const TensorTupleReducerOp<
745       internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
746       const array<Index, NumDimensions>, const Derived>
argmax()747     argmax() const {
748       array<Index, NumDimensions> in_dims;
749       for (Index d = 0; d < NumDimensions; ++d) in_dims[d] = d;
750       return TensorTupleReducerOp<
751         internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
752         const array<Index, NumDimensions>,
753         const Derived>(derived(), internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >(), -1, in_dims);
754     }
755 
756     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
757     const TensorTupleReducerOp<
758       internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
759       const array<Index, NumDimensions>, const Derived>
argmin()760     argmin() const {
761       array<Index, NumDimensions> in_dims;
762       for (Index d = 0; d < NumDimensions; ++d) in_dims[d] = d;
763       return TensorTupleReducerOp<
764         internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
765         const array<Index, NumDimensions>,
766         const Derived>(derived(), internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >(), -1, in_dims);
767     }
768 
769     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
770     const TensorTupleReducerOp<
771       internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
772       const array<Index, 1>, const Derived>
argmax(const Index return_dim)773     argmax(const Index return_dim) const {
774       array<Index, 1> in_dims;
775       in_dims[0] = return_dim;
776       return TensorTupleReducerOp<
777         internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >,
778         const array<Index, 1>,
779         const Derived>(derived(), internal::ArgMaxTupleReducer<Tuple<Index, CoeffReturnType> >(), return_dim, in_dims);
780     }
781 
782     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
783     const TensorTupleReducerOp<
784       internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
785       const array<Index, 1>, const Derived>
argmin(const Index return_dim)786     argmin(const Index return_dim) const {
787       array<Index, 1> in_dims;
788       in_dims[0] = return_dim;
789       return TensorTupleReducerOp<
790         internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >,
791         const array<Index, 1>,
792         const Derived>(derived(), internal::ArgMinTupleReducer<Tuple<Index, CoeffReturnType> >(), return_dim, in_dims);
793     }
794 
795     template <typename Reducer, typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
796     const TensorReductionOp<Reducer, const Dims, const Derived>
reduce(const Dims & dims,const Reducer & reducer)797     reduce(const Dims& dims, const Reducer& reducer) const {
798       return TensorReductionOp<Reducer, const Dims, const Derived>(derived(), dims, reducer);
799     }
800 
801     template <typename Dims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
802     const TensorTraceOp<const Dims, const Derived>
trace(const Dims & dims)803     trace(const Dims& dims) const {
804       return TensorTraceOp<const Dims, const Derived>(derived(), dims);
805     }
806 
807     const TensorTraceOp<const DimensionList<Index, NumDimensions>, const Derived>
trace()808     trace() const {
809       DimensionList<Index, NumDimensions> in_dims;
810       return TensorTraceOp<const DimensionList<Index, NumDimensions>, const Derived>(derived(), in_dims);
811     }
812 
813     template <typename Broadcast> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
814     const TensorBroadcastingOp<const Broadcast, const Derived>
broadcast(const Broadcast & bcast)815     broadcast(const Broadcast& bcast) const {
816       return TensorBroadcastingOp<const Broadcast, const Derived>(derived(), bcast);
817     }
818 
819     template <typename Axis, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
820     const TensorConcatenationOp<Axis, const Derived, const OtherDerived>
concatenate(const OtherDerived & other,Axis axis)821     concatenate(const OtherDerived& other, Axis axis) const {
822       return TensorConcatenationOp<Axis, const Derived, const OtherDerived>(derived(), other.derived(), axis);
823     }
824 
825     template <typename PatchDims> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
826     const TensorPatchOp<const PatchDims, const Derived>
extract_patches(const PatchDims & patch_dims)827     extract_patches(const PatchDims& patch_dims) const {
828       return TensorPatchOp<const PatchDims, const Derived>(derived(), patch_dims);
829     }
830 
831     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
832     const TensorImagePatchOp<Dynamic, Dynamic, const Derived>
833     extract_image_patches(const Index patch_rows = 1, const Index patch_cols = 1,
834                           const Index row_stride = 1, const Index col_stride = 1,
835                           const Index in_row_stride = 1, const Index in_col_stride = 1,
836                           const PaddingType padding_type = PADDING_SAME, const Scalar padding_value = Scalar(0)) const {
837       return TensorImagePatchOp<Dynamic, Dynamic, const Derived>(derived(), patch_rows, patch_cols, row_stride, col_stride,
838                                                                  in_row_stride, in_col_stride, 1, 1, padding_type, padding_value);
839     }
840 
841     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
842     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)843     extract_image_patches(const Index patch_rows, const Index patch_cols,
844                           const Index row_stride, const Index col_stride,
845                           const Index in_row_stride, const Index in_col_stride,
846                           const Index row_inflate_stride, const Index col_inflate_stride,
847                           const Index padding_top, const Index padding_bottom,
848                           const Index padding_left,const Index padding_right,
849                           const Scalar padding_value) const {
850       return TensorImagePatchOp<Dynamic, Dynamic, const Derived>(derived(), patch_rows, patch_cols, row_stride, col_stride,
851                                                                  in_row_stride, in_col_stride, row_inflate_stride, col_inflate_stride,
852                                                                  padding_top, padding_bottom, padding_left, padding_right, padding_value);
853     }
854 
855     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
856     const TensorVolumePatchOp<Dynamic, Dynamic, Dynamic, const Derived>
857     extract_volume_patches(const Index patch_planes, const Index patch_rows, const Index patch_cols,
858                            const Index plane_stride = 1, const Index row_stride = 1, const Index col_stride = 1,
859                            const PaddingType padding_type = PADDING_SAME, const Scalar padding_value = Scalar(0)) const {
860       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);
861     }
862 
863 
864     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
865     const TensorVolumePatchOp<Dynamic, Dynamic, Dynamic, const Derived>
866     extract_volume_patches(const Index patch_planes, const Index patch_rows, const Index patch_cols,
867                            const Index plane_stride, const Index row_stride, const Index col_stride,
868                            const Index plane_inflate_stride, const Index row_inflate_stride, const Index col_inflate_stride,
869                            const Index padding_top_z, const Index padding_bottom_z,
870                            const Index padding_top, const Index padding_bottom,
871                            const Index padding_left, const Index padding_right, const Scalar padding_value = Scalar(0)) const {
872       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);
873     }
874 
875     // Morphing operators.
876     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
877     const TensorLayoutSwapOp<const Derived>
swap_layout()878     swap_layout() const {
879       return TensorLayoutSwapOp<const Derived>(derived());
880     }
881     template <typename NewDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
882     const TensorReshapingOp<const NewDimensions, const Derived>
reshape(const NewDimensions & newDimensions)883     reshape(const NewDimensions& newDimensions) const {
884       return TensorReshapingOp<const NewDimensions, const Derived>(derived(), newDimensions);
885     }
886     template <typename StartIndices, typename Sizes> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
887     const TensorSlicingOp<const StartIndices, const Sizes, const Derived>
slice(const StartIndices & startIndices,const Sizes & sizes)888     slice(const StartIndices& startIndices, const Sizes& sizes) const {
889       return TensorSlicingOp<const StartIndices, const Sizes, const Derived>(derived(), startIndices, sizes);
890     }
891     template <typename StartIndices, typename StopIndices, typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
892     const TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides, const Derived>
stridedSlice(const StartIndices & startIndices,const StopIndices & stopIndices,const Strides & strides)893     stridedSlice(const StartIndices& startIndices, const StopIndices& stopIndices, const Strides& strides) const {
894       return TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides,
895                                 const Derived>(derived(), startIndices, stopIndices, strides);
896     }
897     template <Index DimId> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
898     const TensorChippingOp<DimId, const Derived>
chip(const Index offset)899     chip(const Index offset) const {
900       return TensorChippingOp<DimId, const Derived>(derived(), offset, DimId);
901     }
902     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
903     const TensorChippingOp<Dynamic, const Derived>
chip(const Index offset,const Index dim)904     chip(const Index offset, const Index dim) const {
905       return TensorChippingOp<Dynamic, const Derived>(derived(), offset, dim);
906     }
907     template <typename ReverseDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
908     const TensorReverseOp<const ReverseDimensions, const Derived>
reverse(const ReverseDimensions & rev)909     reverse(const ReverseDimensions& rev) const {
910       return TensorReverseOp<const ReverseDimensions, const Derived>(derived(), rev);
911     }
912     template <typename PaddingDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
913     const TensorPaddingOp<const PaddingDimensions, const Derived>
pad(const PaddingDimensions & padding)914     pad(const PaddingDimensions& padding) const {
915       return TensorPaddingOp<const PaddingDimensions, const Derived>(derived(), padding, internal::scalar_cast_op<int, Scalar>()(0));
916     }
917     template <typename PaddingDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
918     const TensorPaddingOp<const PaddingDimensions, const Derived>
pad(const PaddingDimensions & padding,const Scalar padding_value)919     pad(const PaddingDimensions& padding, const Scalar padding_value) const {
920       return TensorPaddingOp<const PaddingDimensions, const Derived>(derived(), padding, padding_value);
921     }
922     template <typename Shuffle> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
923     const TensorShufflingOp<const Shuffle, const Derived>
shuffle(const Shuffle & shfl)924     shuffle(const Shuffle& shfl) const {
925       return TensorShufflingOp<const Shuffle, const Derived>(derived(), shfl);
926     }
927     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
928     const TensorStridingOp<const Strides, const Derived>
stride(const Strides & strides)929     stride(const Strides& strides) const {
930       return TensorStridingOp<const Strides, const Derived>(derived(), strides);
931     }
932     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
933     const TensorInflationOp<const Strides, const Derived>
inflate(const Strides & strides)934     inflate(const Strides& strides) const {
935       return TensorInflationOp<const Strides, const Derived>(derived(), strides);
936     }
937 
938     // Returns a tensor containing index/value tuples
939     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
940     const TensorIndexTupleOp<const Derived>
index_tuples()941     index_tuples() const {
942       return TensorIndexTupleOp<const Derived>(derived());
943     }
944 
945     // Support for custom unary and binary operations
946     template <typename CustomUnaryFunc>
947     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
customOp(const CustomUnaryFunc & op)948     const TensorCustomUnaryOp<const CustomUnaryFunc, const Derived> customOp(const CustomUnaryFunc& op) const {
949       return TensorCustomUnaryOp<const CustomUnaryFunc, const Derived>(derived(), op);
950     }
951     template <typename OtherDerived, typename CustomBinaryFunc>
952     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
customOp(const OtherDerived & other,const CustomBinaryFunc & op)953     const TensorCustomBinaryOp<const CustomBinaryFunc, const Derived, const OtherDerived> customOp(const OtherDerived& other, const CustomBinaryFunc& op) const {
954       return TensorCustomBinaryOp<const CustomBinaryFunc, const Derived, const OtherDerived>(derived(), other, op);
955     }
956 
957     // Force the evaluation of the expression.
958     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
eval()959     const TensorForcedEvalOp<const Derived> eval() const {
960       return TensorForcedEvalOp<const Derived>(derived());
961     }
962 
963   protected:
964     template <typename Scalar, int NumIndices, int Options, typename IndexType> friend class Tensor;
965     template <typename Scalar, typename Dimensions, int Option, typename IndexTypes> friend class TensorFixedSize;
966     // the Eigen:: prefix is required to workaround a compilation issue with nvcc 9.0
967     template <typename OtherDerived, int AccessLevel> friend class Eigen::TensorBase;
968     EIGEN_DEVICE_FUNC
derived()969     EIGEN_STRONG_INLINE const Derived& derived() const { return *static_cast<const Derived*>(this); }
970 };
971 
972 template<typename Derived, int AccessLevel = internal::accessors_level<Derived>::value>
973 class TensorBase : public TensorBase<Derived, ReadOnlyAccessors> {
974  public:
975     typedef TensorBase<Derived, ReadOnlyAccessors> Base;
976     typedef internal::traits<Derived> DerivedTraits;
977     typedef typename DerivedTraits::Scalar Scalar;
978     typedef typename DerivedTraits::Index Index;
979     typedef Scalar CoeffReturnType;
980     static const int NumDimensions = DerivedTraits::NumDimensions;
981 
982     template <typename Scalar, int NumIndices, int Options, typename IndexType> friend class Tensor;
983     template <typename Scalar, typename Dimensions, int Option, typename IndexTypes> friend class TensorFixedSize;
984     // the Eigen:: prefix is required to workaround a compilation issue with nvcc 9.0
985     template <typename OtherDerived, int OtherAccessLevel> friend class Eigen::TensorBase;
986 
987     EIGEN_DEVICE_FUNC
setZero()988     EIGEN_STRONG_INLINE Derived& setZero() {
989       return setConstant(Scalar(0));
990     }
991     EIGEN_DEVICE_FUNC
setConstant(const Scalar & val)992     EIGEN_STRONG_INLINE Derived& setConstant(const Scalar& val) {
993       return derived() = this->constant(val);
994     }
995     EIGEN_DEVICE_FUNC
setRandom()996     EIGEN_STRONG_INLINE Derived& setRandom() {
997       return derived() = this->random();
998     }
999     template <typename RandomGenerator> EIGEN_DEVICE_FUNC
setRandom()1000     EIGEN_STRONG_INLINE Derived& setRandom() {
1001       return derived() = this->template random<RandomGenerator>();
1002     }
1003 
1004 #if EIGEN_HAS_VARIADIC_TEMPLATES
1005     EIGEN_DEVICE_FUNC
setValues(const typename internal::Initializer<Derived,NumDimensions>::InitList & vals)1006     EIGEN_STRONG_INLINE Derived& setValues(
1007         const typename internal::Initializer<Derived, NumDimensions>::InitList& vals) {
1008       TensorEvaluator<Derived, DefaultDevice> eval(derived(), DefaultDevice());
1009       internal::initialize_tensor<Derived, NumDimensions>(eval, vals);
1010       return derived();
1011     }
1012 #endif  // EIGEN_HAS_VARIADIC_TEMPLATES
1013 
1014     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1015     Derived& operator+=(const OtherDerived& other) {
1016       return derived() = derived() + other.derived();
1017     }
1018     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1019     Derived& operator-=(const OtherDerived& other) {
1020       return derived() = derived() - other.derived();
1021     }
1022     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1023     Derived& operator*=(const OtherDerived& other) {
1024       return derived() = derived() * other.derived();
1025     }
1026     template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1027     Derived& operator/=(const OtherDerived& other) {
1028       return derived() = derived() / other.derived();
1029     }
1030 
1031     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1032     const TensorLayoutSwapOp<const Derived>
swap_layout()1033     swap_layout() const {
1034       return TensorLayoutSwapOp<const Derived>(derived());
1035     }
1036     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1037     TensorLayoutSwapOp<Derived>
swap_layout()1038     swap_layout() {
1039       return TensorLayoutSwapOp<Derived>(derived());
1040     }
1041 
1042     template <typename Axis, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1043     const TensorConcatenationOp<const Axis, const Derived, const OtherDerived>
concatenate(const OtherDerived & other,const Axis & axis)1044     concatenate(const OtherDerived& other, const Axis& axis) const {
1045       return TensorConcatenationOp<const Axis, const Derived, const OtherDerived>(derived(), other, axis);
1046     }
1047     template <typename Axis, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1048     TensorConcatenationOp<const Axis, Derived, OtherDerived>
concatenate(const OtherDerived & other,const Axis & axis)1049     concatenate(const OtherDerived& other, const Axis& axis) {
1050       return TensorConcatenationOp<const Axis, Derived, OtherDerived>(derived(), other, axis);
1051     }
1052 
1053     template <typename NewDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1054     const TensorReshapingOp<const NewDimensions, const Derived>
reshape(const NewDimensions & newDimensions)1055     reshape(const NewDimensions& newDimensions) const {
1056       return TensorReshapingOp<const NewDimensions, const Derived>(derived(), newDimensions);
1057     }
1058     template <typename NewDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1059     TensorReshapingOp<const NewDimensions, Derived>
reshape(const NewDimensions & newDimensions)1060     reshape(const NewDimensions& newDimensions) {
1061       return TensorReshapingOp<const NewDimensions, Derived>(derived(), newDimensions);
1062     }
1063 
1064     template <typename StartIndices, typename Sizes> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1065     const TensorSlicingOp<const StartIndices, const Sizes, const Derived>
slice(const StartIndices & startIndices,const Sizes & sizes)1066     slice(const StartIndices& startIndices, const Sizes& sizes) const {
1067       return TensorSlicingOp<const StartIndices, const Sizes, const Derived>(derived(), startIndices, sizes);
1068     }
1069     template <typename StartIndices, typename Sizes> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1070     TensorSlicingOp<const StartIndices, const Sizes, Derived>
slice(const StartIndices & startIndices,const Sizes & sizes)1071     slice(const StartIndices& startIndices, const Sizes& sizes) {
1072       return TensorSlicingOp<const StartIndices, const Sizes, Derived>(derived(), startIndices, sizes);
1073     }
1074 
1075     template <typename StartIndices, typename StopIndices, typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1076     const TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides, const Derived>
stridedSlice(const StartIndices & startIndices,const StopIndices & stopIndices,const Strides & strides)1077     stridedSlice(const StartIndices& startIndices, const StopIndices& stopIndices, const Strides& strides) const {
1078       return TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides,
1079                                 const Derived>(derived(), startIndices, stopIndices, strides);
1080     }
1081     template <typename StartIndices, typename StopIndices, typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1082     TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides, Derived>
stridedSlice(const StartIndices & startIndices,const StopIndices & stopIndices,const Strides & strides)1083     stridedSlice(const StartIndices& startIndices, const StopIndices& stopIndices, const Strides& strides) {
1084       return TensorStridingSlicingOp<const StartIndices, const StopIndices, const Strides,
1085                                 Derived>(derived(), startIndices, stopIndices, strides);
1086     }
1087 
1088     template <DenseIndex DimId> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1089     const TensorChippingOp<DimId, const Derived>
chip(const Index offset)1090     chip(const Index offset) const {
1091       return TensorChippingOp<DimId, const Derived>(derived(), offset, DimId);
1092     }
1093     template <Index DimId> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1094     TensorChippingOp<DimId, Derived>
chip(const Index offset)1095     chip(const Index offset) {
1096       return TensorChippingOp<DimId, Derived>(derived(), offset, DimId);
1097     }
1098 
1099     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1100     const TensorChippingOp<Dynamic, const Derived>
chip(const Index offset,const Index dim)1101     chip(const Index offset, const Index dim) const {
1102       return TensorChippingOp<Dynamic, const Derived>(derived(), offset, dim);
1103     }
1104     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1105     TensorChippingOp<Dynamic, Derived>
chip(const Index offset,const Index dim)1106     chip(const Index offset, const Index dim) {
1107       return TensorChippingOp<Dynamic, Derived>(derived(), offset, dim);
1108     }
1109 
1110     template <typename ReverseDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1111     const TensorReverseOp<const ReverseDimensions, const Derived>
reverse(const ReverseDimensions & rev)1112     reverse(const ReverseDimensions& rev) const {
1113       return TensorReverseOp<const ReverseDimensions, const Derived>(derived(), rev);
1114     }
1115     template <typename ReverseDimensions> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1116     TensorReverseOp<const ReverseDimensions, Derived>
reverse(const ReverseDimensions & rev)1117     reverse(const ReverseDimensions& rev) {
1118       return TensorReverseOp<const ReverseDimensions, Derived>(derived(), rev);
1119     }
1120 
1121     template <typename Shuffle> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1122     const TensorShufflingOp<const Shuffle, const Derived>
shuffle(const Shuffle & shfl)1123     shuffle(const Shuffle& shfl) const {
1124       return TensorShufflingOp<const Shuffle, const Derived>(derived(), shfl);
1125     }
1126     template <typename Shuffle> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1127     TensorShufflingOp<const Shuffle, Derived>
shuffle(const Shuffle & shfl)1128     shuffle(const Shuffle& shfl) {
1129       return TensorShufflingOp<const Shuffle, Derived>(derived(), shfl);
1130     }
1131 
1132     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1133     const TensorStridingOp<const Strides, const Derived>
stride(const Strides & strides)1134     stride(const Strides& strides) const {
1135       return TensorStridingOp<const Strides, const Derived>(derived(), strides);
1136     }
1137     template <typename Strides> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1138     TensorStridingOp<const Strides, Derived>
stride(const Strides & strides)1139     stride(const Strides& strides) {
1140       return TensorStridingOp<const Strides, Derived>(derived(), strides);
1141     }
1142 
1143     // Select the device on which to evaluate the expression.
1144     template <typename DeviceType>
device(const DeviceType & dev)1145     TensorDevice<Derived, DeviceType> device(const DeviceType& dev) {
1146       return TensorDevice<Derived, DeviceType>(dev, derived());
1147     }
1148 
1149     // Select the async device on which to evaluate the expression.
1150     template <typename DeviceType, typename DoneCallback>
device(const DeviceType & dev,DoneCallback done)1151     TensorAsyncDevice<Derived, DeviceType, DoneCallback> device(const DeviceType& dev, DoneCallback done) {
1152       return TensorAsyncDevice<Derived, DeviceType, DoneCallback>(dev, derived(), std::move(done));
1153     }
1154 
1155  protected:
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TensorBase)1156     EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TensorBase)
1157     EIGEN_DEFAULT_COPY_CONSTRUCTOR(TensorBase)
1158 
1159     template<typename OtherDerived> EIGEN_DEVICE_FUNC
1160     EIGEN_STRONG_INLINE Derived& operator=(const OtherDerived& other)
1161     {
1162       typedef TensorAssignOp<Derived, const OtherDerived> Assign;
1163       Assign assign(derived(), other.derived());
1164       internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice());
1165       return derived();
1166     }
1167 
1168     EIGEN_DEVICE_FUNC
derived()1169     EIGEN_STRONG_INLINE Derived& derived() { return *static_cast<Derived*>(this); }
1170     EIGEN_DEVICE_FUNC
derived()1171     EIGEN_STRONG_INLINE const Derived& derived() const { return *static_cast<const Derived*>(this); }
1172 };
1173 #endif // EIGEN_PARSED_BY_DOXYGEN
1174 } // end namespace Eigen
1175 
1176 #endif // EIGEN_CXX11_TENSOR_TENSOR_BASE_H
1177