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