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
15namespace 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
26template<typename Derived>
27class 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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> >
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> >
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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> >
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> >
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> >
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> >
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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
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
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
823    EIGEN_STRONG_INLINE const Derived& derived() const { return *static_cast<const Derived*>(this); }
824};
825
826template<typename Derived, int AccessLevel = internal::accessors_level<Derived>::value>
827class 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
840    EIGEN_STRONG_INLINE Derived& setZero() {
841      return setConstant(Scalar(0));
842    }
843    EIGEN_DEVICE_FUNC
844    EIGEN_STRONG_INLINE Derived& setConstant(const Scalar& val) {
845      return derived() = this->constant(val);
846    }
847    EIGEN_DEVICE_FUNC
848    EIGEN_STRONG_INLINE Derived& setRandom() {
849      return derived() = this->random();
850    }
851    template <typename RandomGenerator> EIGEN_DEVICE_FUNC
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
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>
885    swap_layout() const {
886      return TensorLayoutSwapOp<const Derived>(derived());
887    }
888    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
889    TensorLayoutSwapOp<Derived>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
997    TensorDevice<Derived, DeviceType> device(const DeviceType& device) {
998      return TensorDevice<Derived, DeviceType>(device, derived());
999    }
1000
1001 protected:
1002    EIGEN_DEVICE_FUNC
1003    EIGEN_STRONG_INLINE Derived& derived() { return *static_cast<Derived*>(this); }
1004    EIGEN_DEVICE_FUNC
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