![]() |
Eigen-unsupported
3.3.3
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 00004 #ifndef EIGEN_CXX11_TENSOR_TENSOR_VOLUME_PATCH_H 00005 #define EIGEN_CXX11_TENSOR_TENSOR_VOLUME_PATCH_H 00006 00007 namespace Eigen { 00008 00024 namespace internal { 00025 template<DenseIndex Planes, DenseIndex Rows, DenseIndex Cols, typename XprType> 00026 struct traits<TensorVolumePatchOp<Planes, Rows, Cols, XprType> > : public traits<XprType> 00027 { 00028 typedef typename internal::remove_const<typename XprType::Scalar>::type Scalar; 00029 typedef traits<XprType> XprTraits; 00030 typedef typename XprTraits::StorageKind StorageKind; 00031 typedef typename XprTraits::Index Index; 00032 typedef typename XprType::Nested Nested; 00033 typedef typename remove_reference<Nested>::type _Nested; 00034 static const int NumDimensions = XprTraits::NumDimensions + 1; 00035 static const int Layout = XprTraits::Layout; 00036 }; 00037 00038 template<DenseIndex Planes, DenseIndex Rows, DenseIndex Cols, typename XprType> 00039 struct eval<TensorVolumePatchOp<Planes, Rows, Cols, XprType>, Eigen::Dense> 00040 { 00041 typedef const TensorVolumePatchOp<Planes, Rows, Cols, XprType>& type; 00042 }; 00043 00044 template<DenseIndex Planes, DenseIndex Rows, DenseIndex Cols, typename XprType> 00045 struct nested<TensorVolumePatchOp<Planes, Rows, Cols, XprType>, 1, typename eval<TensorVolumePatchOp<Planes, Rows, Cols, XprType> >::type> 00046 { 00047 typedef TensorVolumePatchOp<Planes, Rows, Cols, XprType> type; 00048 }; 00049 00050 } // end namespace internal 00051 00052 template<DenseIndex Planes, DenseIndex Rows, DenseIndex Cols, typename XprType> 00053 class TensorVolumePatchOp : public TensorBase<TensorVolumePatchOp<Planes, Rows, Cols, XprType>, ReadOnlyAccessors> 00054 { 00055 public: 00056 typedef typename Eigen::internal::traits<TensorVolumePatchOp>::Scalar Scalar; 00057 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; 00058 typedef typename XprType::CoeffReturnType CoeffReturnType; 00059 typedef typename Eigen::internal::nested<TensorVolumePatchOp>::type Nested; 00060 typedef typename Eigen::internal::traits<TensorVolumePatchOp>::StorageKind StorageKind; 00061 typedef typename Eigen::internal::traits<TensorVolumePatchOp>::Index Index; 00062 00063 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorVolumePatchOp(const XprType& expr, DenseIndex patch_planes, DenseIndex patch_rows, DenseIndex patch_cols, 00064 DenseIndex plane_strides, DenseIndex row_strides, DenseIndex col_strides, 00065 DenseIndex in_plane_strides, DenseIndex in_row_strides, DenseIndex in_col_strides, 00066 DenseIndex plane_inflate_strides, DenseIndex row_inflate_strides, DenseIndex col_inflate_strides, 00067 PaddingType padding_type, Scalar padding_value) 00068 : m_xpr(expr), m_patch_planes(patch_planes), m_patch_rows(patch_rows), m_patch_cols(patch_cols), 00069 m_plane_strides(plane_strides), m_row_strides(row_strides), m_col_strides(col_strides), 00070 m_in_plane_strides(in_plane_strides), m_in_row_strides(in_row_strides), m_in_col_strides(in_col_strides), 00071 m_plane_inflate_strides(plane_inflate_strides), m_row_inflate_strides(row_inflate_strides), m_col_inflate_strides(col_inflate_strides), 00072 m_padding_explicit(false), m_padding_top_z(0), m_padding_bottom_z(0), m_padding_top(0), m_padding_bottom(0), m_padding_left(0), m_padding_right(0), 00073 m_padding_type(padding_type), m_padding_value(padding_value) {} 00074 00075 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorVolumePatchOp(const XprType& expr, DenseIndex patch_planes, DenseIndex patch_rows, DenseIndex patch_cols, 00076 DenseIndex plane_strides, DenseIndex row_strides, DenseIndex col_strides, 00077 DenseIndex in_plane_strides, DenseIndex in_row_strides, DenseIndex in_col_strides, 00078 DenseIndex plane_inflate_strides, DenseIndex row_inflate_strides, DenseIndex col_inflate_strides, 00079 DenseIndex padding_top_z, DenseIndex padding_bottom_z, 00080 DenseIndex padding_top, DenseIndex padding_bottom, 00081 DenseIndex padding_left, DenseIndex padding_right, 00082 Scalar padding_value) 00083 : m_xpr(expr), m_patch_planes(patch_planes), m_patch_rows(patch_rows), m_patch_cols(patch_cols), 00084 m_plane_strides(plane_strides), m_row_strides(row_strides), m_col_strides(col_strides), 00085 m_in_plane_strides(in_plane_strides), m_in_row_strides(in_row_strides), m_in_col_strides(in_col_strides), 00086 m_plane_inflate_strides(plane_inflate_strides), m_row_inflate_strides(row_inflate_strides), m_col_inflate_strides(col_inflate_strides), 00087 m_padding_explicit(true), m_padding_top_z(padding_top_z), m_padding_bottom_z(padding_bottom_z), m_padding_top(padding_top), m_padding_bottom(padding_bottom), 00088 m_padding_left(padding_left), m_padding_right(padding_right), 00089 m_padding_type(PADDING_VALID), m_padding_value(padding_value) {} 00090 00091 EIGEN_DEVICE_FUNC 00092 DenseIndex patch_planes() const { return m_patch_planes; } 00093 EIGEN_DEVICE_FUNC 00094 DenseIndex patch_rows() const { return m_patch_rows; } 00095 EIGEN_DEVICE_FUNC 00096 DenseIndex patch_cols() const { return m_patch_cols; } 00097 EIGEN_DEVICE_FUNC 00098 DenseIndex plane_strides() const { return m_plane_strides; } 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_plane_strides() const { return m_in_plane_strides; } 00105 EIGEN_DEVICE_FUNC 00106 DenseIndex in_row_strides() const { return m_in_row_strides; } 00107 EIGEN_DEVICE_FUNC 00108 DenseIndex in_col_strides() const { return m_in_col_strides; } 00109 EIGEN_DEVICE_FUNC 00110 DenseIndex plane_inflate_strides() const { return m_plane_inflate_strides; } 00111 EIGEN_DEVICE_FUNC 00112 DenseIndex row_inflate_strides() const { return m_row_inflate_strides; } 00113 EIGEN_DEVICE_FUNC 00114 DenseIndex col_inflate_strides() const { return m_col_inflate_strides; } 00115 EIGEN_DEVICE_FUNC 00116 bool padding_explicit() const { return m_padding_explicit; } 00117 EIGEN_DEVICE_FUNC 00118 DenseIndex padding_top_z() const { return m_padding_top_z; } 00119 EIGEN_DEVICE_FUNC 00120 DenseIndex padding_bottom_z() const { return m_padding_bottom_z; } 00121 EIGEN_DEVICE_FUNC 00122 DenseIndex padding_top() const { return m_padding_top; } 00123 EIGEN_DEVICE_FUNC 00124 DenseIndex padding_bottom() const { return m_padding_bottom; } 00125 EIGEN_DEVICE_FUNC 00126 DenseIndex padding_left() const { return m_padding_left; } 00127 EIGEN_DEVICE_FUNC 00128 DenseIndex padding_right() const { return m_padding_right; } 00129 EIGEN_DEVICE_FUNC 00130 PaddingType padding_type() const { return m_padding_type; } 00131 EIGEN_DEVICE_FUNC 00132 Scalar padding_value() const { return m_padding_value; } 00133 00134 EIGEN_DEVICE_FUNC 00135 const typename internal::remove_all<typename XprType::Nested>::type& 00136 expression() const { return m_xpr; } 00137 00138 protected: 00139 typename XprType::Nested m_xpr; 00140 const DenseIndex m_patch_planes; 00141 const DenseIndex m_patch_rows; 00142 const DenseIndex m_patch_cols; 00143 const DenseIndex m_plane_strides; 00144 const DenseIndex m_row_strides; 00145 const DenseIndex m_col_strides; 00146 const DenseIndex m_in_plane_strides; 00147 const DenseIndex m_in_row_strides; 00148 const DenseIndex m_in_col_strides; 00149 const DenseIndex m_plane_inflate_strides; 00150 const DenseIndex m_row_inflate_strides; 00151 const DenseIndex m_col_inflate_strides; 00152 const bool m_padding_explicit; 00153 const DenseIndex m_padding_top_z; 00154 const DenseIndex m_padding_bottom_z; 00155 const DenseIndex m_padding_top; 00156 const DenseIndex m_padding_bottom; 00157 const DenseIndex m_padding_left; 00158 const DenseIndex m_padding_right; 00159 const PaddingType m_padding_type; 00160 const Scalar m_padding_value; 00161 }; 00162 00163 00164 // Eval as rvalue 00165 template<DenseIndex Planes, DenseIndex Rows, DenseIndex Cols, typename ArgType, typename Device> 00166 struct TensorEvaluator<const TensorVolumePatchOp<Planes, Rows, Cols, ArgType>, Device> 00167 { 00168 typedef TensorVolumePatchOp<Planes, Rows, Cols, ArgType> XprType; 00169 typedef typename XprType::Index Index; 00170 static const int NumInputDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value; 00171 static const int NumDims = NumInputDims + 1; 00172 typedef DSizes<Index, NumDims> Dimensions; 00173 typedef typename internal::remove_const<typename XprType::Scalar>::type Scalar; 00174 typedef typename XprType::CoeffReturnType CoeffReturnType; 00175 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType; 00176 static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size; 00177 00178 enum { 00179 IsAligned = false, 00180 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess, 00181 BlockAccess = false, 00182 Layout = TensorEvaluator<ArgType, Device>::Layout, 00183 CoordAccess = false, 00184 RawAccess = false 00185 }; 00186 00187 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device) 00188 : m_impl(op.expression(), device) 00189 { 00190 EIGEN_STATIC_ASSERT((NumDims >= 5), YOU_MADE_A_PROGRAMMING_MISTAKE); 00191 00192 m_paddingValue = op.padding_value(); 00193 00194 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions(); 00195 00196 // Cache a few variables. 00197 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) { 00198 m_inputDepth = input_dims[0]; 00199 m_inputPlanes = input_dims[1]; 00200 m_inputRows = input_dims[2]; 00201 m_inputCols = input_dims[3]; 00202 } else { 00203 m_inputDepth = input_dims[NumInputDims-1]; 00204 m_inputPlanes = input_dims[NumInputDims-2]; 00205 m_inputRows = input_dims[NumInputDims-3]; 00206 m_inputCols = input_dims[NumInputDims-4]; 00207 } 00208 00209 m_plane_strides = op.plane_strides(); 00210 m_row_strides = op.row_strides(); 00211 m_col_strides = op.col_strides(); 00212 00213 // Input strides and effective input/patch size 00214 m_in_plane_strides = op.in_plane_strides(); 00215 m_in_row_strides = op.in_row_strides(); 00216 m_in_col_strides = op.in_col_strides(); 00217 m_plane_inflate_strides = op.plane_inflate_strides(); 00218 m_row_inflate_strides = op.row_inflate_strides(); 00219 m_col_inflate_strides = op.col_inflate_strides(); 00220 00221 // The "effective" spatial size after inflating data with zeros. 00222 m_input_planes_eff = (m_inputPlanes - 1) * m_plane_inflate_strides + 1; 00223 m_input_rows_eff = (m_inputRows - 1) * m_row_inflate_strides + 1; 00224 m_input_cols_eff = (m_inputCols - 1) * m_col_inflate_strides + 1; 00225 m_patch_planes_eff = op.patch_planes() + (op.patch_planes() - 1) * (m_in_plane_strides - 1); 00226 m_patch_rows_eff = op.patch_rows() + (op.patch_rows() - 1) * (m_in_row_strides - 1); 00227 m_patch_cols_eff = op.patch_cols() + (op.patch_cols() - 1) * (m_in_col_strides - 1); 00228 00229 if (op.padding_explicit()) { 00230 m_outputPlanes = numext::ceil((m_input_planes_eff + op.padding_top_z() + op.padding_bottom_z() - m_patch_planes_eff + 1.f) / static_cast<float>(m_plane_strides)); 00231 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)); 00232 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)); 00233 m_planePaddingTop = op.padding_top_z(); 00234 m_rowPaddingTop = op.padding_top(); 00235 m_colPaddingLeft = op.padding_left(); 00236 } else { 00237 // Computing padding from the type 00238 switch (op.padding_type()) { 00239 case PADDING_VALID: 00240 m_outputPlanes = numext::ceil((m_input_planes_eff - m_patch_planes_eff + 1.f) / static_cast<float>(m_plane_strides)); 00241 m_outputRows = numext::ceil((m_input_rows_eff - m_patch_rows_eff + 1.f) / static_cast<float>(m_row_strides)); 00242 m_outputCols = numext::ceil((m_input_cols_eff - m_patch_cols_eff + 1.f) / static_cast<float>(m_col_strides)); 00243 m_planePaddingTop = 0; 00244 m_rowPaddingTop = 0; 00245 m_colPaddingLeft = 0; 00246 break; 00247 case PADDING_SAME: { 00248 m_outputPlanes = numext::ceil(m_input_planes_eff / static_cast<float>(m_plane_strides)); 00249 m_outputRows = numext::ceil(m_input_rows_eff / static_cast<float>(m_row_strides)); 00250 m_outputCols = numext::ceil(m_input_cols_eff / static_cast<float>(m_col_strides)); 00251 const Index dz = m_outputPlanes * m_plane_strides + m_patch_planes_eff - 1 - m_input_planes_eff; 00252 const Index dy = m_outputRows * m_row_strides + m_patch_rows_eff - 1 - m_input_rows_eff; 00253 const Index dx = m_outputCols * m_col_strides + m_patch_cols_eff - 1 - m_input_cols_eff; 00254 m_planePaddingTop = dz - dz / 2; 00255 m_rowPaddingTop = dy - dy / 2; 00256 m_colPaddingLeft = dx - dx / 2; 00257 break; 00258 } 00259 default: 00260 eigen_assert(false && "unexpected padding"); 00261 } 00262 } 00263 eigen_assert(m_outputRows > 0); 00264 eigen_assert(m_outputCols > 0); 00265 eigen_assert(m_outputPlanes > 0); 00266 00267 // Dimensions for result of extraction. 00268 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) { 00269 // ColMajor 00270 // 0: depth 00271 // 1: patch_planes 00272 // 2: patch_rows 00273 // 3: patch_cols 00274 // 4: number of patches 00275 // 5 and beyond: anything else (such as batch). 00276 m_dimensions[0] = input_dims[0]; 00277 m_dimensions[1] = op.patch_planes(); 00278 m_dimensions[2] = op.patch_rows(); 00279 m_dimensions[3] = op.patch_cols(); 00280 m_dimensions[4] = m_outputPlanes * m_outputRows * m_outputCols; 00281 for (int i = 5; i < NumDims; ++i) { 00282 m_dimensions[i] = input_dims[i-1]; 00283 } 00284 } else { 00285 // RowMajor 00286 // NumDims-1: depth 00287 // NumDims-2: patch_planes 00288 // NumDims-3: patch_rows 00289 // NumDims-4: patch_cols 00290 // NumDims-5: number of patches 00291 // NumDims-6 and beyond: anything else (such as batch). 00292 m_dimensions[NumDims-1] = input_dims[NumInputDims-1]; 00293 m_dimensions[NumDims-2] = op.patch_planes(); 00294 m_dimensions[NumDims-3] = op.patch_rows(); 00295 m_dimensions[NumDims-4] = op.patch_cols(); 00296 m_dimensions[NumDims-5] = m_outputPlanes * m_outputRows * m_outputCols; 00297 for (int i = NumDims-6; i >= 0; --i) { 00298 m_dimensions[i] = input_dims[i]; 00299 } 00300 } 00301 00302 // Strides for the output tensor. 00303 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) { 00304 m_rowStride = m_dimensions[1]; 00305 m_colStride = m_dimensions[2] * m_rowStride; 00306 m_patchStride = m_colStride * m_dimensions[3] * m_dimensions[0]; 00307 m_otherStride = m_patchStride * m_dimensions[4]; 00308 } else { 00309 m_rowStride = m_dimensions[NumDims-2]; 00310 m_colStride = m_dimensions[NumDims-3] * m_rowStride; 00311 m_patchStride = m_colStride * m_dimensions[NumDims-4] * m_dimensions[NumDims-1]; 00312 m_otherStride = m_patchStride * m_dimensions[NumDims-5]; 00313 } 00314 00315 // Strides for navigating through the input tensor. 00316 m_planeInputStride = m_inputDepth; 00317 m_rowInputStride = m_inputDepth * m_inputPlanes; 00318 m_colInputStride = m_inputDepth * m_inputRows * m_inputPlanes; 00319 m_otherInputStride = m_inputDepth * m_inputRows * m_inputCols * m_inputPlanes; 00320 00321 m_outputPlanesRows = m_outputPlanes * m_outputRows; 00322 00323 // Fast representations of different variables. 00324 m_fastOtherStride = internal::TensorIntDivisor<Index>(m_otherStride); 00325 m_fastPatchStride = internal::TensorIntDivisor<Index>(m_patchStride); 00326 m_fastColStride = internal::TensorIntDivisor<Index>(m_colStride); 00327 m_fastRowStride = internal::TensorIntDivisor<Index>(m_rowStride); 00328 m_fastInputRowStride = internal::TensorIntDivisor<Index>(m_row_inflate_strides); 00329 m_fastInputColStride = internal::TensorIntDivisor<Index>(m_col_inflate_strides); 00330 m_fastInputPlaneStride = internal::TensorIntDivisor<Index>(m_plane_inflate_strides); 00331 m_fastInputColsEff = internal::TensorIntDivisor<Index>(m_input_cols_eff); 00332 m_fastOutputPlanes = internal::TensorIntDivisor<Index>(m_outputPlanes); 00333 m_fastOutputPlanesRows = internal::TensorIntDivisor<Index>(m_outputPlanesRows); 00334 00335 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) { 00336 m_fastOutputDepth = internal::TensorIntDivisor<Index>(m_dimensions[0]); 00337 } else { 00338 m_fastOutputDepth = internal::TensorIntDivisor<Index>(m_dimensions[NumDims-1]); 00339 } 00340 } 00341 00342 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; } 00343 00344 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(Scalar* /*data*/) { 00345 m_impl.evalSubExprsIfNeeded(NULL); 00346 return true; 00347 } 00348 00349 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() { 00350 m_impl.cleanup(); 00351 } 00352 00353 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const 00354 { 00355 // Patch index corresponding to the passed in index. 00356 const Index patchIndex = index / m_fastPatchStride; 00357 00358 // Spatial offset within the patch. This has to be translated into 3D 00359 // coordinates within the patch. 00360 const Index patchOffset = (index - patchIndex * m_patchStride) / m_fastOutputDepth; 00361 00362 // Batch, etc. 00363 const Index otherIndex = (NumDims == 5) ? 0 : index / m_fastOtherStride; 00364 const Index patch3DIndex = (NumDims == 5) ? patchIndex : (index - otherIndex * m_otherStride) / m_fastPatchStride; 00365 00366 // Calculate column index in the input original tensor. 00367 const Index colIndex = patch3DIndex / m_fastOutputPlanesRows; 00368 const Index colOffset = patchOffset / m_fastColStride; 00369 const Index inputCol = colIndex * m_col_strides + colOffset * m_in_col_strides - m_colPaddingLeft; 00370 const Index origInputCol = (m_col_inflate_strides == 1) ? inputCol : ((inputCol >= 0) ? (inputCol / m_fastInputColStride) : 0); 00371 if (inputCol < 0 || inputCol >= m_input_cols_eff || 00372 ((m_col_inflate_strides != 1) && (inputCol != origInputCol * m_col_inflate_strides))) { 00373 return Scalar(m_paddingValue); 00374 } 00375 00376 // Calculate row index in the original input tensor. 00377 const Index rowIndex = (patch3DIndex - colIndex * m_outputPlanesRows) / m_fastOutputPlanes; 00378 const Index rowOffset = (patchOffset - colOffset * m_colStride) / m_fastRowStride; 00379 const Index inputRow = rowIndex * m_row_strides + rowOffset * m_in_row_strides - m_rowPaddingTop; 00380 const Index origInputRow = (m_row_inflate_strides == 1) ? inputRow : ((inputRow >= 0) ? (inputRow / m_fastInputRowStride) : 0); 00381 if (inputRow < 0 || inputRow >= m_input_rows_eff || 00382 ((m_row_inflate_strides != 1) && (inputRow != origInputRow * m_row_inflate_strides))) { 00383 return Scalar(m_paddingValue); 00384 } 00385 00386 // Calculate plane index in the original input tensor. 00387 const Index planeIndex = (patch3DIndex - m_outputPlanes * (colIndex * m_outputRows + rowIndex)); 00388 const Index planeOffset = patchOffset - colOffset * m_colStride - rowOffset * m_rowStride; 00389 const Index inputPlane = planeIndex * m_plane_strides + planeOffset * m_in_plane_strides - m_planePaddingTop; 00390 const Index origInputPlane = (m_plane_inflate_strides == 1) ? inputPlane : ((inputPlane >= 0) ? (inputPlane / m_fastInputPlaneStride) : 0); 00391 if (inputPlane < 0 || inputPlane >= m_input_planes_eff || 00392 ((m_plane_inflate_strides != 1) && (inputPlane != origInputPlane * m_plane_inflate_strides))) { 00393 return Scalar(m_paddingValue); 00394 } 00395 00396 const int depth_index = static_cast<int>(Layout) == static_cast<int>(ColMajor) ? 0 : NumDims - 1; 00397 const Index depth = index - (index / m_fastOutputDepth) * m_dimensions[depth_index]; 00398 00399 const Index inputIndex = depth + 00400 origInputRow * m_rowInputStride + 00401 origInputCol * m_colInputStride + 00402 origInputPlane * m_planeInputStride + 00403 otherIndex * m_otherInputStride; 00404 00405 return m_impl.coeff(inputIndex); 00406 } 00407 00408 template<int LoadMode> 00409 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const 00410 { 00411 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE) 00412 eigen_assert(index+PacketSize-1 < dimensions().TotalSize()); 00413 00414 if (m_in_row_strides != 1 || m_in_col_strides != 1 || m_row_inflate_strides != 1 || m_col_inflate_strides != 1 || 00415 m_in_plane_strides != 1 || m_plane_inflate_strides != 1) { 00416 return packetWithPossibleZero(index); 00417 } 00418 00419 const Index indices[2] = {index, index + PacketSize - 1}; 00420 const Index patchIndex = indices[0] / m_fastPatchStride; 00421 if (patchIndex != indices[1] / m_fastPatchStride) { 00422 return packetWithPossibleZero(index); 00423 } 00424 const Index otherIndex = (NumDims == 5) ? 0 : indices[0] / m_fastOtherStride; 00425 eigen_assert(otherIndex == indices[1] / m_fastOtherStride); 00426 00427 // Find the offset of the element wrt the location of the first element. 00428 const Index patchOffsets[2] = {(indices[0] - patchIndex * m_patchStride) / m_fastOutputDepth, 00429 (indices[1] - patchIndex * m_patchStride) / m_fastOutputDepth}; 00430 00431 const Index patch3DIndex = (NumDims == 5) ? patchIndex : (indices[0] - otherIndex * m_otherStride) / m_fastPatchStride; 00432 eigen_assert(patch3DIndex == (indices[1] - otherIndex * m_otherStride) / m_fastPatchStride); 00433 00434 const Index colIndex = patch3DIndex / m_fastOutputPlanesRows; 00435 const Index colOffsets[2] = { 00436 patchOffsets[0] / m_fastColStride, 00437 patchOffsets[1] / m_fastColStride}; 00438 00439 // Calculate col indices in the original input tensor. 00440 const Index inputCols[2] = { 00441 colIndex * m_col_strides + colOffsets[0] - m_colPaddingLeft, 00442 colIndex * m_col_strides + colOffsets[1] - m_colPaddingLeft}; 00443 if (inputCols[1] < 0 || inputCols[0] >= m_inputCols) { 00444 return internal::pset1<PacketReturnType>(Scalar(m_paddingValue)); 00445 } 00446 00447 if (inputCols[0] != inputCols[1]) { 00448 return packetWithPossibleZero(index); 00449 } 00450 00451 const Index rowIndex = (patch3DIndex - colIndex * m_outputPlanesRows) / m_fastOutputPlanes; 00452 const Index rowOffsets[2] = { 00453 (patchOffsets[0] - colOffsets[0] * m_colStride) / m_fastRowStride, 00454 (patchOffsets[1] - colOffsets[1] * m_colStride) / m_fastRowStride}; 00455 eigen_assert(rowOffsets[0] <= rowOffsets[1]); 00456 // Calculate col indices in the original input tensor. 00457 const Index inputRows[2] = { 00458 rowIndex * m_row_strides + rowOffsets[0] - m_rowPaddingTop, 00459 rowIndex * m_row_strides + rowOffsets[1] - m_rowPaddingTop}; 00460 00461 if (inputRows[1] < 0 || inputRows[0] >= m_inputRows) { 00462 return internal::pset1<PacketReturnType>(Scalar(m_paddingValue)); 00463 } 00464 00465 if (inputRows[0] != inputRows[1]) { 00466 return packetWithPossibleZero(index); 00467 } 00468 00469 const Index planeIndex = (patch3DIndex - m_outputPlanes * (colIndex * m_outputRows + rowIndex)); 00470 const Index planeOffsets[2] = { 00471 patchOffsets[0] - colOffsets[0] * m_colStride - rowOffsets[0] * m_rowStride, 00472 patchOffsets[1] - colOffsets[1] * m_colStride - rowOffsets[1] * m_rowStride}; 00473 eigen_assert(planeOffsets[0] <= planeOffsets[1]); 00474 const Index inputPlanes[2] = { 00475 planeIndex * m_plane_strides + planeOffsets[0] - m_planePaddingTop, 00476 planeIndex * m_plane_strides + planeOffsets[1] - m_planePaddingTop}; 00477 00478 if (inputPlanes[1] < 0 || inputPlanes[0] >= m_inputPlanes) { 00479 return internal::pset1<PacketReturnType>(Scalar(m_paddingValue)); 00480 } 00481 00482 if (inputPlanes[0] >= 0 && inputPlanes[1] < m_inputPlanes) { 00483 // no padding 00484 const int depth_index = static_cast<int>(Layout) == static_cast<int>(ColMajor) ? 0 : NumDims - 1; 00485 const Index depth = index - (index / m_fastOutputDepth) * m_dimensions[depth_index]; 00486 const Index inputIndex = depth + 00487 inputRows[0] * m_rowInputStride + 00488 inputCols[0] * m_colInputStride + 00489 m_planeInputStride * inputPlanes[0] + 00490 otherIndex * m_otherInputStride; 00491 return m_impl.template packet<Unaligned>(inputIndex); 00492 } 00493 00494 return packetWithPossibleZero(index); 00495 } 00496 00497 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost 00498 costPerCoeff(bool vectorized) const { 00499 const double compute_cost = 00500 10 * TensorOpCost::DivCost<Index>() + 21 * TensorOpCost::MulCost<Index>() + 00501 8 * TensorOpCost::AddCost<Index>(); 00502 return TensorOpCost(0, 0, compute_cost, vectorized, PacketSize); 00503 } 00504 00505 EIGEN_DEVICE_FUNC Scalar* data() const { return NULL; } 00506 00507 const TensorEvaluator<ArgType, Device>& impl() const { return m_impl; } 00508 00509 Index planePaddingTop() const { return m_planePaddingTop; } 00510 Index rowPaddingTop() const { return m_rowPaddingTop; } 00511 Index colPaddingLeft() const { return m_colPaddingLeft; } 00512 Index outputPlanes() const { return m_outputPlanes; } 00513 Index outputRows() const { return m_outputRows; } 00514 Index outputCols() const { return m_outputCols; } 00515 Index userPlaneStride() const { return m_plane_strides; } 00516 Index userRowStride() const { return m_row_strides; } 00517 Index userColStride() const { return m_col_strides; } 00518 Index userInPlaneStride() const { return m_in_plane_strides; } 00519 Index userInRowStride() const { return m_in_row_strides; } 00520 Index userInColStride() const { return m_in_col_strides; } 00521 Index planeInflateStride() const { return m_plane_inflate_strides; } 00522 Index rowInflateStride() const { return m_row_inflate_strides; } 00523 Index colInflateStride() const { return m_col_inflate_strides; } 00524 00525 protected: 00526 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetWithPossibleZero(Index index) const 00527 { 00528 EIGEN_ALIGN_MAX typename internal::remove_const<CoeffReturnType>::type values[PacketSize]; 00529 for (int i = 0; i < PacketSize; ++i) { 00530 values[i] = coeff(index+i); 00531 } 00532 PacketReturnType rslt = internal::pload<PacketReturnType>(values); 00533 return rslt; 00534 } 00535 00536 Dimensions m_dimensions; 00537 00538 // Parameters passed to the costructor. 00539 Index m_plane_strides; 00540 Index m_row_strides; 00541 Index m_col_strides; 00542 00543 Index m_outputPlanes; 00544 Index m_outputRows; 00545 Index m_outputCols; 00546 00547 Index m_planePaddingTop; 00548 Index m_rowPaddingTop; 00549 Index m_colPaddingLeft; 00550 00551 Index m_in_plane_strides; 00552 Index m_in_row_strides; 00553 Index m_in_col_strides; 00554 00555 Index m_plane_inflate_strides; 00556 Index m_row_inflate_strides; 00557 Index m_col_inflate_strides; 00558 00559 // Cached input size. 00560 Index m_inputDepth; 00561 Index m_inputPlanes; 00562 Index m_inputRows; 00563 Index m_inputCols; 00564 00565 // Other cached variables. 00566 Index m_outputPlanesRows; 00567 00568 // Effective input/patch post-inflation size. 00569 Index m_input_planes_eff; 00570 Index m_input_rows_eff; 00571 Index m_input_cols_eff; 00572 Index m_patch_planes_eff; 00573 Index m_patch_rows_eff; 00574 Index m_patch_cols_eff; 00575 00576 // Strides for the output tensor. 00577 Index m_otherStride; 00578 Index m_patchStride; 00579 Index m_rowStride; 00580 Index m_colStride; 00581 00582 // Strides for the input tensor. 00583 Index m_planeInputStride; 00584 Index m_rowInputStride; 00585 Index m_colInputStride; 00586 Index m_otherInputStride; 00587 00588 internal::TensorIntDivisor<Index> m_fastOtherStride; 00589 internal::TensorIntDivisor<Index> m_fastPatchStride; 00590 internal::TensorIntDivisor<Index> m_fastColStride; 00591 internal::TensorIntDivisor<Index> m_fastRowStride; 00592 internal::TensorIntDivisor<Index> m_fastInputPlaneStride; 00593 internal::TensorIntDivisor<Index> m_fastInputRowStride; 00594 internal::TensorIntDivisor<Index> m_fastInputColStride; 00595 internal::TensorIntDivisor<Index> m_fastInputColsEff; 00596 internal::TensorIntDivisor<Index> m_fastOutputPlanesRows; 00597 internal::TensorIntDivisor<Index> m_fastOutputPlanes; 00598 internal::TensorIntDivisor<Index> m_fastOutputDepth; 00599 00600 Scalar m_paddingValue; 00601 00602 TensorEvaluator<ArgType, Device> m_impl; 00603 }; 00604 00605 00606 } // end namespace Eigen 00607 00608 #endif // EIGEN_CXX11_TENSOR_TENSOR_VOLUME_PATCH_H