diff --git a/kernels/test/CMakeLists.txt b/kernels/test/CMakeLists.txt index 991da25ff7f..f5b51dc97c3 100644 --- a/kernels/test/CMakeLists.txt +++ b/kernels/test/CMakeLists.txt @@ -241,6 +241,7 @@ set(_optimized_kernels_test_sources "op_native_layer_norm_test.cpp" "op_neg_test.cpp" "op_sub_test.cpp" + "UnaryUfuncRealHBToFloatHTest.cpp" ${CMAKE_CURRENT_BINARY_DIR}/include/portable/executorch/kernels/test/supported_features.cpp ) diff --git a/kernels/test/UnaryUfuncRealHBToFloatHTest.h b/kernels/test/UnaryUfuncRealHBToFloatHTest.h index 7e9e5cf24cb..4ce41b2ed3c 100644 --- a/kernels/test/UnaryUfuncRealHBToFloatHTest.h +++ b/kernels/test/UnaryUfuncRealHBToFloatHTest.h @@ -50,21 +50,26 @@ class UnaryUfuncRealHBToFloatHTest : public OperatorTest { exec_aten::Tensor out = tf_out.zeros(out_shape, dynamism); - std::vector test_vector = { - 0, 1, 3, 5, 10, 100}; - std::vector expected_vector; - std::transform( - test_vector.begin(), - test_vector.end(), - std::back_inserter(expected_vector), - [this](auto x) { return this->op_reference(x); }); + using IN_CTYPE = typename decltype(tf_in)::ctype; + using OUT_CTYPE = typename decltype(tf_out)::ctype; + std::vector test_vector = {0, 1, 3, 5, 10, 100}; + std::vector expected_vector; + for (int ii = 0; ii < test_vector.size(); ++ii) { + auto ref_result = this->op_reference(test_vector[ii]); + // Drop test cases with high magnitude results due to precision + // issues. + if ((std::abs(ref_result) > 1e30 || std::abs(ref_result) < -1e30)) { + test_vector[ii] = 2; + ref_result = this->op_reference(2); + } + expected_vector.push_back(ref_result); + } // clang-format off op_out(tf_in.make({1, 6}, test_vector), out); - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, expected_vector)); + auto expected = tf_out.make({1, 6}, expected_vector); + EXPECT_TENSOR_CLOSE(out, expected); // clang-format on } diff --git a/kernels/test/op_acos_test.cpp b/kernels/test/op_acos_test.cpp index 19f3c3ea5a1..2c749072d8d 100644 --- a/kernels/test/op_acos_test.cpp +++ b/kernels/test/op_acos_test.cpp @@ -14,9 +14,8 @@ #include using exec_aten::Tensor; -using torch::executor::testing::UnaryUfuncRealHBToFloatHTest; - -class OpAcosOutTest : public UnaryUfuncRealHBToFloatHTest { +class OpAcosOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::acos_outf(context_, self, out); diff --git a/kernels/test/op_acosh_test.cpp b/kernels/test/op_acosh_test.cpp index ce01411fd3f..7e06cda5451 100644 --- a/kernels/test/op_acosh_test.cpp +++ b/kernels/test/op_acosh_test.cpp @@ -7,144 +7,27 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; +#include + using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; -class OpAcoshOutTest : public OperatorTest { +class OpAcoshOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_acosh_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::acosh_outf(context_, self, out); } - // Common testing for acosh operator and all kinds of supported input types - template - void test_floating_point_acosh_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the acosh operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_acosh_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { NAN, 0.000000, 1.762747, 2.292432, 2.993223, 5.298292 })); - // clang-format on + double op_reference(double x) const override { + return std::acosh(x); } - // Unhandled output dtypes. - template - void test_acosh_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_acosh_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpAcoshOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{NAN, 0.000000}); - - EXPECT_TENSOR_CLOSE(op_acosh_out(a, out), res); -} - -TEST_F(OpAcoshOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_acosh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAcoshOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_acosh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAcoshOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_acosh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAcoshOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_acosh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAcoshOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_acosh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAcoshOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_acosh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAcoshOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_acosh_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpAcoshOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_acosh_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpAcoshOutTest) diff --git a/kernels/test/op_asin_test.cpp b/kernels/test/op_asin_test.cpp index ae0af71d2de..1f839c5000a 100644 --- a/kernels/test/op_asin_test.cpp +++ b/kernels/test/op_asin_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpAsinOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpAsinOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_asin_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::asin_outf(context_, self, out); } - // Common testing for asin operator and all kinds of supported input types - template - void test_floating_point_asin_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the asin operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_asin_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 0.000000, 1.570796, NAN, NAN, NAN, NAN })); - // clang-format on + double op_reference(double x) const override { + return std::asin(x); } - // Unhandled output dtypes. - template - void test_asin_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_asin_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpAsinOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 1.5707960}); - - EXPECT_TENSOR_CLOSE(op_asin_out(a, out), res); -} - -TEST_F(OpAsinOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asin_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_asin_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpAsinOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_asin_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpAsinOutTest) diff --git a/kernels/test/op_asinh_test.cpp b/kernels/test/op_asinh_test.cpp index cd887404b75..81f564c116a 100644 --- a/kernels/test/op_asinh_test.cpp +++ b/kernels/test/op_asinh_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpAsinhOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpAsinhOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_asinh_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::asinh_outf(context_, self, out); } - // Common testing for asinh operator and all kinds of supported input types - template - void test_floating_point_asinh_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the asinh operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_asinh_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 0.000000, 0.881374, 1.818447, 2.312438, 2.998223, 5.298342 })); - // clang-format on + double op_reference(double x) const override { + return std::asinh(x); } - // Unhandled output dtypes. - template - void test_asinh_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_asinh_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpAsinhOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 0.881374}); - - EXPECT_TENSOR_CLOSE(op_asinh_out(a, out), res); -} - -TEST_F(OpAsinhOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_asinh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAsinhOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_asinh_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpAsinhOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_asinh_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpAsinhOutTest) diff --git a/kernels/test/op_atan_test.cpp b/kernels/test/op_atan_test.cpp index 6258819432f..d97f9fe74f0 100644 --- a/kernels/test/op_atan_test.cpp +++ b/kernels/test/op_atan_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpAtanOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpAtanOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_atan_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::atan_outf(context_, self, out); } - // Common testing for atan operator and all kinds of supported input types - template - void test_floating_point_atan_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the atan operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_atan_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 0.000000, 0.785398, 1.249046, 1.373401, 1.471128, 1.560797 })); - // clang-format on + double op_reference(double x) const override { + return std::atan(x); } - // Unhandled output dtypes. - template - void test_atan_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_atan_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpAtanOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 0.785398}); - - EXPECT_TENSOR_CLOSE(op_atan_out(a, out), res); -} - -TEST_F(OpAtanOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atan_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_atan_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpAtanOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_atan_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpAtanOutTest) diff --git a/kernels/test/op_atanh_test.cpp b/kernels/test/op_atanh_test.cpp index 88f02603c85..3e90818587a 100644 --- a/kernels/test/op_atanh_test.cpp +++ b/kernels/test/op_atanh_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpAtanhOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpAtanhOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_atanh_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::atanh_outf(context_, self, out); } - // Common testing for atanh operator and all kinds of supported input types - template - void test_floating_point_atanh_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the atanh operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_atanh_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 0.0, std::numeric_limits::infinity(), NAN, NAN, NAN, NAN })); - // clang-format on + double op_reference(double x) const override { + return std::atanh(x); } - // Unhandled output dtypes. - template - void test_atanh_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_atanh_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpAtanhOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, INFINITY}); - - EXPECT_TENSOR_CLOSE(op_atanh_out(a, out), res); -} - -TEST_F(OpAtanhOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_atanh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpAtanhOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_atanh_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpAtanhOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_atanh_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpAtanhOutTest) diff --git a/kernels/test/op_cos_test.cpp b/kernels/test/op_cos_test.cpp index f6105787a8e..07aab9838fd 100644 --- a/kernels/test/op_cos_test.cpp +++ b/kernels/test/op_cos_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpCosOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpCosOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_cos_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::cos_outf(context_, self, out); } - // Common testing for cos operator and all kinds of supported input types - template - void test_floating_point_cos_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the cos operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_cos_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 1.000000, 0.540302, -0.989992, 0.283662, -0.839072, 0.862319 })); - // clang-format on + double op_reference(double x) const override { + return std::cos(x); } - // Unhandled output dtypes. - template - void test_cos_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_cos_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpCosOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{1.000000, 0.540302}); - - EXPECT_TENSOR_CLOSE(op_cos_out(a, out), res); -} - -TEST_F(OpCosOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cos_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCosOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_cos_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpCosOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_cos_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpCosOutTest) diff --git a/kernels/test/op_cosh_test.cpp b/kernels/test/op_cosh_test.cpp index d9939a81938..0b9a0df7a01 100644 --- a/kernels/test/op_cosh_test.cpp +++ b/kernels/test/op_cosh_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpCoshOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpCoshOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_cosh_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::cosh_outf(context_, self, out); } - // Common testing for cosh operator and all kinds of supported input types - template - void test_floating_point_cosh_out( - const std::vector& out_shape = {1, 5}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the cosh operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_cosh_out(tf_in.make({1, 5}, { 0, 1, 3, 5, 10 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 5}, { 1.000000e+00, 1.543081e+00, 1.006766e+01, 7.420995e+01, 1.101323e+04 })); - // clang-format on + double op_reference(double x) const override { + return std::cosh(x); } - // Unhandled output dtypes. - template - void test_cosh_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_cosh_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpCoshOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{1.000000, 1.543081}); - - EXPECT_TENSOR_CLOSE(op_cosh_out(a, out), res); -} - -TEST_F(OpCoshOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_cosh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpCoshOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_cosh_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpCoshOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_cosh_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpCoshOutTest) diff --git a/kernels/test/op_erf_test.cpp b/kernels/test/op_erf_test.cpp index 73f8d6cd5a0..e3a2f98ed20 100644 --- a/kernels/test/op_erf_test.cpp +++ b/kernels/test/op_erf_test.cpp @@ -8,7 +8,7 @@ #include // Declares the operator #include -#include +#include #include #include #include @@ -20,14 +20,22 @@ using exec_aten::ScalarType; using exec_aten::Tensor; using torch::executor::testing::TensorFactory; -class OpErfTest : public OperatorTest { +class OpErfOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_erf_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::erf_outf(context_, self, out); } + + double op_reference(double x) const override { + return std::erf(x); + } + + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpErfTest, SanityCheck) { +TEST_F(OpErfOutTest, SanityCheck) { TensorFactory tf; Tensor in = tf.make({1, 7}, {-3.0, -2.99, -1.01, 0.0, 1.01, 2.99, 3.0}); @@ -36,36 +44,10 @@ TEST_F(OpErfTest, SanityCheck) { Tensor expected = tf.make({1, 7}, {-0.999978, -0.999976, -0.846811, 0.000000, 0.846811, 0.999976, 0.999978}); // clang-format on - Tensor ret = op_erf_out(in, out); + Tensor ret = op_out(in, out); EXPECT_TENSOR_EQ(out, ret); EXPECT_TENSOR_CLOSE(out, expected); } -TEST_F(OpErfTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 0.842701}); - - EXPECT_TENSOR_CLOSE(op_erf_out(a, out), res); -} - -TEST_F(OpErfTest, HalfSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } - TensorFactory tf_half; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_half.make(sizes, /*data=*/{0.0, 1.0}); - Tensor out = tf_half.zeros(sizes); - Tensor res = tf_half.make(sizes, /*data=*/{0.000000, 0.842701}); - - EXPECT_TENSOR_CLOSE(op_erf_out(a, out), res); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpErfOutTest) diff --git a/kernels/test/op_exp_test.cpp b/kernels/test/op_exp_test.cpp index 220aad1ee1d..ff4b5bb68a9 100644 --- a/kernels/test/op_exp_test.cpp +++ b/kernels/test/op_exp_test.cpp @@ -7,178 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::Scalar; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using torch::executor::testing::SupportedFeatures; -using torch::executor::testing::TensorFactory; +#include -class OpExpOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpExpOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_exp_out(const Tensor& a, Tensor& out) { - return torch::executor::aten::exp_outf(context_, a, out); + Tensor& op_out(const Tensor& self, Tensor& out) override { + return torch::executor::aten::exp_outf(context_, self, out); } - template - CTYPE apply_log(double x) { - return static_cast(std::log(x)); - } - - // Common testing for log operator - template - void test__exp_out() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 2}; - - // clang-format off - Tensor x = tf.make( - sizes, - { - apply_log(1.), apply_log(2.), - apply_log(4.), apply_log(8.), - }); - // clang-format on - - // clang-format off - Tensor expected = tf_out.make( - sizes, - { - 1., 2., - 4., 8., - }); - // clang-format on - - Tensor out = tf_out.zeros(sizes); - - op_exp_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected); + double op_reference(double x) const override { + return std::exp(x); } - // Unhandled output dtypes. - template - void test_exp_invalid_output_dtype_dies() { - TensorFactory tf_float; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf_float.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_exp_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpExpOutTest, AllFloatInputFloatOutputSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test__exp_out(); - ET_FORALL_FLOAT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpExpOutTest, AllFloatInputDoubleOutputSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test__exp_out(); - ET_FORALL_FLOAT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpExpOutTest, HandleBoolInput) { - // op_exp_out() handles Bool as input. - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{true, false}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{2.718282, 1}); - - EXPECT_TENSOR_CLOSE(op_exp_out(a, out), res); -} - -TEST_F(OpExpOutTest, HandleHalfInput) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } - TensorFactory tf_half; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_half.make(sizes, /*data=*/{-2.5, -3.0}); - Tensor out = tf_half.zeros(sizes); - Tensor res = tf_half.make(sizes, /*data=*/{0.082085, 0.049787}); - - EXPECT_TENSOR_CLOSE(op_exp_out(a, out), res); -} - -// Mismatched shape tests. -TEST_F(OpExpOutTest, MismatchedShapesDies) { - if (SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched shapes"; - } - - TensorFactory tf_int; - TensorFactory tf_float; - - Tensor a = tf_int.ones(/*sizes=*/{4}); - Tensor out = tf_float.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_exp_out(a, out)); -} - -TEST_F(OpExpOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_exp_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -#ifndef USE_ATEN_LIB -TEST_F(OpExpOutTest, DynamicOutputShape) { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {4, 2}; - const std::vector out_size = {8, 1}; - - // clang-format off - Tensor x = tf.make( - sizes, - { - apply_log(1.), apply_log(2.), - apply_log(4.), apply_log(8.), - apply_log(3.), apply_log(6.), - apply_log(7.), apply_log(5.), - }); - // clang-format on - - // clang-format off - Tensor expected = tf_out.make( - sizes, - { - 1., 2., - 4., 8., - 3., 6., - 7., 5., - }); - // clang-format on - - Tensor out = - tf.zeros(out_size, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND); - - op_exp_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected); -} -#endif +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpExpOutTest) diff --git a/kernels/test/op_expm1_test.cpp b/kernels/test/op_expm1_test.cpp index c0d3a226309..b40204279ae 100644 --- a/kernels/test/op_expm1_test.cpp +++ b/kernels/test/op_expm1_test.cpp @@ -7,32 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::Scalar; -using exec_aten::ScalarType; +#include + using exec_aten::Tensor; -using torch::executor::testing::SupportedFeatures; -using torch::executor::testing::TensorFactory; +class OpExpm1OutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { + protected: + Tensor& op_out(const Tensor& self, Tensor& out) override { + return torch::executor::aten::expm1_outf(context_, self, out); + } -Tensor& op_expm1_out(const Tensor& a, Tensor& out) { - executorch::runtime::KernelRuntimeContext context{}; - return torch::executor::aten::expm1_outf(context, a, out); -} + double op_reference(double x) const override { + return std::expm1(x); + } -TEST(OpExpm1OutTest, SmokeTest) { - TensorFactory tfDouble; + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - Tensor self = tfDouble.full({}, -31.375); - Tensor out = tfDouble.zeros({}); - Tensor out_expected = tfDouble.full({}, -0.9999999999999764); - op_expm1_out(self, out); - EXPECT_TENSOR_CLOSE(out, out_expected); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpExpm1OutTest) diff --git a/kernels/test/op_log10_test.cpp b/kernels/test/op_log10_test.cpp index d4e14100497..fd45669c4b3 100644 --- a/kernels/test/op_log10_test.cpp +++ b/kernels/test/op_log10_test.cpp @@ -7,35 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::Scalar; -using exec_aten::ScalarType; +#include + using exec_aten::Tensor; -using torch::executor::testing::SupportedFeatures; -using torch::executor::testing::TensorFactory; +class OpLog10OutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { + protected: + Tensor& op_out(const Tensor& self, Tensor& out) override { + return torch::executor::aten::log10_outf(context_, self, out); + } -Tensor& op_log10_out(const Tensor& a, Tensor& out) { - executorch::runtime::KernelRuntimeContext context{}; - return torch::executor::aten::log10_outf(context, a, out); -} + double op_reference(double x) const override { + return std::log10(x); + } -TEST(OpLog10OutTest, SmokeTest) { - TensorFactory tfDouble; - TensorFactory tfShort; + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - Tensor self = tfShort.make({8}, {-12, -6, -65, -61, 16, -44, -47, 54}); - Tensor out = tfDouble.zeros({8}); - Tensor out_expected = tfDouble.make( - {8}, - {NAN, NAN, NAN, NAN, 1.2041200399398804, NAN, NAN, 1.732393741607666}); - op_log10_out(self, out); - EXPECT_TENSOR_CLOSE(out, out_expected); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpLog10OutTest) diff --git a/kernels/test/op_log1p_test.cpp b/kernels/test/op_log1p_test.cpp index 3d4b0f1c567..b4877b54fc8 100644 --- a/kernels/test/op_log1p_test.cpp +++ b/kernels/test/op_log1p_test.cpp @@ -7,33 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::Scalar; -using exec_aten::ScalarType; +#include + using exec_aten::Tensor; -using torch::executor::testing::SupportedFeatures; -using torch::executor::testing::TensorFactory; +class OpLog1pOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { + protected: + Tensor& op_out(const Tensor& self, Tensor& out) override { + return torch::executor::aten::log1p_outf(context_, self, out); + } -Tensor& op_log1p_out(const Tensor& a, Tensor& out) { - executorch::runtime::KernelRuntimeContext context{}; - return torch::executor::aten::log1p_outf(context, a, out); -} + double op_reference(double x) const override { + return std::log1p(x); + } -TEST(OpLog1pOutTest, SmokeTest) { - TensorFactory tfChar; - TensorFactory tfDouble; + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - Tensor self = tfChar.full({}, 13); - Tensor out = tfDouble.zeros({}); - Tensor out_expected = tfDouble.full({}, 2.6390573978424072); - op_log1p_out(self, out); - EXPECT_TENSOR_CLOSE(out, out_expected); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpLog1pOutTest) diff --git a/kernels/test/op_log2_test.cpp b/kernels/test/op_log2_test.cpp index cbbd8f6a985..b1829df8566 100644 --- a/kernels/test/op_log2_test.cpp +++ b/kernels/test/op_log2_test.cpp @@ -7,34 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::Scalar; -using exec_aten::ScalarType; +#include + using exec_aten::Tensor; -using torch::executor::testing::SupportedFeatures; -using torch::executor::testing::TensorFactory; +class OpLog2OutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { + protected: + Tensor& op_out(const Tensor& self, Tensor& out) override { + return torch::executor::aten::log2_outf(context_, self, out); + } -Tensor& op_log2_out(const Tensor& a, Tensor& out) { - executorch::runtime::KernelRuntimeContext context{}; - return torch::executor::aten::log2_outf(context, a, out); -} + double op_reference(double x) const override { + return std::log2(x); + } -TEST(OpLog2OutTest, SmokeTest) { - TensorFactory tfByte; - TensorFactory tfFloat; + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - Tensor self = tfByte.make({3}, {45, 55, 82}); - Tensor out = tfFloat.zeros({3}); - Tensor out_expected = tfFloat.make( - {3}, {5.4918532371521, 5.781359672546387, 6.3575520515441895}); - op_log2_out(self, out); - EXPECT_TENSOR_CLOSE(out, out_expected); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpLog2OutTest) diff --git a/kernels/test/op_log_test.cpp b/kernels/test/op_log_test.cpp index 887defe621d..aa57b991238 100644 --- a/kernels/test/op_log_test.cpp +++ b/kernels/test/op_log_test.cpp @@ -7,117 +7,32 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::Scalar; +#include + using exec_aten::ScalarType; using exec_aten::Tensor; using torch::executor::testing::SupportedFeatures; using torch::executor::testing::TensorFactory; - -class OpLogOutTest : public OperatorTest { +class OpLogOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_log_out(const Tensor& a, Tensor& out) { - return torch::executor::aten::log_outf(context_, a, out); + Tensor& op_out(const Tensor& self, Tensor& out) override { + return torch::executor::aten::log_outf(context_, self, out); } - // Common testing for log operator - template - void test__log_out() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 2}; - - Tensor out = tf_out.zeros(sizes); - - // Valid input should give the expected output - op_log_out(tf.make(sizes, /*data=*/{0, 1, 2, 4}), out); - EXPECT_TENSOR_CLOSE( - out, tf_out.make(sizes, /*data=*/{-INFINITY, 0, 0.693147, 1.386294})); + double op_reference(double x) const override { + return std::log(x); } - // Unhandled output dtypes. - template - void test_log_invalid_output_dtype_dies() { - TensorFactory tf_float; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf_float.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_log_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpLogOutTest, AllRealInputHalfOutputSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test__log_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpLogOutTest, AllRealInputFloatOutputSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test__log_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpLogOutTest, AllRealInputDoubleOutputSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test__log_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpLogOutTest, HandleBoolInput) { - // op_log_out() handles Bool as input. - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{true, false}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0, -INFINITY}); - - EXPECT_TENSOR_EQ(op_log_out(a, out), res); -} - -// Mismatched shape tests. -TEST_F(OpLogOutTest, MismatchedShapesDies) { - if (SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched shapes"; - } - - TensorFactory tf_int; - TensorFactory tf_float; - - Tensor a = tf_int.ones(/*sizes=*/{4}); - Tensor out = tf_float.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_log_out(a, out)); -} - -TEST_F(OpLogOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_log_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpLogOutTest) TEST_F(OpLogOutTest, SimpleGeneratedCase) { TensorFactory tf; @@ -144,7 +59,7 @@ TEST_F(OpLogOutTest, SimpleGeneratedCase) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); Tensor out = tf.zeros({10, 10}); - Tensor ret = op_log_out(x, out); + Tensor ret = op_out(x, out); EXPECT_TENSOR_CLOSE(out, expected_result); } @@ -170,59 +85,6 @@ TEST_F(OpLogOutTest, DynamicShapeUpperBoundSameAsExpected) { Tensor out = tf.zeros({3, 2}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND); - Tensor ret = op_log_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected_result); -} - -TEST_F(OpLogOutTest, DynamicShapeUpperBoundLargerThanExpected) { - TensorFactory tf; - - Tensor x = tf.make( - {3, 2}, - {0.6879220604896545, - 0.8289883136749268, - 0.7889447808265686, - 0.6339777112007141, - 0.8719115853309631, - 0.4185197353363037}); - Tensor expected_result = tf.make( - {3, 2}, - {-0.37407973408699036, - -0.18754921853542328, - -0.23705895245075226, - -0.4557414948940277, - -0.1370672583580017, - -0.8710312247276306}); - - Tensor out = - tf.zeros({10, 10}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND); - Tensor ret = op_log_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected_result); -} - -TEST_F(OpLogOutTest, DynamicShapeUnbound) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - TensorFactory tf; - - Tensor x = tf.make( - {3, 2}, - {0.6879220604896545, - 0.8289883136749268, - 0.7889447808265686, - 0.6339777112007141, - 0.8719115853309631, - 0.4185197353363037}); - Tensor expected_result = tf.make( - {3, 2}, - {-0.37407973408699036, - -0.18754921853542328, - -0.23705895245075226, - -0.4557414948940277, - -0.1370672583580017, - -0.8710312247276306}); - - Tensor out = - tf.zeros({1, 1}, torch::executor::TensorShapeDynamism::DYNAMIC_UNBOUND); - Tensor ret = op_log_out(x, out); + Tensor ret = op_out(x, out); EXPECT_TENSOR_CLOSE(out, expected_result); } diff --git a/kernels/test/op_reciprocal_test.cpp b/kernels/test/op_reciprocal_test.cpp index b3da01c7905..870ce4097d0 100644 --- a/kernels/test/op_reciprocal_test.cpp +++ b/kernels/test/op_reciprocal_test.cpp @@ -7,65 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using torch::executor::testing::TensorFactory; +#include -class OpReciprocalTest : public OperatorTest { +using exec_aten::Tensor; +class OpReciprocalOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_reciprocal_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::reciprocal_outf(context_, self, out); } -}; - -TEST_F(OpReciprocalTest, SanityCheck) { - TensorFactory tf; - - Tensor in = tf.make({1, 7}, {-3.0, -2.99, -1.01, 0.0, 1.01, 2.99, 3.0}); - Tensor out = tf.zeros({1, 7}); - // clang-format off - Tensor expected = tf.make({1, 7}, {-0.333333, -0.334448, -0.990099, std::numeric_limits::infinity(), 0.990099, 0.334448, 0.333333}); - // clang-format on - - Tensor ret = op_reciprocal_out(in, out); - - EXPECT_TENSOR_EQ(out, ret); - EXPECT_TENSOR_CLOSE(out, expected); -} -TEST_F(OpReciprocalTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{INFINITY, 1.0}); - - EXPECT_TENSOR_CLOSE(op_reciprocal_out(a, out), res); -} - -TEST_F(OpReciprocalTest, HandleHalfInput) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; + double op_reference(double x) const override { + return 1.0 / x; } - TensorFactory tf_half; - - const std::vector sizes = {1, 2}; - Tensor a = tf_half.make(sizes, /*data=*/{5.0, -2.0}); - Tensor out = tf_half.zeros(sizes); - Tensor res = tf_half.make(sizes, /*data=*/{0.2, -0.5}); + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - EXPECT_TENSOR_CLOSE(op_reciprocal_out(a, out), res); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpReciprocalOutTest) diff --git a/kernels/test/op_rsqrt_test.cpp b/kernels/test/op_rsqrt_test.cpp index 3332e3be8e1..1549e038395 100644 --- a/kernels/test/op_rsqrt_test.cpp +++ b/kernels/test/op_rsqrt_test.cpp @@ -7,65 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using torch::executor::testing::TensorFactory; +#include -class OpRsqrtTest : public OperatorTest { +using exec_aten::Tensor; +class OpRsqrtOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_rsqrt_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::rsqrt_outf(context_, self, out); } -}; - -TEST_F(OpRsqrtTest, SanityCheck) { - TensorFactory tf; - - Tensor in = tf.make({1, 7}, {-3.0, -2.99, -1.01, 0.0, 1.01, 2.99, 3.0}); - Tensor out = tf.zeros({1, 7}); - // clang-format off - Tensor expected = tf.make({1, 7}, {NAN, NAN, NAN, std::numeric_limits::infinity(), 0.995037, 0.578315, 0.577350}); - // clang-format on - - Tensor ret = op_rsqrt_out(in, out); - - EXPECT_TENSOR_EQ(out, ret); - EXPECT_TENSOR_CLOSE(out, expected); -} -TEST_F(OpRsqrtTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{INFINITY, 1.0}); - - EXPECT_TENSOR_CLOSE(op_rsqrt_out(a, out), res); -} - -TEST_F(OpRsqrtTest, HandleHalfInput) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; + double op_reference(double x) const override { + return 1.0 / std::sqrt(x); } - TensorFactory tf_half; - - const std::vector sizes = {1, 2}; - Tensor a = tf_half.make(sizes, /*data=*/{3.5, 2.6}); - Tensor out = tf_half.zeros(sizes); - Tensor res = tf_half.make(sizes, /*data=*/{0.53452248, 0.62017367}); + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - EXPECT_TENSOR_CLOSE(op_rsqrt_out(a, out), res); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpRsqrtOutTest) diff --git a/kernels/test/op_sin_test.cpp b/kernels/test/op_sin_test.cpp index 74991f6cc37..6bda62035ec 100644 --- a/kernels/test/op_sin_test.cpp +++ b/kernels/test/op_sin_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpSinOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpSinOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_sin_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::sin_outf(context_, self, out); } - // Common testing for sin operator and all kinds of supported input types - template - void test_floating_point_sin_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the sin operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_sin_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 0.000000, 0.841471, 0.141120, -0.958924, -0.544021, -0.506366 })); - // clang-format on + double op_reference(double x) const override { + return std::sin(x); } - // Unhandled output dtypes. - template - void test_sin_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_sin_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpSinOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 0.841471}); - - EXPECT_TENSOR_CLOSE(op_sin_out(a, out), res); -} - -TEST_F(OpSinOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sin_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_sin_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpSinOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_sin_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpSinOutTest) diff --git a/kernels/test/op_sinh_test.cpp b/kernels/test/op_sinh_test.cpp index 8f533ad3251..865d71c83a2 100644 --- a/kernels/test/op_sinh_test.cpp +++ b/kernels/test/op_sinh_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpSinhOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpSinhOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_sinh_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::sinh_outf(context_, self, out); } - // Common testing for sinh operator and all kinds of supported input types - template - void test_floating_point_sinh_out( - const std::vector& out_shape = {1, 5}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the sinh operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_sinh_out(tf_in.make({1, 5}, { 0, 1, 3, 5, 10 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 5}, { 0.000000e+00, 1.175201e+00, 1.001787e+01, 7.420321e+01, 1.101323e+04 })); - // clang-format on + double op_reference(double x) const override { + return std::sinh(x); } - // Unhandled output dtypes. - template - void test_sinh_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_sinh_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpSinhOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 1.175201}); - - EXPECT_TENSOR_CLOSE(op_sinh_out(a, out), res); -} - -TEST_F(OpSinhOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_sinh_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpSinhOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_sinh_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpSinhOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_sinh_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpSinhOutTest) diff --git a/kernels/test/op_sqrt_test.cpp b/kernels/test/op_sqrt_test.cpp index f14f345a8cf..84e3db25cf3 100644 --- a/kernels/test/op_sqrt_test.cpp +++ b/kernels/test/op_sqrt_test.cpp @@ -7,65 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using torch::executor::testing::TensorFactory; +#include -class OpSqrtTest : public OperatorTest { +using exec_aten::Tensor; +class OpSqrtOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_sqrt_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::sqrt_outf(context_, self, out); } -}; - -TEST_F(OpSqrtTest, SanityCheck) { - TensorFactory tf; - - Tensor in = tf.make({1, 7}, {-9., -2., -1., 0., 1., 2., 9.}); - Tensor out = tf.zeros({1, 7}); - // clang-format off - Tensor expected = tf.make({1, 7}, {NAN, NAN, NAN, 0., 1., 1.414214, 3.}); - // clang-format on - - Tensor ret = op_sqrt_out(in, out); - - EXPECT_TENSOR_EQ(out, ret); - EXPECT_TENSOR_CLOSE(out, expected); -} -TEST_F(OpSqrtTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.0, 1.0}); - - EXPECT_TENSOR_CLOSE(op_sqrt_out(a, out), res); -} - -TEST_F(OpSqrtTest, HandleHalfInput) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; + double op_reference(double x) const override { + return std::sqrt(x); } - TensorFactory tf_half; - - const std::vector sizes = {1, 2}; - Tensor a = tf_half.make(sizes, /*data=*/{4.0, 6.25}); - Tensor out = tf_half.zeros(sizes); - Tensor res = tf_half.make(sizes, /*data=*/{2.0, 2.5}); + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; +}; - EXPECT_TENSOR_CLOSE(op_sqrt_out(a, out), res); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpSqrtOutTest) diff --git a/kernels/test/op_tan_test.cpp b/kernels/test/op_tan_test.cpp index 560da69d8bb..dfa14a6bc70 100644 --- a/kernels/test/op_tan_test.cpp +++ b/kernels/test/op_tan_test.cpp @@ -7,164 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using exec_aten::TensorShapeDynamism; -using torch::executor::testing::TensorFactory; +#include -class OpTanOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpTanOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_tan_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::tan_outf(context_, self, out); } - // Common testing for tan operator and all kinds of supported input types - template - void test_floating_point_tan_out( - const std::vector& out_shape = {1, 6}, - TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) { - TensorFactory tf_in; - TensorFactory tf_out; - - // Destination for the tan operator. - Tensor out = tf_out.zeros(out_shape, dynamism); - - // clang-format off - op_tan_out(tf_in.make({1, 6}, { 0, 1, 3, 5, 10, 100 }), out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make({1, 6}, { 0.000000, 1.557408, -0.142547, -3.380515, 0.648361, -0.587214 })); - // clang-format on + double op_reference(double x) const override { + return std::tan(x); } - // Unhandled output dtypes. - template - void test_tan_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_tan_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpTanOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 1.557408}); - - EXPECT_TENSOR_CLOSE(op_tan_out(a, out), res); -} - -TEST_F(OpTanOutTest, AllRealInputHalfOutputStaticDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputFloatOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputDoubleOutputStaticDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputHalfOutputBoundDynamismSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputFloatOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputDoubleOutputBoundDynamismSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out( \ - {10, 10}, TensorShapeDynamism::DYNAMIC_BOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputFloatOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllRealInputDoubleOutputUnboundDynamismSupport) { - if (!torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tan_out( \ - {1, 1}, TensorShapeDynamism::DYNAMIC_UNBOUND); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_tan_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpTanOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_tan_out(a, out)); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpTanOutTest) diff --git a/kernels/test/op_tanh_test.cpp b/kernels/test/op_tanh_test.cpp index 7ded964e8b3..b02eeb8b84d 100644 --- a/kernels/test/op_tanh_test.cpp +++ b/kernels/test/op_tanh_test.cpp @@ -7,254 +7,26 @@ */ #include // Declares the operator -#include -#include -#include -#include -#include +#include #include -using namespace ::testing; -using exec_aten::ScalarType; -using exec_aten::Tensor; -using torch::executor::testing::TensorFactory; +#include -class OpTanhOutTest : public OperatorTest { +using exec_aten::Tensor; +class OpTanhOutTest + : public torch::executor::testing::UnaryUfuncRealHBToFloatHTest { protected: - Tensor& op_tanh_out(const Tensor& self, Tensor& out) { + Tensor& op_out(const Tensor& self, Tensor& out) override { return torch::executor::aten::tanh_outf(context_, self, out); } - // Common testing for tanh operator and all kinds of supported input types - template - void test_floating_point_tanh_out() { - TensorFactory tf_in; - TensorFactory tf_out; - - const std::vector sizes = {1, 12}; - - // Destination for the tanh operator. - Tensor out = tf_out.zeros(sizes); - - // clang-format off - op_tanh_out( - tf_in.make(sizes, /*data=*/{ 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 100}), - out); - - // Check that it matches (or close to) the expected output. - EXPECT_TENSOR_CLOSE( - out, - tf_out.make( - sizes, /*data=*/{ 0.0000000000, 0.7615941763, - 0.9640275836, 0.9950547814, 0.9993293285, - 0.9999092221, 0.9999877214, 0.9999983311, - 0.9999997616, 0.9999999404, 1.0000000000, 1.0000000000})); - // clang-format on + double op_reference(double x) const override { + return std::tanh(x); } - // Unhandled output dtypes. - template - void test_tanh_invalid_output_dtype_dies() { - TensorFactory tf; - TensorFactory tf_out; - - const std::vector sizes = {2, 5}; - - Tensor in = tf.ones(sizes); - Tensor out = tf_out.zeros(sizes); - - ET_EXPECT_KERNEL_FAILURE(context_, op_tanh_out(in, out)); - } + torch::executor::testing::SupportedFeatures* get_supported_features() + const override; }; -TEST_F(OpTanhOutTest, HandleBoolInput) { - TensorFactory tf_bool; - TensorFactory tf_float; - - const std::vector sizes = {1, 2}; - - Tensor a = tf_bool.make(sizes, /*data=*/{false, true}); - Tensor out = tf_float.zeros(sizes); - Tensor res = tf_float.make(sizes, /*data=*/{0.000000, 0.761594}); - - EXPECT_TENSOR_CLOSE(op_tanh_out(a, out), res); -} - -TEST_F(OpTanhOutTest, AllRealInputHalfOutputSupport) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "Test Half support only for ExecuTorch mode"; - } -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tanh_out(); - ET_FORALL_REALH_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanhOutTest, AllRealInputFloatOutputSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tanh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanhOutTest, AllRealInputDoubleOutputSupport) { -#define TEST_ENTRY(ctype, dtype) \ - test_floating_point_tanh_out(); - ET_FORALL_REAL_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -TEST_F(OpTanhOutTest, AllNonFloatOutputDTypeDies) { -#define TEST_ENTRY(ctype, dtype) \ - test_tanh_invalid_output_dtype_dies(); - ET_FORALL_INT_TYPES(TEST_ENTRY); -#undef TEST_ENTRY -} - -// Mismatched shape tests. -TEST_F(OpTanhOutTest, MismatchedInputShapesDies) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel can handle mismatched input shapes"; - } - TensorFactory tf; - - Tensor a = tf.ones(/*sizes=*/{4}); - Tensor out = tf.ones(/*sizes=*/{2, 2}); - - ET_EXPECT_KERNEL_FAILURE(context_, op_tanh_out(a, out)); -} - -TEST_F(OpTanhOutTest, SimpleGeneratedCase) { - TensorFactory tf; - - Tensor x = tf.make( - {10, 10}, - {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}); - Tensor expected_result = tf.make( - {10, 10}, {0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194, 0.7615941762924194, 0.7615941762924194, - 0.7615941762924194}); - - Tensor out = tf.zeros({10, 10}); - Tensor ret = op_tanh_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected_result); -} - -TEST_F(OpTanhOutTest, DynamicShapeUpperBoundSameAsExpected) { - TensorFactory tf; - - Tensor x = tf.make( - {3, 2}, - {0.23026639223098755, - 0.24356824159622192, - 0.9074369668960571, - 0.167863667011261, - 0.8099868297576904, - 0.6270960569381714}); - Tensor expected_result = tf.make( - {3, 2}, - {0.22628112137317657, - 0.2388632595539093, - 0.7198998332023621, - 0.1663045436143875, - 0.6695830225944519, - 0.5560494065284729}); - - Tensor out = - tf.zeros({3, 2}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND); - Tensor ret = op_tanh_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected_result); -} - -TEST_F(OpTanhOutTest, DynamicShapeUpperBoundLargerThanExpected) { - TensorFactory tf; - - Tensor x = tf.make( - {3, 2}, - {0.23026639223098755, - 0.24356824159622192, - 0.9074369668960571, - 0.167863667011261, - 0.8099868297576904, - 0.6270960569381714}); - Tensor expected_result = tf.make( - {3, 2}, - {0.22628112137317657, - 0.2388632595539093, - 0.7198998332023621, - 0.1663045436143875, - 0.6695830225944519, - 0.5560494065284729}); - - Tensor out = - tf.zeros({10, 10}, torch::executor::TensorShapeDynamism::DYNAMIC_BOUND); - Tensor ret = op_tanh_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected_result); -} - -TEST_F(OpTanhOutTest, DynamicShapeUnbound) { - GTEST_SKIP() << "Dynamic shape unbound not supported"; - TensorFactory tf; - - Tensor x = tf.make( - {3, 2}, - {0.23026639223098755, - 0.24356824159622192, - 0.9074369668960571, - 0.167863667011261, - 0.8099868297576904, - 0.6270960569381714}); - Tensor expected_result = tf.make( - {3, 2}, - {0.22628112137317657, - 0.2388632595539093, - 0.7198998332023621, - 0.1663045436143875, - 0.6695830225944519, - 0.5560494065284729}); - - Tensor out = - tf.zeros({1, 1}, torch::executor::TensorShapeDynamism::DYNAMIC_UNBOUND); - Tensor ret = op_tanh_out(x, out); - EXPECT_TENSOR_CLOSE(out, expected_result); -} +IMPLEMENT_UNARY_UFUNC_REALHB_TO_FLOATH_TEST(OpTanhOutTest)