#include "caffe2/operators/mod_op.h" #include "caffe2/core/operator.h" #include "caffe2/core/tensor.h" namespace caffe2 { template <> template bool ModOp::DoRunWithType() { auto& data = Input(DATA); auto N = data.numel(); const auto* data_ptr = data.template data(); auto* output = Output(0, Input(DATA).sizes(), at::dtype()); auto* output_ptr = output->template mutable_data(); for (auto i = 0; i < N; i++) { output_ptr[i] = data_ptr[i] % divisor_; if (output_ptr[i] && sign_follow_divisor_ && ((output_ptr[i] > 0) != (divisor_ > 0))) { output_ptr[i] += divisor_; } } return true; } namespace { REGISTER_CPU_OPERATOR(Mod, ModOp); OPERATOR_SCHEMA(Mod) .NumInputs(1) .NumOutputs(1) .Arg("divisor", "*(type: int; default: 0)* Divisor of the modulo operation (must be >= 1).") .Arg( "sign_follow_divisor", "*(type: bool; default: False)* If true, sign of output matches divisor, else if false, sign follows dividend.") .IdenticalTypeAndShape() .AllowInplace({{0, 0}}) .SetDoc(R"DOC( Element-wise modulo operation. Each element in the output is the modulo result of the corresponding element in the input data. The divisor of the modulo is provided by the `divisor` argument. Github Link: - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/mod_op.cc
Example **Code** ``` workspace.ResetWorkspace() op = core.CreateOperator( "Mod", ["X"], ["Y"], divisor=10 ) workspace.FeedBlob("X", (np.random.randint(100, size=(5,5)))) print("X before running op:", workspace.FetchBlob("X")) workspace.RunOperatorOnce(op) print("X after running op:", workspace.FetchBlob("Y")) ``` **Result** ``` X before running op: [[56 22 43 13 60] [ 4 55 58 10 45] [64 66 4 3 66] [10 36 47 52 78] [91 4 36 47 95]] X after running op: [[6 2 3 3 0] [4 5 8 0 5] [4 6 4 3 6] [0 6 7 2 8] [1 4 6 7 5]] ```
)DOC") .Input(0, "X", "*(type: Tensor``)* Input tensor with int32 or int64 data.") .Output(0, "Y", "*(type: Tensor``)* Output tensor of data with modulo operation applied."); SHOULD_NOT_DO_GRADIENT(ModOp); } // namespace } // namespace caffe2