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