Caffe2 - C++ API
A deep learning, cross platform ML framework
boolean_unmask_ops.cc
1 #include "caffe2/operators/boolean_unmask_ops.h"
2 #include "caffe2/core/operator.h"
3 #include "caffe2/core/tensor.h"
4 
5 namespace caffe2 {
6 
7 template <>
8 bool BooleanUnmaskOp<CPUContext>::RunOnDevice() {
9  int maskSize = Input(0).size();
10  int numMasks = InputSize() / 2;
11  auto& valueMeta = Input(1).meta();
12 
13  auto* valuesOut = Output(0);
14  valuesOut->Resize(maskSize);
15  auto* valuesOutPtr = (char*)valuesOut->raw_mutable_data(valueMeta);
16 
17  std::vector<int> nextValueIndices(numMasks, 0);
18  for (int maskOffset = 0; maskOffset < maskSize; ++maskOffset) {
19  bool maskFound = false;
20  for (int maskIndex = 0; maskIndex < numMasks; ++maskIndex) {
21  auto& mask = Input(maskIndex * 2);
22  CAFFE_ENFORCE_EQ(mask.ndim(), 1);
23  CAFFE_ENFORCE_EQ(mask.size(), maskSize);
24  const auto* maskPtr = mask.template data<bool>();
25 
26  auto& values = Input(maskIndex * 2 + 1);
27  CAFFE_ENFORCE_EQ(values.ndim(), 1);
28  const auto* valuesPtr = (char*)values.raw_data();
29 
30  if (maskPtr[maskOffset]) {
31  auto& valueIndex = nextValueIndices[maskIndex];
32  CAFFE_ENFORCE_LT(valueIndex, values.size());
33  auto* src = valuesPtr + (valueIndex++) * valueMeta.itemsize();
34  auto* dst = valuesOutPtr + maskOffset * valueMeta.itemsize();
35  std::copy(src, src + valueMeta.itemsize(), dst);
36  maskFound = true;
37  break;
38  }
39  }
40  CAFFE_ENFORCE(
41  maskFound, "All masks have False at position ", maskOffset, ".");
42  }
43  // check all indices match value length
44  for (int i = 0; i < numMasks; ++i) {
45  auto& values = Input(i * 2 + 1);
46  CAFFE_ENFORCE_EQ(
47  values.size(),
48  nextValueIndices[i],
49  "The number of true at mask ",
50  i,
51  " does not match the corresponding value size.");
52  }
53  return true;
54 }
55 
56 REGISTER_CPU_OPERATOR(BooleanUnmask, BooleanUnmaskOp<CPUContext>);
57 
58 OPERATOR_SCHEMA(BooleanUnmask)
59  .NumInputs([](int n) { return n > 0 && n % 2 == 0; })
60  .NumOutputs(1)
61  .SetDoc(R"DOC(
62 Given a series of mask and values, reconstruct values together according
63 to masks.
64 
65 A comprehensive example:
66  mask1 = True, False, True, False, False
67  values1 = 1.0, 3.0
68  mask2 = False, True, False, False, False
69  values2 = 2.0
70  mask3 = False, False, False, True, True
71  values3 = 4.0, 5.0
72 
73 Reconstruct by:
74  output = net.BooleanUnmask([mask1, values1, mask2, values2, mask3, values3], ["output"])
75 
76 We get:
77  output = 1.0, 2.0, 3.0, 4.0, 5.0
78 
79 Note that for all mask positions, there must be at least one True. If for a
80 field there are multiple True's, we will accept the first value. For example:
81 
82 
83 Example 1:
84  mask1 = True, False
85  values1 = 1.0
86  mask2 = False, False
87  values2 =
88 
89 This is not allowed:
90  output = net.BooleanUnmask([mask1, values1, mask2, values2], ["output"])
91 
92 Example 2:
93  mask1 = True, False
94  values1 = 1.0
95  mask2 = True, True
96  values2 = 2.0, 2.0
97 
98  output = net.BooleanUnmask([mask1, values1, mask2, values2], ["output"])
99 
100 We get:
101  output = 1.0, 2.0
102 )DOC")
103  .Output(0, "unmasked_data", "The final reconstructed unmasked data");
104 
105 NO_GRADIENT(BooleanUnmask)
106 }
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...