Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / inference_engine / layer_transform.hpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma once
6
7 #include <tuple>
8 #include <memory>
9 #include <utility>
10 #include "ie_layers.h"
11
12 namespace InferenceEngine {
13
14 namespace details {
15
16 template<class T, class InjectType>
17 class LayerInjector : public T {
18  public:
19     InjectType injected;
20     explicit LayerInjector(const T & base) : T(base) {
21     }
22 };
23
24
25 using AllLayers = std::tuple <
26     DeconvolutionLayer*,
27     ConvolutionLayer *,
28     PoolingLayer*,
29     FullyConnectedLayer*,
30     GemmLayer*,
31     PadLayer*,
32     GatherLayer*,
33     StridedSliceLayer*,
34     ShuffleChannelsLayer*,
35     DepthToSpaceLayer*,
36     SpaceToDepthLayer*,
37     ReverseSequenceLayer*,
38     SqueezeLayer*,
39     UnsqueezeLayer*,
40     RangeLayer*,
41     FillLayer*,
42     ExpandLayer*,
43     ConcatLayer*,
44     SplitLayer*,
45     NormLayer*,
46     SoftMaxLayer*,
47     GRNLayer*,
48     MVNLayer*,
49     ReLULayer*,
50     EltwiseLayer*,
51     CropLayer*,
52     ReshapeLayer*,
53     TileLayer*,
54     ScaleShiftLayer*,
55     PReLULayer*,
56     PowerLayer*,
57     BatchNormalizationLayer*,
58     ClampLayer*,
59     TensorIterator*,
60     LSTMCell*,
61     GRUCell*,
62     RNNCell*,
63     RNNSequenceLayer*,
64     QuantizeLayer*,
65     BinaryConvolutionLayer*,
66     WeightableLayer*,
67     CNNLayer*
68 >;
69
70 template<typename InjectedType, typename T>
71 void dynamic_cast_layer(const CNNLayer &source, CNNLayerPtr &target, T & /*, InjectedType value*/) {
72     if (target) {
73         return;
74     }
75     auto casted = dynamic_cast<const T *>(source);
76     if (casted != nullptr) {
77         auto layerWithInjectedData =
78             std::make_shared<LayerInjector<T, InjectedType>>(LayerParams{casted->name, casted->type,
79                                                                          casted->precision});
80         target = layerWithInjectedData;
81     }
82 }
83
84 template<class Visitor, std::size_t I = 0, typename... Tp>
85 inline typename std::enable_if<I == sizeof...(Tp), void>::type
86 visitActualLayer(std::tuple<Tp...> &&t, const CNNLayer &sourceLayer, const Visitor & v) {}
87
88 template<class Visitor, std::size_t I = 0, typename... Tp>
89 inline typename std::enable_if < I < sizeof...(Tp), void>::type
90 visitActualLayer(std::tuple<Tp...> &&t, const CNNLayer &sourceLayer, const Visitor & visitor) {
91     using EType = typename std::tuple_element<I, std::tuple<Tp...>>::type;
92     auto casted = dynamic_cast<EType>(const_cast<CNNLayer *>(&sourceLayer));
93
94     if (casted != nullptr) {
95         // means no need to handle further layers
96         if (visitor(casted)) {
97             return;
98         }
99     }
100
101     visitActualLayer<Visitor, I + 1, Tp...>(std::move(t), sourceLayer, visitor);
102 }
103
104 template<class InjectedType, std::size_t I = 0, typename... Tp>
105 inline typename std::enable_if<I == sizeof...(Tp), void>::type
106 injectHelper(std::tuple<Tp...> &t, const CNNLayer &sourceLayer, CNNLayerPtr &targetLayer, const InjectedType &value) {}
107
108 template<class InjectedType, std::size_t I = 0, typename... Tp>
109 inline typename std::enable_if < I < sizeof...(Tp), void>::type
110 injectHelper(std::tuple<Tp...> &t, const CNNLayer &sourceLayer, CNNLayerPtr &target, const InjectedType &value) {
111     if (target) {
112         return;
113     }
114     using EType = typename std::tuple_element<I, std::tuple<Tp...>>::type;
115     auto casted = dynamic_cast<EType>(const_cast<CNNLayer *>(&sourceLayer));
116
117     if (casted != nullptr) {
118         auto layerWithInjectedData =
119             std::make_shared<LayerInjector<typename std::remove_pointer<EType>::type, InjectedType>>(*casted);
120
121         // copy outdata
122         for (auto && data : layerWithInjectedData->outData) {
123             data = std::make_shared<Data>(*data.get());
124         }
125
126         layerWithInjectedData->injected = value;
127
128         target = layerWithInjectedData;
129     }
130
131     injectHelper<InjectedType, I + 1, Tp...>(t, sourceLayer, target, value);
132 }
133
134 template<class InjectedType, std::size_t I = 0, typename... Tp>
135 inline typename std::enable_if<I == sizeof...(Tp), void>::type
136 locateInjected(std::tuple<Tp...> &t, const CNNLayer &sourceLayer, InjectedType *&value) {}
137
138 template<class InjectedType, std::size_t I = 0, typename... Tp>
139 inline typename std::enable_if < I < sizeof...(Tp), void>::type
140 locateInjected(std::tuple<Tp...> &t, const CNNLayer &sourceLayer, InjectedType *&value) {
141     if (value != nullptr) {
142         return;
143     }
144     using EType = typename std::tuple_element<I, std::tuple<Tp...>>::type;
145     auto injectedLayer = dynamic_cast<LayerInjector<typename std::remove_pointer<EType>::type,
146                                                     InjectedType> *>(const_cast<CNNLayer *>(&sourceLayer));
147
148     if (injectedLayer != nullptr) {
149         value = &injectedLayer->injected;
150     }
151
152     locateInjected<InjectedType, I + 1, Tp...>(t, sourceLayer, value);
153 }
154
155 }  // namespace details
156
157 /**
158  * @brief creates copy of source layer, with injected arbitrary data
159  * @tparam InjectType data type to be injected
160  * @param sourceLayer
161  * @param value injected value
162  * @return newly created layer with injected data
163  */
164 template<class InjectType>
165 inline CNNLayerPtr injectData(const CNNLayer & sourceLayer, const InjectType &value = InjectType()) {
166     details::AllLayers layers;
167     CNNLayerPtr targetLayer;
168     details::injectHelper(layers, sourceLayer, targetLayer, value);
169
170     return targetLayer;
171 }
172
173 template<class InjectType>
174 inline CNNLayerPtr injectData(CNNLayerPtr sourceLayer, const InjectType & value = InjectType()) {
175     return injectData(*sourceLayer.get(), value);
176 }
177
178 /**
179  * @brief transforms of source layer
180  * @tparam InjectType data type to be injected
181  * @param sourceLayer
182  * @param value injected value
183  * @return newly created layer with injected data
184  */
185 template<class Transformer>
186 inline void transformLayer(const CNNLayer & sourceLayer, const Transformer & transformer) {
187     details::visitActualLayer<Transformer>(std::move(details::AllLayers()), sourceLayer, transformer);
188 }
189
190 template<class Transformer>
191 inline void transformLayer(CNNLayerPtr sourceLayer, const Transformer & transformer) {
192     transformLayer(*sourceLayer.get(), transformer);
193 }
194
195 /**
196  * @brief  getPointer to injected data
197  * @tparam InjectType
198  * @param sourceLayer
199  * @return if previously data of type InjectType was injected, will return pointer to it, nullptr otherwise
200  */
201 template<class InjectType>
202 inline InjectType * getInjectedData(const CNNLayer & sourceLayer) {
203     details::AllLayers layers;
204     InjectType *injected = nullptr;
205
206     details::locateInjected(layers, sourceLayer, injected);
207
208     return injected;
209 }
210
211 template<class InjectType>
212 inline InjectType * getInjectedData(CNNLayerPtr sourceLayer) {
213     return getInjectedData<InjectType>(*sourceLayer.get());
214 }
215
216
217 }  // namespace InferenceEngine