| #ifndef CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_ |
| #define CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_ |
| |
| #include "caffe2/operators/elementwise_ops.h" |
| |
| #include <iostream> |
| #include <string> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| |
| template <typename Context, typename T> |
| void CopyVector(const int N, const T* x, T* y); |
| |
| template <typename Context, typename I_Type, typename O_Type> |
| void FillTensor( |
| caffe2::Workspace* ws, |
| const std::string& name, |
| const std::vector<int64_t>& shape, |
| const std::vector<I_Type>& values) { |
| auto* blob = ws->CreateBlob(name); |
| auto* tensor = BlobGetMutableTensor(blob, Context::GetDeviceType()); |
| tensor->Resize(shape); |
| auto* mutable_data = tensor->template mutable_data<O_Type>(); |
| const O_Type* data = reinterpret_cast<const O_Type*>(values.data()); |
| CopyVector<Context, O_Type>(values.size(), data, mutable_data); |
| } |
| |
| template <typename Context> |
| caffe2::OperatorDef CreateOperatorDef() { |
| caffe2::OperatorDef def; |
| return def; |
| } |
| |
| template <typename Context> |
| caffe2::OperatorDef DefineOperator(const std::string& op_type) { |
| caffe2::OperatorDef def = CreateOperatorDef<Context>(); |
| def.set_name("test"); |
| def.set_type(op_type); |
| def.add_input("X"); |
| def.add_input("Y"); |
| def.add_output("Z"); |
| return def; |
| } |
| |
| template <typename Context> |
| void elementwiseAnd() { |
| const int N = 4; |
| const int M = 2; |
| caffe2::Workspace ws; |
| auto def = DefineOperator<Context>("And"); |
| { // equal size |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {N}, {true, false, true, false}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, true, false, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), N); |
| std::vector<bool> result{true, false, false, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| { // broadcast |
| auto* arg = def.add_arg(); |
| arg->set_name("broadcast"); |
| arg->set_i(1); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {M, N}, {true, false, true, false, true, false, true, false}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, true, false, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), M * N); |
| std::vector<bool> result{ |
| true, false, false, false, true, false, false, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| } |
| |
| template <typename Context> |
| void elementwiseOr() { |
| const int N = 4; |
| const int M = 2; |
| caffe2::Workspace ws; |
| auto def = DefineOperator<Context>("Or"); |
| { // equal size |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {N}, {true, false, true, false}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, true, false, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), N); |
| std::vector<bool> result{true, true, true, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| { // broadcast |
| auto* arg = def.add_arg(); |
| arg->set_name("broadcast"); |
| arg->set_i(1); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {M, N}, {true, false, true, false, true, false, true, false}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, true, false, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), M * N); |
| std::vector<bool> result{true, true, true, false, true, true, true, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| } |
| |
| template <typename Context> |
| void elementwiseXor() { |
| const int N = 4; |
| const int M = 2; |
| caffe2::Workspace ws; |
| auto def = DefineOperator<Context>("Xor"); |
| { // equal size |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {N}, {true, false, true, false}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, true, false, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), N); |
| std::vector<bool> result{false, true, true, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| { // broadcast |
| auto* arg = def.add_arg(); |
| arg->set_name("broadcast"); |
| arg->set_i(1); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {M, N}, {true, false, true, false, true, false, true, false}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, true, false, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), M * N); |
| std::vector<bool> result{ |
| false, true, true, false, false, true, true, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| } |
| |
| template <typename Context> |
| void elementwiseNot() { |
| const int N = 2; |
| caffe2::Workspace ws; |
| caffe2::OperatorDef def = CreateOperatorDef<Context>(); |
| def.set_name("test"); |
| def.set_type("Not"); |
| def.add_input("X"); |
| def.add_output("Y"); |
| FillTensor<Context, uint8_t, bool>(&ws, "X", {N}, {true, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Y"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Y(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Y.numel(), N); |
| std::vector<bool> result{false, true}; |
| for (const auto i : c10::irange(Y.numel())) { |
| EXPECT_EQ(Y.template data<bool>()[i], result[i]); |
| } |
| } |
| |
| template <typename Context> |
| void elementwiseEQ() { |
| const int N = 4; |
| const int M = 2; |
| caffe2::Workspace ws; |
| auto def = DefineOperator<Context>("EQ"); |
| { // equal size |
| FillTensor<Context, int32_t, int32_t>(&ws, "X", {N}, {1, 100, 5, -10}); |
| FillTensor<Context, int32_t, int32_t>(&ws, "Y", {N}, {0, 100, 4, -10}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), N); |
| std::vector<bool> result{false, true, false, true}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| { // boolean |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "X", {N}, {true, false, false, true}); |
| FillTensor<Context, uint8_t, bool>( |
| &ws, "Y", {N}, {true, false, true, false}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), N); |
| std::vector<bool> result{true, true, false, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| { // broadcast |
| auto* arg = def.add_arg(); |
| arg->set_name("broadcast"); |
| arg->set_i(1); |
| FillTensor<Context, int32_t, int32_t>( |
| &ws, "X", {M, N}, {1, 100, 5, -10, 3, 6, -1000, 33}); |
| FillTensor<Context, int32_t, int32_t>(&ws, "Y", {N}, {1, 6, -1000, -10}); |
| std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws)); |
| EXPECT_NE(nullptr, op.get()); |
| EXPECT_TRUE(op->Run()); |
| auto* blob = ws.GetBlob("Z"); |
| EXPECT_NE(nullptr, blob); |
| caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU); |
| EXPECT_EQ(Z.numel(), M * N); |
| std::vector<bool> result{ |
| true, false, false, true, false, true, true, false}; |
| for (const auto i : c10::irange(Z.numel())) { |
| EXPECT_EQ(Z.template data<bool>()[i], result[i]); |
| } |
| } |
| } |
| |
| #endif // CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_ |