TensorImagePatch.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_IMAGE_PATCH_H
00011 #define EIGEN_CXX11_TENSOR_TENSOR_IMAGE_PATCH_H
00012 
00013 namespace Eigen {
00014 
00029 namespace internal {
00030 template<DenseIndex Rows, DenseIndex Cols, typename XprType>
00031 struct traits<TensorImagePatchOp<Rows, Cols, XprType> > : public traits<XprType>
00032 {
00033   typedef typename internal::remove_const<typename XprType::Scalar>::type Scalar;
00034   typedef traits<XprType> XprTraits;
00035   typedef typename XprTraits::StorageKind StorageKind;
00036   typedef typename XprTraits::Index Index;
00037   typedef typename XprType::Nested Nested;
00038   typedef typename remove_reference<Nested>::type _Nested;
00039   static const int NumDimensions = XprTraits::NumDimensions + 1;
00040   static const int Layout = XprTraits::Layout;
00041 };
00042 
00043 template<DenseIndex Rows, DenseIndex Cols, typename XprType>
00044 struct eval<TensorImagePatchOp<Rows, Cols, XprType>, Eigen::Dense>
00045 {
00046   typedef const TensorImagePatchOp<Rows, Cols, XprType>& type;
00047 };
00048 
00049 template<DenseIndex Rows, DenseIndex Cols, typename XprType>
00050 struct nested<TensorImagePatchOp<Rows, Cols, XprType>, 1, typename eval<TensorImagePatchOp<Rows, Cols, XprType> >::type>
00051 {
00052   typedef TensorImagePatchOp<Rows, Cols, XprType> type;
00053 };
00054 
00055 }  // end namespace internal
00056 
00057 template<DenseIndex Rows, DenseIndex Cols, typename XprType>
00058 class TensorImagePatchOp : public TensorBase<TensorImagePatchOp<Rows, Cols, XprType>, ReadOnlyAccessors>
00059 {
00060   public:
00061   typedef typename Eigen::internal::traits<TensorImagePatchOp>::Scalar Scalar;
00062   typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
00063   typedef typename XprType::CoeffReturnType CoeffReturnType;
00064   typedef typename Eigen::internal::nested<TensorImagePatchOp>::type Nested;
00065   typedef typename Eigen::internal::traits<TensorImagePatchOp>::StorageKind StorageKind;
00066   typedef typename Eigen::internal::traits<TensorImagePatchOp>::Index Index;
00067 
00068   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorImagePatchOp(const XprType& expr, DenseIndex patch_rows, DenseIndex patch_cols,
00069                                                            DenseIndex row_strides, DenseIndex col_strides,
00070                                                            DenseIndex in_row_strides, DenseIndex in_col_strides,
00071                                                            DenseIndex row_inflate_strides, DenseIndex col_inflate_strides,
00072                                                            PaddingType padding_type, Scalar padding_value)
00073       : m_xpr(expr), m_patch_rows(patch_rows), m_patch_cols(patch_cols),
00074         m_row_strides(row_strides), m_col_strides(col_strides),
00075         m_in_row_strides(in_row_strides), m_in_col_strides(in_col_strides),
00076         m_row_inflate_strides(row_inflate_strides), m_col_inflate_strides(col_inflate_strides),
00077         m_padding_explicit(false), m_padding_top(0), m_padding_bottom(0), m_padding_left(0), m_padding_right(0),
00078         m_padding_type(padding_type), m_padding_value(padding_value) {}
00079 
00080   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorImagePatchOp(const XprType& expr, DenseIndex patch_rows, DenseIndex patch_cols,
00081                                                            DenseIndex row_strides, DenseIndex col_strides,
00082                                                            DenseIndex in_row_strides, DenseIndex in_col_strides,
00083                                                            DenseIndex row_inflate_strides, DenseIndex col_inflate_strides,
00084                                                            DenseIndex padding_top, DenseIndex padding_bottom,
00085                                                            DenseIndex padding_left, DenseIndex padding_right,
00086                                                            Scalar padding_value)
00087       : m_xpr(expr), m_patch_rows(patch_rows), m_patch_cols(patch_cols),
00088         m_row_strides(row_strides), m_col_strides(col_strides),
00089         m_in_row_strides(in_row_strides), m_in_col_strides(in_col_strides),
00090         m_row_inflate_strides(row_inflate_strides), m_col_inflate_strides(col_inflate_strides),
00091         m_padding_explicit(true), m_padding_top(padding_top), m_padding_bottom(padding_bottom),
00092         m_padding_left(padding_left), m_padding_right(padding_right),
00093         m_padding_type(PADDING_VALID), m_padding_value(padding_value) {}
00094 
00095     EIGEN_DEVICE_FUNC
00096     DenseIndex patch_rows() const { return m_patch_rows; }
00097     EIGEN_DEVICE_FUNC
00098     DenseIndex patch_cols() const { return m_patch_cols; }
00099     EIGEN_DEVICE_FUNC
00100     DenseIndex row_strides() const { return m_row_strides; }
00101     EIGEN_DEVICE_FUNC
00102     DenseIndex col_strides() const { return m_col_strides; }
00103     EIGEN_DEVICE_FUNC
00104     DenseIndex in_row_strides() const { return m_in_row_strides; }
00105     EIGEN_DEVICE_FUNC
00106     DenseIndex in_col_strides() const { return m_in_col_strides; }
00107     EIGEN_DEVICE_FUNC
00108     DenseIndex row_inflate_strides() const { return m_row_inflate_strides; }
00109     EIGEN_DEVICE_FUNC
00110     DenseIndex col_inflate_strides() const { return m_col_inflate_strides; }
00111     EIGEN_DEVICE_FUNC
00112     bool padding_explicit() const { return m_padding_explicit; }
00113     EIGEN_DEVICE_FUNC
00114     DenseIndex padding_top() const { return m_padding_top; }
00115     EIGEN_DEVICE_FUNC
00116     DenseIndex padding_bottom() const { return m_padding_bottom; }
00117     EIGEN_DEVICE_FUNC
00118     DenseIndex padding_left() const { return m_padding_left; }
00119     EIGEN_DEVICE_FUNC
00120     DenseIndex padding_right() const { return m_padding_right; }
00121     EIGEN_DEVICE_FUNC
00122     PaddingType padding_type() const { return m_padding_type; }
00123     EIGEN_DEVICE_FUNC
00124     Scalar padding_value() const { return m_padding_value; }
00125 
00126     EIGEN_DEVICE_FUNC
00127     const typename internal::remove_all<typename XprType::Nested>::type&
00128     expression() const { return m_xpr; }
00129 
00130   protected:
00131     typename XprType::Nested m_xpr;
00132     const DenseIndex m_patch_rows;
00133     const DenseIndex m_patch_cols;
00134     const DenseIndex m_row_strides;
00135     const DenseIndex m_col_strides;
00136     const DenseIndex m_in_row_strides;
00137     const DenseIndex m_in_col_strides;
00138     const DenseIndex m_row_inflate_strides;
00139     const DenseIndex m_col_inflate_strides;
00140     const bool m_padding_explicit;
00141     const DenseIndex m_padding_top;
00142     const DenseIndex m_padding_bottom;
00143     const DenseIndex m_padding_left;
00144     const DenseIndex m_padding_right;
00145     const PaddingType m_padding_type;
00146     const Scalar m_padding_value;
00147 };
00148 
00149 // Eval as rvalue
00150 template<DenseIndex Rows, DenseIndex Cols, typename ArgType, typename Device>
00151 struct TensorEvaluator<const TensorImagePatchOp<Rows, Cols, ArgType>, Device>
00152 {
00153   typedef TensorImagePatchOp<Rows, Cols, ArgType> XprType;
00154   typedef typename XprType::Index Index;
00155   static const int NumInputDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
00156   static const int NumDims = NumInputDims + 1;
00157   typedef DSizes<Index, NumDims> Dimensions;
00158   typedef typename internal::remove_const<typename XprType::Scalar>::type Scalar;
00159   typedef TensorEvaluator<const TensorImagePatchOp<Rows, Cols, ArgType>,
00160                           Device> Self;
00161   typedef TensorEvaluator<ArgType, Device> Impl;
00162   typedef typename XprType::CoeffReturnType CoeffReturnType;
00163   typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
00164   static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size;
00165 
00166   enum {
00167     IsAligned = false,
00168     PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
00169     Layout = TensorEvaluator<ArgType, Device>::Layout,
00170     CoordAccess = false,
00171     RawAccess = false
00172   };
00173 
00174   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
00175       : m_impl(op.expression(), device)
00176   {
00177     EIGEN_STATIC_ASSERT((NumDims >= 4), YOU_MADE_A_PROGRAMMING_MISTAKE);
00178 
00179     m_paddingValue = op.padding_value();
00180 
00181     const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
00182 
00183     // Caches a few variables.
00184     if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
00185       m_inputDepth = input_dims[0];
00186       m_inputRows = input_dims[1];
00187       m_inputCols = input_dims[2];
00188     } else {
00189       m_inputDepth = input_dims[NumInputDims-1];
00190       m_inputRows = input_dims[NumInputDims-2];
00191       m_inputCols = input_dims[NumInputDims-3];
00192     }
00193 
00194     m_row_strides = op.row_strides();
00195     m_col_strides = op.col_strides();
00196 
00197     // Input strides and effective input/patch size
00198     m_in_row_strides = op.in_row_strides();
00199     m_in_col_strides = op.in_col_strides();
00200     m_row_inflate_strides = op.row_inflate_strides();
00201     m_col_inflate_strides = op.col_inflate_strides();
00202     // The "effective" input rows and input cols are the input rows and cols
00203     // after inflating them with zeros.
00204     // For examples, a 2x3 matrix with row_inflate_strides and
00205     // col_inflate_strides of 2 comes from:
00206     //   A B C
00207     //   D E F
00208     //
00209     // to a matrix is 3 x 5:
00210     //
00211     //   A . B . C
00212     //   . . . . .
00213     //   D . E . F
00214 
00215     m_input_rows_eff = (m_inputRows - 1) * m_row_inflate_strides + 1;
00216     m_input_cols_eff = (m_inputCols - 1) * m_col_inflate_strides + 1;
00217     m_patch_rows_eff = op.patch_rows() + (op.patch_rows() - 1) * (m_in_row_strides - 1);
00218     m_patch_cols_eff = op.patch_cols() + (op.patch_cols() - 1) * (m_in_col_strides - 1);
00219 
00220     if (op.padding_explicit()) {
00221       m_outputRows = numext::ceil((m_input_rows_eff + op.padding_top() + op.padding_bottom() - m_patch_rows_eff + 1.f) / static_cast<float>(m_row_strides));
00222       m_outputCols = numext::ceil((m_input_cols_eff + op.padding_left() + op.padding_right() - m_patch_cols_eff + 1.f) / static_cast<float>(m_col_strides));
00223       m_rowPaddingTop = op.padding_top();
00224       m_colPaddingLeft = op.padding_left();
00225     } else {
00226       // Computing padding from the type
00227       switch (op.padding_type()) {
00228         case PADDING_VALID:
00229           m_outputRows = numext::ceil((m_input_rows_eff - m_patch_rows_eff + 1.f) / static_cast<float>(m_row_strides));
00230           m_outputCols = numext::ceil((m_input_cols_eff - m_patch_cols_eff + 1.f) / static_cast<float>(m_col_strides));
00231           // Calculate the padding
00232           m_rowPaddingTop = numext::maxi<Index>(0, ((m_outputRows - 1) * m_row_strides + m_patch_rows_eff - m_input_rows_eff) / 2);
00233           m_colPaddingLeft = numext::maxi<Index>(0, ((m_outputCols - 1) * m_col_strides + m_patch_cols_eff - m_input_cols_eff) / 2);
00234           break;
00235         case PADDING_SAME:
00236           m_outputRows = numext::ceil(m_input_rows_eff / static_cast<float>(m_row_strides));
00237           m_outputCols = numext::ceil(m_input_cols_eff / static_cast<float>(m_col_strides));
00238           // Calculate the padding
00239           m_rowPaddingTop = ((m_outputRows - 1) * m_row_strides + m_patch_rows_eff - m_input_rows_eff) / 2;
00240           m_colPaddingLeft = ((m_outputCols - 1) * m_col_strides + m_patch_cols_eff - m_input_cols_eff) / 2;
00241           break;
00242         default:
00243           eigen_assert(false && "unexpected padding");
00244       }
00245     }
00246     eigen_assert(m_outputRows > 0);
00247     eigen_assert(m_outputCols > 0);
00248 
00249     // Dimensions for result of extraction.
00250     if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
00251       // ColMajor
00252       // 0: depth
00253       // 1: patch_rows
00254       // 2: patch_cols
00255       // 3: number of patches
00256       // 4 and beyond: anything else (such as batch).
00257       m_dimensions[0] = input_dims[0];
00258       m_dimensions[1] = op.patch_rows();
00259       m_dimensions[2] = op.patch_cols();
00260       m_dimensions[3] = m_outputRows * m_outputCols;
00261       for (int i = 4; i < NumDims; ++i) {
00262         m_dimensions[i] = input_dims[i-1];
00263       }
00264     } else {
00265       // RowMajor
00266       // NumDims-1: depth
00267       // NumDims-2: patch_rows
00268       // NumDims-3: patch_cols
00269       // NumDims-4: number of patches
00270       // NumDims-5 and beyond: anything else (such as batch).
00271       m_dimensions[NumDims-1] = input_dims[NumInputDims-1];
00272       m_dimensions[NumDims-2] = op.patch_rows();
00273       m_dimensions[NumDims-3] = op.patch_cols();
00274       m_dimensions[NumDims-4] = m_outputRows * m_outputCols;
00275       for (int i = NumDims-5; i >= 0; --i) {
00276         m_dimensions[i] = input_dims[i];
00277       }
00278     }
00279 
00280     // Strides for moving the patch in various dimensions.
00281     if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
00282       m_colStride = m_dimensions[1];
00283       m_patchStride = m_colStride * m_dimensions[2] * m_dimensions[0];
00284       m_otherStride = m_patchStride * m_dimensions[3];
00285     } else {
00286       m_colStride = m_dimensions[NumDims-2];
00287       m_patchStride = m_colStride * m_dimensions[NumDims-3] * m_dimensions[NumDims-1];
00288       m_otherStride = m_patchStride * m_dimensions[NumDims-4];
00289     }
00290 
00291     // Strides for navigating through the input tensor.
00292     m_rowInputStride = m_inputDepth;
00293     m_colInputStride = m_inputDepth * m_inputRows;
00294     m_patchInputStride = m_inputDepth * m_inputRows * m_inputCols;
00295 
00296     // Fast representations of different variables.
00297     m_fastOtherStride = internal::TensorIntDivisor<Index>(m_otherStride);
00298     m_fastPatchStride = internal::TensorIntDivisor<Index>(m_patchStride);
00299     m_fastColStride = internal::TensorIntDivisor<Index>(m_colStride);
00300     m_fastInflateRowStride = internal::TensorIntDivisor<Index>(m_row_inflate_strides);
00301     m_fastInflateColStride = internal::TensorIntDivisor<Index>(m_col_inflate_strides);
00302     m_fastInputColsEff = internal::TensorIntDivisor<Index>(m_input_cols_eff);
00303 
00304     // Number of patches in the width dimension.
00305     m_fastOutputRows = internal::TensorIntDivisor<Index>(m_outputRows);
00306     if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
00307       m_fastOutputDepth = internal::TensorIntDivisor<Index>(m_dimensions[0]);
00308     } else {
00309       m_fastOutputDepth = internal::TensorIntDivisor<Index>(m_dimensions[NumDims-1]);
00310     }
00311   }
00312 
00313   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }
00314 
00315   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(Scalar* /*data*/) {
00316     m_impl.evalSubExprsIfNeeded(NULL);
00317     return true;
00318   }
00319 
00320   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() {
00321     m_impl.cleanup();
00322   }
00323 
00324   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
00325   {
00326     // Patch index corresponding to the passed in index.
00327     const Index patchIndex = index / m_fastPatchStride;
00328     // Find the offset of the element wrt the location of the first element.
00329     const Index patchOffset = (index - patchIndex * m_patchStride) / m_fastOutputDepth;
00330 
00331     // Other ways to index this element.
00332     const Index otherIndex = (NumDims == 4) ? 0 : index / m_fastOtherStride;
00333     const Index patch2DIndex = (NumDims == 4) ? patchIndex : (index - otherIndex * m_otherStride) / m_fastPatchStride;
00334 
00335     // Calculate col index in the input original tensor.
00336     const Index colIndex = patch2DIndex / m_fastOutputRows;
00337     const Index colOffset = patchOffset / m_fastColStride;
00338     const Index inputCol = colIndex * m_col_strides + colOffset * m_in_col_strides - m_colPaddingLeft;
00339     const Index origInputCol = (m_col_inflate_strides == 1) ? inputCol : ((inputCol >= 0) ? (inputCol / m_fastInflateColStride) : 0);
00340     if (inputCol < 0 || inputCol >= m_input_cols_eff ||
00341         ((m_col_inflate_strides != 1) && (inputCol != origInputCol * m_col_inflate_strides))) {
00342       return Scalar(m_paddingValue);
00343     }
00344 
00345     // Calculate row index in the original input tensor.
00346     const Index rowIndex = patch2DIndex - colIndex * m_outputRows;
00347     const Index rowOffset = patchOffset - colOffset * m_colStride;
00348     const Index inputRow = rowIndex * m_row_strides + rowOffset * m_in_row_strides - m_rowPaddingTop;
00349     const Index origInputRow = (m_row_inflate_strides == 1) ? inputRow : ((inputRow >= 0) ? (inputRow / m_fastInflateRowStride) : 0);
00350     if (inputRow < 0 || inputRow >= m_input_rows_eff ||
00351         ((m_row_inflate_strides != 1) && (inputRow != origInputRow * m_row_inflate_strides))) {
00352       return Scalar(m_paddingValue);
00353     }
00354 
00355     const int depth_index = static_cast<int>(Layout) == static_cast<int>(ColMajor) ? 0 : NumDims - 1;
00356     const Index depth = index - (index / m_fastOutputDepth) * m_dimensions[depth_index];
00357 
00358     const Index inputIndex = depth + origInputRow * m_rowInputStride + origInputCol * m_colInputStride + otherIndex * m_patchInputStride;
00359     return m_impl.coeff(inputIndex);
00360   }
00361 
00362   template<int LoadMode>
00363   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
00364   {
00365     EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
00366     eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
00367 
00368     if (m_in_row_strides != 1 || m_in_col_strides != 1 || m_row_inflate_strides != 1 || m_col_inflate_strides != 1) {
00369       return packetWithPossibleZero(index);
00370     }
00371 
00372     const Index indices[2] = {index, index + PacketSize - 1};
00373     const Index patchIndex = indices[0] / m_fastPatchStride;
00374     if (patchIndex != indices[1] / m_fastPatchStride) {
00375       return packetWithPossibleZero(index);
00376     }
00377     const Index otherIndex = (NumDims == 4) ? 0 : indices[0] / m_fastOtherStride;
00378     eigen_assert(otherIndex == indices[1] / m_fastOtherStride);
00379 
00380     // Find the offset of the element wrt the location of the first element.
00381     const Index patchOffsets[2] = {(indices[0] - patchIndex * m_patchStride) / m_fastOutputDepth,
00382                                    (indices[1] - patchIndex * m_patchStride) / m_fastOutputDepth};
00383 
00384     const Index patch2DIndex = (NumDims == 4) ? patchIndex : (indices[0] - otherIndex * m_otherStride) / m_fastPatchStride;
00385     eigen_assert(patch2DIndex == (indices[1] - otherIndex * m_otherStride) / m_fastPatchStride);
00386 
00387     const Index colIndex = patch2DIndex / m_fastOutputRows;
00388     const Index colOffsets[2] = {patchOffsets[0] / m_fastColStride, patchOffsets[1] / m_fastColStride};
00389 
00390     // Calculate col indices in the original input tensor.
00391     const Index inputCols[2] = {colIndex * m_col_strides + colOffsets[0] -
00392       m_colPaddingLeft, colIndex * m_col_strides + colOffsets[1] - m_colPaddingLeft};
00393     if (inputCols[1] < 0 || inputCols[0] >= m_inputCols) {
00394       return internal::pset1<PacketReturnType>(Scalar(m_paddingValue));
00395     }
00396 
00397     if (inputCols[0] == inputCols[1]) {
00398       const Index rowIndex = patch2DIndex - colIndex * m_outputRows;
00399       const Index rowOffsets[2] = {patchOffsets[0] - colOffsets[0]*m_colStride, patchOffsets[1] - colOffsets[1]*m_colStride};
00400       eigen_assert(rowOffsets[0] <= rowOffsets[1]);
00401       // Calculate col indices in the original input tensor.
00402       const Index inputRows[2] = {rowIndex * m_row_strides + rowOffsets[0] -
00403         m_rowPaddingTop, rowIndex * m_row_strides + rowOffsets[1] - m_rowPaddingTop};
00404 
00405       if (inputRows[1] < 0 || inputRows[0] >= m_inputRows) {
00406         return internal::pset1<PacketReturnType>(Scalar(m_paddingValue));
00407       }
00408 
00409       if (inputRows[0] >= 0 && inputRows[1] < m_inputRows) {
00410         // no padding
00411         const int depth_index = static_cast<int>(Layout) == static_cast<int>(ColMajor) ? 0 : NumDims - 1;
00412         const Index depth = index - (index / m_fastOutputDepth) * m_dimensions[depth_index];
00413         const Index inputIndex = depth + inputRows[0] * m_rowInputStride + inputCols[0] * m_colInputStride + otherIndex * m_patchInputStride;
00414         return m_impl.template packet<Unaligned>(inputIndex);
00415       }
00416     }
00417 
00418     return packetWithPossibleZero(index);
00419   }
00420 
00421   EIGEN_DEVICE_FUNC Scalar* data() const { return NULL; }
00422 
00423   const TensorEvaluator<ArgType, Device>& impl() const { return m_impl; }
00424 
00425   Index rowPaddingTop() const { return m_rowPaddingTop; }
00426   Index colPaddingLeft() const { return m_colPaddingLeft; }
00427   Index outputRows() const { return m_outputRows; }
00428   Index outputCols() const { return m_outputCols; }
00429   Index userRowStride() const { return m_row_strides; }
00430   Index userColStride() const { return m_col_strides; }
00431   Index userInRowStride() const { return m_in_row_strides; }
00432   Index userInColStride() const { return m_in_col_strides; }
00433   Index rowInflateStride() const { return m_row_inflate_strides; }
00434   Index colInflateStride() const { return m_col_inflate_strides; }
00435 
00436   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost
00437   costPerCoeff(bool vectorized) const {
00438     // We conservatively estimate the cost for the code path where the computed
00439     // index is inside the original image and
00440     // TensorEvaluator<ArgType, Device>::CoordAccess is false.
00441     const double compute_cost = 3 * TensorOpCost::DivCost<Index>() +
00442                                 6 * TensorOpCost::MulCost<Index>() +
00443                                 8 * TensorOpCost::MulCost<Index>();
00444     return m_impl.costPerCoeff(vectorized) +
00445            TensorOpCost(0, 0, compute_cost, vectorized, PacketSize);
00446   }
00447 
00448  protected:
00449   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetWithPossibleZero(Index index) const
00450   {
00451     EIGEN_ALIGN_MAX typename internal::remove_const<CoeffReturnType>::type values[PacketSize];
00452     for (int i = 0; i < PacketSize; ++i) {
00453       values[i] = coeff(index+i);
00454     }
00455     PacketReturnType rslt = internal::pload<PacketReturnType>(values);
00456     return rslt;
00457   }
00458 
00459   Dimensions m_dimensions;
00460 
00461   Index m_otherStride;
00462   Index m_patchStride;
00463   Index m_colStride;
00464   Index m_row_strides;
00465   Index m_col_strides;
00466 
00467   Index m_in_row_strides;
00468   Index m_in_col_strides;
00469   Index m_row_inflate_strides;
00470   Index m_col_inflate_strides;
00471 
00472   Index m_input_rows_eff;
00473   Index m_input_cols_eff;
00474   Index m_patch_rows_eff;
00475   Index m_patch_cols_eff;
00476 
00477   internal::TensorIntDivisor<Index> m_fastOtherStride;
00478   internal::TensorIntDivisor<Index> m_fastPatchStride;
00479   internal::TensorIntDivisor<Index> m_fastColStride;
00480   internal::TensorIntDivisor<Index> m_fastInflateRowStride;
00481   internal::TensorIntDivisor<Index> m_fastInflateColStride;
00482   internal::TensorIntDivisor<Index> m_fastInputColsEff;
00483 
00484   Index m_rowInputStride;
00485   Index m_colInputStride;
00486   Index m_patchInputStride;
00487 
00488   Index m_inputDepth;
00489   Index m_inputRows;
00490   Index m_inputCols;
00491 
00492   Index m_outputRows;
00493   Index m_outputCols;
00494 
00495   Index m_rowPaddingTop;
00496   Index m_colPaddingLeft;
00497 
00498   internal::TensorIntDivisor<Index> m_fastOutputRows;
00499   internal::TensorIntDivisor<Index> m_fastOutputDepth;
00500 
00501   Scalar m_paddingValue;
00502 
00503   TensorEvaluator<ArgType, Device> m_impl;
00504 };
00505 
00506 
00507 } // end namespace Eigen
00508 
00509 #endif // EIGEN_CXX11_TENSOR_TENSOR_IMAGE_PATCH_H
 All Classes Functions Variables Typedefs Enumerator