#ifndef CAFFE2_OPERATORS_STRING_OPS_H_ #define CAFFE2_OPERATORS_STRING_OPS_H_ #include "caffe2/core/operator.h" #include "caffe2/operators/elementwise_ops.h" namespace caffe2 { /** * ForEach is a unary functor that forwards each element of the input array * into the elementwise Functor provided, and gathers the results of each * call into the resulting array. Use it as an adaptor if you want to create * a UnaryElementwiseOp that acts on each element of the tensor per function * call -- this is resonable for complex types where vectorization wouldn't * be much of a gain, performance-wise. */ template struct ForEach { explicit ForEach(OperatorBase& op) : functor(op) {} template bool operator()(int n, const In* in, Out* out, Context* /*c*/) { for (int i = 0; i < n; ++i) { out[i] = functor(in[i]); } return true; } Functor functor; }; template > using StringElementwiseOp = UnaryElementwiseWithArgsOp< TensorTypes, CPUContext, ForEach, TypeMap>; template class StringJoinOp final : public Operator { public: USE_OPERATOR_CONTEXT_FUNCTIONS; StringJoinOp(const OperatorDef& operator_def, Workspace* ws) : Operator(operator_def, ws), delimiter_( this->template GetSingleArgument("delimiter", ",")), axis_(this->template GetSingleArgument("axis", 0)) { CAFFE_ENFORCE(axis_ == 0 || axis_ == 1); } bool RunOnDevice() override { return DispatchHelper>::call(this, Input(0)); } template bool DoRunWithType(); protected: std::string delimiter_; int axis_; }; } // namespace caffe2 #endif // CAFFE2_OPERATORS_STRING_OPS_H_