|  | #ifndef CAFFE2_OPERATORS_LENGTH_SPLIT_OP_H_ | 
|  | #define CAFFE2_OPERATORS_LENGTH_SPLIT_OP_H_ | 
|  |  | 
|  | #include "caffe2/core/common_omp.h" | 
|  | #include "caffe2/core/context.h" | 
|  | #include "caffe2/core/logging.h" | 
|  | #include "caffe2/core/operator.h" | 
|  | #include "caffe2/utils/math.h" | 
|  |  | 
|  | namespace caffe2 { | 
|  |  | 
|  | template <class Context> | 
|  | class LengthsSplitOp final : public Operator<Context> { | 
|  | public: | 
|  | USE_OPERATOR_CONTEXT_FUNCTIONS; | 
|  |  | 
|  | template <class... Args> | 
|  | explicit LengthsSplitOp(Args&&... args) | 
|  | : Operator<Context>(std::forward<Args>(args)...), | 
|  | n_split_(OperatorBase::GetSingleArgument<int32_t>("n_split", 0)) { | 
|  | if (InputSize() == 1) { | 
|  | // If not specified, then must have this argument | 
|  | CAFFE_ENFORCE( | 
|  | OperatorBase::HasArgument("n_split"), | 
|  | "Argument `n_split` is missing and was not specified as input."); | 
|  | CAFFE_ENFORCE( | 
|  | n_split_ > 0, | 
|  | "`n_split` must contain a positive value for defined behavior."); | 
|  | } | 
|  | } | 
|  | ~LengthsSplitOp() {} | 
|  |  | 
|  | bool RunOnDevice() override { | 
|  | const auto& L = Input(0); | 
|  | CAFFE_ENFORCE_EQ(L.dim(), 1, "Input `LENGTHS` should be a 1D vector."); | 
|  |  | 
|  | if (InputSize() > 1) { | 
|  | // We potentially have n_split specified as inputs as well | 
|  | CAFFE_ENFORCE( | 
|  | Input(1).dim() == 1 && Input(1).numel() == 1, | 
|  | "Input `n_split` should be a vector of size 1."); | 
|  |  | 
|  | const auto& input1 = Input(1); | 
|  | context_.template CopyItems<Context, CPUContext>( | 
|  | input1.dtype(), 1, input1.raw_data(), &n_split_); | 
|  | } | 
|  |  | 
|  | CAFFE_ENFORCE( | 
|  | n_split_ > 0, | 
|  | "`n_split` must contain a positive value for defined behavior."); | 
|  | const auto M = L.numel(); | 
|  |  | 
|  | auto* Y = Output(0, {M * n_split_}, at::dtype<int32_t>()); | 
|  |  | 
|  | const int32_t* Ldata = L.template data<int32_t>(); | 
|  | int32_t* Ydata = Y->template mutable_data<int32_t>(); | 
|  |  | 
|  | for (int i = 0; i < M; i++) { | 
|  | int32_t mod = Ldata[i] % n_split_; | 
|  | int32_t res = | 
|  | mod != 0 ? math::DivUp(Ldata[i], n_split_) : Ldata[i] / n_split_ + 1; | 
|  | for (int j = 0; j < n_split_; j++) { | 
|  | Ydata[(i * n_split_) + j] = mod-- > 0 ? res : res - 1; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | private: | 
|  | int32_t n_split_; | 
|  | }; | 
|  |  | 
|  | } // namespace caffe2 | 
|  |  | 
|  | #endif // CAFFE2_OPERATORS_LENGTH_SPLIT_OP_H_ |