1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
10 #include "ie_layers.h"
12 namespace InferenceEngine {
16 template<class T, class InjectType>
17 class LayerInjector : public T {
20 explicit LayerInjector(const T & base) : T(base) {
25 using AllLayers = std::tuple <
34 ShuffleChannelsLayer*,
37 ReverseSequenceLayer*,
57 BatchNormalizationLayer*,
65 BinaryConvolutionLayer*,
70 template<typename InjectedType, typename T>
71 void dynamic_cast_layer(const CNNLayer &source, CNNLayerPtr &target, T & /*, InjectedType value*/) {
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,
80 target = layerWithInjectedData;
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) {}
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));
94 if (casted != nullptr) {
95 // means no need to handle further layers
96 if (visitor(casted)) {
101 visitActualLayer<Visitor, I + 1, Tp...>(std::move(t), sourceLayer, visitor);
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) {}
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) {
114 using EType = typename std::tuple_element<I, std::tuple<Tp...>>::type;
115 auto casted = dynamic_cast<EType>(const_cast<CNNLayer *>(&sourceLayer));
117 if (casted != nullptr) {
118 auto layerWithInjectedData =
119 std::make_shared<LayerInjector<typename std::remove_pointer<EType>::type, InjectedType>>(*casted);
122 for (auto && data : layerWithInjectedData->outData) {
123 data = std::make_shared<Data>(*data.get());
126 layerWithInjectedData->injected = value;
128 target = layerWithInjectedData;
131 injectHelper<InjectedType, I + 1, Tp...>(t, sourceLayer, target, value);
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) {}
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) {
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));
148 if (injectedLayer != nullptr) {
149 value = &injectedLayer->injected;
152 locateInjected<InjectedType, I + 1, Tp...>(t, sourceLayer, value);
155 } // namespace details
158 * @brief creates copy of source layer, with injected arbitrary data
159 * @tparam InjectType data type to be injected
161 * @param value injected value
162 * @return newly created layer with injected data
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);
173 template<class InjectType>
174 inline CNNLayerPtr injectData(CNNLayerPtr sourceLayer, const InjectType & value = InjectType()) {
175 return injectData(*sourceLayer.get(), value);
179 * @brief transforms of source layer
180 * @tparam InjectType data type to be injected
182 * @param value injected value
183 * @return newly created layer with injected data
185 template<class Transformer>
186 inline void transformLayer(const CNNLayer & sourceLayer, const Transformer & transformer) {
187 details::visitActualLayer<Transformer>(std::move(details::AllLayers()), sourceLayer, transformer);
190 template<class Transformer>
191 inline void transformLayer(CNNLayerPtr sourceLayer, const Transformer & transformer) {
192 transformLayer(*sourceLayer.get(), transformer);
196 * @brief getPointer to injected data
199 * @return if previously data of type InjectType was injected, will return pointer to it, nullptr otherwise
201 template<class InjectType>
202 inline InjectType * getInjectedData(const CNNLayer & sourceLayer) {
203 details::AllLayers layers;
204 InjectType *injected = nullptr;
206 details::locateInjected(layers, sourceLayer, injected);
211 template<class InjectType>
212 inline InjectType * getInjectedData(CNNLayerPtr sourceLayer) {
213 return getInjectedData<InjectType>(*sourceLayer.get());
217 } // namespace InferenceEngine