![]() |
Eigen-unsupported
3.3.3
|
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