|  | #ifndef CAFFE2_OPERATORS_PAD_OP_H_ | 
|  | #define CAFFE2_OPERATORS_PAD_OP_H_ | 
|  |  | 
|  | #include "caffe2/core/context.h" | 
|  | #include "caffe2/core/logging.h" | 
|  | #include "caffe2/core/operator.h" | 
|  | #include "caffe2/operators/conv_pool_op_base.h" | 
|  | #include "caffe2/utils/math.h" | 
|  |  | 
|  | namespace caffe2 { | 
|  |  | 
|  | // Padding mode similar to numpy. | 
|  | enum class PadMode { | 
|  | CONSTANT = 0, // pad constant values, with string "constant" | 
|  | REFLECT = 1, // pads with reflect values, with string "reflect" | 
|  | EDGE = 2, // pads with the edge values, with string "edge" | 
|  | }; | 
|  |  | 
|  | TORCH_API PadMode StringToPadMode(const string&); | 
|  |  | 
|  | template <typename T, class Context> | 
|  | class PadImageOp final : public ConvPoolOpBase<Context> { | 
|  | public: | 
|  | USE_CONV_POOL_BASE_FUNCTIONS(Context); | 
|  | template <class... Args> | 
|  | explicit PadImageOp(Args&&... args) | 
|  | : ConvPoolOpBase<Context>(std::forward<Args>(args)...), | 
|  | mode_(StringToPadMode( | 
|  | this->template GetSingleArgument<string>("mode", "constant"))), | 
|  | value_(static_cast<T>( | 
|  | this->template GetSingleArgument<float>("value", 0.0))) { | 
|  | CAFFE_ENFORCE( | 
|  | legacy_pad_ == LegacyPadding::NOTSET, | 
|  | "Padding layer only supports explicit pad values."); | 
|  | CAFFE_ENFORCE( | 
|  | dilation_h() == 1 && dilation_w() == 1, | 
|  | "Pooling op does not support dilation right now."); | 
|  | CAFFE_ENFORCE( | 
|  | stride_h() == 1 && stride_w() == 1, | 
|  | "Pooling op does not support stride right now."); | 
|  | // Pad op does not use kernel sizes, so we set it to 1 for computing the | 
|  | // output size. | 
|  | kernel_.assign(pads_.size() / 2, 1); | 
|  | } | 
|  | ~PadImageOp() {} | 
|  |  | 
|  | bool RunOnDeviceWithOrderNCHW() override; | 
|  | bool RunOnDeviceWithOrderNHWC() override; | 
|  |  | 
|  | static std::vector<TensorShape> PadTensorInference( | 
|  | const OperatorDef& def, | 
|  | const vector<TensorShape>& in); | 
|  |  | 
|  | private: | 
|  | PadMode mode_; | 
|  | T value_; | 
|  |  | 
|  | // Input: X | 
|  | // Output: Y | 
|  | }; | 
|  |  | 
|  | template <typename T, class Context> | 
|  | class PadImageGradientOp final : public ConvPoolOpBase<Context> { | 
|  | public: | 
|  | USE_CONV_POOL_BASE_FUNCTIONS(Context); | 
|  | template <class... Args> | 
|  | explicit PadImageGradientOp(Args&&... args) | 
|  | : ConvPoolOpBase<Context>(std::forward<Args>(args)...), | 
|  | mode_(StringToPadMode( | 
|  | this->template GetSingleArgument<string>("mode", "constant"))) { | 
|  | CAFFE_ENFORCE( | 
|  | legacy_pad_ == LegacyPadding::NOTSET, | 
|  | "Padding layer only supports explicit pad values."); | 
|  | CAFFE_ENFORCE( | 
|  | dilation_h() == 1 && dilation_w() == 1, | 
|  | "Pooling op does not support dilation right now."); | 
|  | // Pad op does not use kernel sizes, so we set it to 1 for computing the | 
|  | // output size. | 
|  | kernel_.assign(pads_.size() / 2, 1); | 
|  | } | 
|  | ~PadImageGradientOp() {} | 
|  |  | 
|  | bool RunOnDeviceWithOrderNCHW() override; | 
|  | bool RunOnDeviceWithOrderNHWC() override; | 
|  |  | 
|  | private: | 
|  | PadMode mode_; | 
|  | // Input: dY | 
|  | // Output: dX | 
|  | }; | 
|  |  | 
|  | } // namespace caffe2 | 
|  |  | 
|  | #endif // CAFFE2_OPERATORS_PAD_OP_H_ |