Caffe2 - C++ API
A deep learning, cross platform ML framework
elementwise_op_test.h
1 #ifndef CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_
2 #define CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_
3 
4 #include <iostream>
5 #include <string>
6 #include <vector>
7 
8 #include "caffe2/operators/elementwise_op.h"
9 #include <gtest/gtest.h>
10 
11 template <typename Context, typename T>
12 void CopyVector(const int N, const T* x, T* y);
13 
14 template <typename Context, typename I_Type, typename O_Type>
15 void FillTensor(
17  const std::string& name,
18  const std::vector<caffe2::TIndex>& shape,
19  const std::vector<I_Type>& values) {
20  auto* blob = ws->CreateBlob(name);
21  auto* tensor = blob->GetMutable<caffe2::Tensor<Context>>();
22  tensor->Resize(shape);
23  auto* mutable_data = tensor->template mutable_data<O_Type>();
24  const O_Type* data = reinterpret_cast<const O_Type*>(values.data());
25  CopyVector<Context, O_Type>(values.size(), data, mutable_data);
26 }
27 
28 template <typename Context>
29 caffe2::OperatorDef CreateOperatorDef() {
30  caffe2::OperatorDef def;
31  return def;
32 }
33 
34 template <typename Context>
35 caffe2::OperatorDef DefineOperator(const std::string& op_type) {
36  caffe2::OperatorDef def = CreateOperatorDef<Context>();
37  def.set_name("test");
38  def.set_type(op_type);
39  def.add_input("X");
40  def.add_input("Y");
41  def.add_output("Z");
42  return def;
43 }
44 
45 template <typename Context>
46 void elementwiseAnd() {
47  const int N = 4;
48  const int M = 2;
50  auto def = DefineOperator<Context>("And");
51  { // equal size
52  FillTensor<Context, uint8_t, bool>(
53  &ws, "X", {N}, {true, false, true, false});
54  FillTensor<Context, uint8_t, bool>(
55  &ws, "Y", {N}, {true, true, false, false});
56  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
57  EXPECT_NE(nullptr, op.get());
58  EXPECT_TRUE(op->Run());
59  auto* blob = ws.GetBlob("Z");
60  EXPECT_NE(nullptr, blob);
62  EXPECT_EQ(Z.size(), N);
63  std::vector<bool> result{true, false, false, false};
64  for (size_t i = 0; i < Z.size(); ++i) {
65  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
66  }
67  }
68  { // broadcast
69  auto* arg = def.add_arg();
70  arg->set_name("broadcast");
71  arg->set_i(1);
72  FillTensor<Context, uint8_t, bool>(
73  &ws, "X", {M, N}, {true, false, true, false, true, false, true, false});
74  FillTensor<Context, uint8_t, bool>(
75  &ws, "Y", {N}, {true, true, false, false});
76  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
77  EXPECT_NE(nullptr, op.get());
78  EXPECT_TRUE(op->Run());
79  auto* blob = ws.GetBlob("Z");
80  EXPECT_NE(nullptr, blob);
82  EXPECT_EQ(Z.size(), M * N);
83  std::vector<bool> result{
84  true, false, false, false, true, false, false, false};
85  for (size_t i = 0; i < Z.size(); ++i) {
86  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
87  }
88  }
89 }
90 
91 template <typename Context>
92 void elementwiseOr() {
93  const int N = 4;
94  const int M = 2;
96  auto def = DefineOperator<Context>("Or");
97  { // equal size
98  FillTensor<Context, uint8_t, bool>(
99  &ws, "X", {N}, {true, false, true, false});
100  FillTensor<Context, uint8_t, bool>(
101  &ws, "Y", {N}, {true, true, false, false});
102  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
103  EXPECT_NE(nullptr, op.get());
104  EXPECT_TRUE(op->Run());
105  auto* blob = ws.GetBlob("Z");
106  EXPECT_NE(nullptr, blob);
108  EXPECT_EQ(Z.size(), N);
109  std::vector<bool> result{true, true, true, false};
110  for (size_t i = 0; i < Z.size(); ++i) {
111  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
112  }
113  }
114  { // broadcast
115  auto* arg = def.add_arg();
116  arg->set_name("broadcast");
117  arg->set_i(1);
118  FillTensor<Context, uint8_t, bool>(
119  &ws, "X", {M, N}, {true, false, true, false, true, false, true, false});
120  FillTensor<Context, uint8_t, bool>(
121  &ws, "Y", {N}, {true, true, false, false});
122  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
123  EXPECT_NE(nullptr, op.get());
124  EXPECT_TRUE(op->Run());
125  auto* blob = ws.GetBlob("Z");
126  EXPECT_NE(nullptr, blob);
128  EXPECT_EQ(Z.size(), M * N);
129  std::vector<bool> result{true, true, true, false, true, true, true, false};
130  for (size_t i = 0; i < Z.size(); ++i) {
131  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
132  }
133  }
134 }
135 
136 template <typename Context>
137 void elementwiseXor() {
138  const int N = 4;
139  const int M = 2;
141  auto def = DefineOperator<Context>("Xor");
142  { // equal size
143  FillTensor<Context, uint8_t, bool>(
144  &ws, "X", {N}, {true, false, true, false});
145  FillTensor<Context, uint8_t, bool>(
146  &ws, "Y", {N}, {true, true, false, false});
147  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
148  EXPECT_NE(nullptr, op.get());
149  EXPECT_TRUE(op->Run());
150  auto* blob = ws.GetBlob("Z");
151  EXPECT_NE(nullptr, blob);
153  EXPECT_EQ(Z.size(), N);
154  std::vector<bool> result{false, true, true, false};
155  for (size_t i = 0; i < Z.size(); ++i) {
156  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
157  }
158  }
159  { // broadcast
160  auto* arg = def.add_arg();
161  arg->set_name("broadcast");
162  arg->set_i(1);
163  FillTensor<Context, uint8_t, bool>(
164  &ws, "X", {M, N}, {true, false, true, false, true, false, true, false});
165  FillTensor<Context, uint8_t, bool>(
166  &ws, "Y", {N}, {true, true, false, false});
167  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
168  EXPECT_NE(nullptr, op.get());
169  EXPECT_TRUE(op->Run());
170  auto* blob = ws.GetBlob("Z");
171  EXPECT_NE(nullptr, blob);
173  EXPECT_EQ(Z.size(), M * N);
174  std::vector<bool> result{
175  false, true, true, false, false, true, true, false};
176  for (size_t i = 0; i < Z.size(); ++i) {
177  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
178  }
179  }
180 }
181 
182 template <typename Context>
183 void elementwiseNot() {
184  const int N = 2;
186  caffe2::OperatorDef def = CreateOperatorDef<Context>();
187  def.set_name("test");
188  def.set_type("Not");
189  def.add_input("X");
190  def.add_output("Y");
191  FillTensor<Context, uint8_t, bool>(&ws, "X", {N}, {true, false});
192  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
193  EXPECT_NE(nullptr, op.get());
194  EXPECT_TRUE(op->Run());
195  auto* blob = ws.GetBlob("Y");
196  EXPECT_NE(nullptr, blob);
198  EXPECT_EQ(Y.size(), N);
199  std::vector<bool> result{false, true};
200  for (size_t i = 0; i < Y.size(); ++i) {
201  EXPECT_EQ(Y.template data<bool>()[i], result[i]);
202  }
203 }
204 
205 template <typename Context>
206 void elementwiseEQ() {
207  const int N = 4;
208  const int M = 2;
210  auto def = DefineOperator<Context>("EQ");
211  { // equal size
212  FillTensor<Context, int32_t, int32_t>(&ws, "X", {N}, {1, 100, 5, -10});
213  FillTensor<Context, int32_t, int32_t>(&ws, "Y", {N}, {0, 100, 4, -10});
214  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
215  EXPECT_NE(nullptr, op.get());
216  EXPECT_TRUE(op->Run());
217  auto* blob = ws.GetBlob("Z");
218  EXPECT_NE(nullptr, blob);
220  EXPECT_EQ(Z.size(), N);
221  std::vector<bool> result{false, true, false, true};
222  for (size_t i = 0; i < Z.size(); ++i) {
223  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
224  }
225  }
226  { // boolean
227  FillTensor<Context, uint8_t, bool>(
228  &ws, "X", {N}, {true, false, false, true});
229  FillTensor<Context, uint8_t, bool>(
230  &ws, "Y", {N}, {true, false, true, false});
231  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
232  EXPECT_NE(nullptr, op.get());
233  EXPECT_TRUE(op->Run());
234  auto* blob = ws.GetBlob("Z");
235  EXPECT_NE(nullptr, blob);
237  EXPECT_EQ(Z.size(), N);
238  std::vector<bool> result{true, true, false, false};
239  for (size_t i = 0; i < Z.size(); ++i) {
240  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
241  }
242  }
243  { // broadcast
244  auto* arg = def.add_arg();
245  arg->set_name("broadcast");
246  arg->set_i(1);
247  FillTensor<Context, int32_t, int32_t>(
248  &ws, "X", {M, N}, {1, 100, 5, -10, 3, 6, -1000, 33});
249  FillTensor<Context, int32_t, int32_t>(&ws, "Y", {N}, {1, 6, -1000, -10});
250  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
251  EXPECT_NE(nullptr, op.get());
252  EXPECT_TRUE(op->Run());
253  auto* blob = ws.GetBlob("Z");
254  EXPECT_NE(nullptr, blob);
256  EXPECT_EQ(Z.size(), M * N);
257  std::vector<bool> result{
258  true, false, false, true, false, true, true, false};
259  for (size_t i = 0; i < Z.size(); ++i) {
260  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
261  }
262  }
263 }
264 
265 #endif // CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_
Blob * CreateBlob(const string &name)
Creates a blob of the given name.
Definition: workspace.cc:104
Tensor is the basic class in Caffe2 that stores a contiguous memory with its shape information...
Definition: tensor.h:93
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47