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