TensorVolumePatch.h
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
 All Classes Functions Variables Typedefs Enumerator