cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

TensorBase.h (57932B)


      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 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>
     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>
     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>
     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>
     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>
     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>
     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>
     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>
     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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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
    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>
    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>
    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>
    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> >
    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> >
    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
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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 >
    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 >
    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 >
    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 >
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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
    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
    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
    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
    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
    988     EIGEN_STRONG_INLINE Derived& setZero() {
    989       return setConstant(Scalar(0));
    990     }
    991     EIGEN_DEVICE_FUNC
    992     EIGEN_STRONG_INLINE Derived& setConstant(const Scalar& val) {
    993       return derived() = this->constant(val);
    994     }
    995     EIGEN_DEVICE_FUNC
    996     EIGEN_STRONG_INLINE Derived& setRandom() {
    997       return derived() = this->random();
    998     }
    999     template <typename RandomGenerator> EIGEN_DEVICE_FUNC
   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
   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>
   1033     swap_layout() const {
   1034       return TensorLayoutSwapOp<const Derived>(derived());
   1035     }
   1036     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
   1037     TensorLayoutSwapOp<Derived>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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:
   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
   1169     EIGEN_STRONG_INLINE Derived& derived() { return *static_cast<Derived*>(this); }
   1170     EIGEN_DEVICE_FUNC
   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