Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / inference_engine / ie_layers_internal.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <algorithm>
6 #include <map>
7 #include <vector>
8 #include <string>
9 #include <tuple>
10 #include "ie_layers_internal.hpp"
11 #include "layer_transform.hpp"
12
13 namespace InferenceEngine {
14
15 template<class Layer>
16 int getKernel(const Layer &layer, size_t i) {
17     if (layer._dilation.size() > i && layer._dilation[i])
18         return (layer._kernel[i] - 1) * layer._dilation[i] + 1;
19     return layer._kernel[i];
20 }
21
22 template<>
23 int getKernel(const PoolingLayer &layer, size_t i) {
24     return layer._kernel[i];
25 }
26
27 template<class Layer>
28 Paddings getPaddingsInternal(const Layer &layer) {
29     std::string errorPrefix = "Failed to calculate padding for " + layer.type + ": ";
30     try {
31         const std::map<std::string, std::string> &params = layer.params;
32         const std::vector<DataWeakPtr> &insData = layer.insData;
33         auto it = params.find("auto_pad");
34         if (it != params.end()) {
35             if (it->second == "valid") {
36                 return {PropertyVector<unsigned>(layer._kernel.size(), 0u),
37                         PropertyVector<unsigned>(layer._kernel.size(), 0u)};
38             } else {
39                 if (insData.size() != 1)
40                     THROW_IE_EXCEPTION << "number of inputs should be equal 1";
41                 auto firstInput = insData[0].lock();
42                 if (!firstInput)
43                     THROW_IE_EXCEPTION << "input is empty";
44                 auto shape = firstInput->getTensorDesc().getDims();
45                 auto shape_size = shape.size();
46                 if (shape_size < 4 || shape_size > 5)
47                     THROW_IE_EXCEPTION << "input shape must be 4D or 5D";
48
49                 std::vector<int> shapes;
50                 shapes.push_back(shape[shape_size - 1]);
51                 shapes.push_back(shape[shape_size - 2]);
52                 if (shape.size() > 4)
53                     shapes.push_back(shape[shape_size - 3]);
54
55                 PropertyVector<unsigned int> pad_begin, pad_end;
56
57                 for (size_t i = 0; i < layer._kernel.size(); i++) {
58                     int PA = 0;
59                     int kernel = getKernel(layer, i);
60
61                     int stride = layer._stride.size() > i ? layer._stride[i] : 1;
62                     int sh = shapes[i];
63                     if (sh % stride == 0) {
64                         PA = std::max(kernel - stride, 0);
65                     } else {
66                         PA = std::max(kernel - (sh % stride), 0);
67                     }
68                     unsigned p_begin = PA / 2;
69                     unsigned p_end = PA - p_begin;
70
71                     pad_begin.insert(i, p_begin);
72                     pad_end.insert(i, p_end);
73                 }
74
75                 return {pad_begin, pad_end};
76             }
77         }
78         return {layer._padding, layer._pads_end};
79     } catch (const InferenceEngine::details::InferenceEngineException &iee) {
80         THROW_IE_EXCEPTION << errorPrefix << iee.what();
81     }
82 }
83
84 class PaddingsUpdater {
85     std::reference_wrapper<Paddings> pad;
86  public:
87     explicit PaddingsUpdater(Paddings & pad) : pad(pad) {}
88     template <class T>
89     typename std::enable_if<!std::is_same<T, CNNLayer*>::value, bool>::type
90     operator () (T & layer) const {
91         pad.get() = getPaddingsInternal(*layer);
92         return true;
93     }
94     bool operator () (CNNLayer * layer) const {
95         THROW_IE_EXCEPTION << "padding calculation for layer: " << layer->name << "(" << layer->type << ") unsupported";
96     }
97 };
98
99 Paddings getPaddingsImpl(const CNNLayer &layer) {
100     Paddings actual;
101     details::visitActualLayer(std::tuple <DeconvolutionLayer*, ConvolutionLayer*, BinaryConvolutionLayer*, PoolingLayer*,
102             CNNLayer*>(), layer, PaddingsUpdater(actual));
103     return actual;
104 }
105
106 }  // namespace InferenceEngine