|  | #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_ |