#include "caffe2/operators/tan_op.h" #include "caffe2/utils/eigen_utils.h" #include #include namespace caffe2 { template <> template bool TanGradientFunctor::Forward( const std::vector& X_dims, const std::vector& /* dY_dims */, const T* X, const T* dY, T* dX, CPUContext* /* context */) const { const int size = std::accumulate( X_dims.cbegin(), X_dims.cend(), 1, std::multiplies()); ConstEigenVectorArrayMap dY_arr(dY, size); ConstEigenVectorArrayMap X_arr(X, size); EigenVectorMap(dX, size) = dY_arr / X_arr.cos().square(); return true; } REGISTER_CPU_OPERATOR( Tan, UnaryElementwiseOp, CPUContext, TanFunctor>); REGISTER_CPU_OPERATOR( TanGradient, BinaryElementwiseOp< TensorTypes, CPUContext, TanGradientFunctor>); OPERATOR_SCHEMA(Tan) .NumInputs(1) .NumOutputs(1) .IdenticalTypeAndShape() .SetDoc(R"DOC( Calculates the tangent of the given input tensor, element-wise. )DOC") .Input(0, "input", "Input tensor") .Output( 0, "output", "The tangent of the input tensor computed element-wise"); OPERATOR_SCHEMA(TanGradient).NumInputs(2).NumOutputs(1).IdenticalTypeAndShape(); namespace { class GetTanGradient : public GradientMakerBase { using GradientMakerBase::GradientMakerBase; std::vector GetGradientDefs() override { return SingleGradientDef( "TanGradient", "", std::vector{I(0), GO(0)}, std::vector{GI(0)}); } }; } // namespace REGISTER_GRADIENT(Tan, GetTanGradient); } // namespace caffe2