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