Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kernels/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down
27 changes: 16 additions & 11 deletions kernels/test/UnaryUfuncRealHBToFloatHTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,26 @@ class UnaryUfuncRealHBToFloatHTest : public OperatorTest {

exec_aten::Tensor out = tf_out.zeros(out_shape, dynamism);

std::vector<typename decltype(tf_in)::ctype> test_vector = {
0, 1, 3, 5, 10, 100};
std::vector<typename decltype(tf_out)::ctype> 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<IN_CTYPE> test_vector = {0, 1, 3, 5, 10, 100};
std::vector<OUT_CTYPE> 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
}

Expand Down
5 changes: 2 additions & 3 deletions kernels/test/op_acos_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
#include <cmath>

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);
Expand Down
139 changes: 11 additions & 128 deletions kernels/test/op_acosh_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,144 +7,27 @@
*/

#include <executorch/kernels/test/FunctionHeaderWrapper.h> // Declares the operator
#include <executorch/kernels/test/TestUtil.h>
#include <executorch/kernels/test/supported_features.h>
#include <executorch/runtime/core/exec_aten/exec_aten.h>
#include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
#include <executorch/runtime/core/exec_aten/testing_util/tensor_util.h>
#include <executorch/kernels/test/UnaryUfuncRealHBToFloatHTest.h>

#include <gtest/gtest.h>

using namespace ::testing;
using exec_aten::ScalarType;
#include <cmath>

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 <ScalarType IN_DTYPE, ScalarType OUT_DTYPE>
void test_floating_point_acosh_out(
const std::vector<int32_t>& out_shape = {1, 6},
TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) {
TensorFactory<IN_DTYPE> tf_in;
TensorFactory<OUT_DTYPE> 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 <ScalarType INPUT_DTYPE, ScalarType OUTPUT_DTYPE>
void test_acosh_invalid_output_dtype_dies() {
TensorFactory<INPUT_DTYPE> tf;
TensorFactory<OUTPUT_DTYPE> tf_out;

const std::vector<int32_t> 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<ScalarType::Bool> tf_bool;
TensorFactory<ScalarType::Float> tf_float;

const std::vector<int32_t> 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<ScalarType::dtype, ScalarType::Float>();
ET_FORALL_REAL_TYPES(TEST_ENTRY);
#undef TEST_ENTRY
}

TEST_F(OpAcoshOutTest, AllRealInputDoubleOutputStaticDynamismSupport) {
#define TEST_ENTRY(ctype, dtype) \
test_floating_point_acosh_out<ScalarType::dtype, ScalarType::Double>();
ET_FORALL_REAL_TYPES(TEST_ENTRY);
#undef TEST_ENTRY
}

TEST_F(OpAcoshOutTest, AllRealInputFloatOutputBoundDynamismSupport) {
#define TEST_ENTRY(ctype, dtype) \
test_floating_point_acosh_out<ScalarType::dtype, ScalarType::Float>( \
{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<ScalarType::dtype, ScalarType::Double>( \
{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<ScalarType::dtype, ScalarType::Float>( \
{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<ScalarType::dtype, ScalarType::Double>( \
{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<ScalarType::Float, ScalarType::dtype>();
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<ScalarType::Float> 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)
160 changes: 11 additions & 149 deletions kernels/test/op_asin_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,164 +7,26 @@
*/

#include <executorch/kernels/test/FunctionHeaderWrapper.h> // Declares the operator
#include <executorch/kernels/test/TestUtil.h>
#include <executorch/kernels/test/supported_features.h>
#include <executorch/runtime/core/exec_aten/exec_aten.h>
#include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
#include <executorch/runtime/core/exec_aten/testing_util/tensor_util.h>
#include <executorch/kernels/test/UnaryUfuncRealHBToFloatHTest.h>

#include <gtest/gtest.h>

using namespace ::testing;
using exec_aten::ScalarType;
using exec_aten::Tensor;
using exec_aten::TensorShapeDynamism;
using torch::executor::testing::TensorFactory;
#include <cmath>

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 <ScalarType IN_DTYPE, ScalarType OUT_DTYPE>
void test_floating_point_asin_out(
const std::vector<int32_t>& out_shape = {1, 6},
TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) {
TensorFactory<IN_DTYPE> tf_in;
TensorFactory<OUT_DTYPE> 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 <ScalarType INPUT_DTYPE, ScalarType OUTPUT_DTYPE>
void test_asin_invalid_output_dtype_dies() {
TensorFactory<INPUT_DTYPE> tf;
TensorFactory<OUTPUT_DTYPE> tf_out;

const std::vector<int32_t> 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<ScalarType::Bool> tf_bool;
TensorFactory<ScalarType::Float> tf_float;

const std::vector<int32_t> 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<ScalarType::dtype, ScalarType::Float>();
ET_FORALL_REALH_TYPES(TEST_ENTRY);
#undef TEST_ENTRY
}

TEST_F(OpAsinOutTest, AllRealInputFloatOutputStaticDynamismSupport) {
#define TEST_ENTRY(ctype, dtype) \
test_floating_point_asin_out<ScalarType::dtype, ScalarType::Float>();
ET_FORALL_REAL_TYPES(TEST_ENTRY);
#undef TEST_ENTRY
}

TEST_F(OpAsinOutTest, AllRealInputDoubleOutputStaticDynamismSupport) {
#define TEST_ENTRY(ctype, dtype) \
test_floating_point_asin_out<ScalarType::dtype, ScalarType::Double>();
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<ScalarType::dtype, ScalarType::Float>( \
{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<ScalarType::dtype, ScalarType::Float>( \
{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<ScalarType::dtype, ScalarType::Double>( \
{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<ScalarType::dtype, ScalarType::Float>( \
{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<ScalarType::dtype, ScalarType::Double>( \
{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<ScalarType::Float, ScalarType::dtype>();
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<ScalarType::Float> 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)
Loading
Loading