Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / api / CPP / eltwise.hpp
1 /*
2 // Copyright (c) 2016-2019 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
18 #pragma once
19 #include "../C/eltwise.h"
20 #include "primitive.hpp"
21
22 namespace cldnn
23 {
24 /// @addtogroup cpp_api C++ API
25 /// @{
26 /// @addtogroup cpp_topology Network Topology
27 /// @{
28 /// @addtogroup cpp_primitives Primitives
29 /// @{
30
31 /// @brief Select mode for the @ref eltwise layer.
32 enum class eltwise_mode : int32_t
33 {
34     /// @brief Eltwise sum.
35     sum = cldnn_eltwise_sum,
36     /// @brief Eltwise subtract.
37     sub = cldnn_eltwise_sub,
38     /// @brief Eltwise max.
39     max = cldnn_eltwise_max,
40     /// @brief Eltwise product (Hadamard).
41     prod = cldnn_eltwise_prod,
42     /// @brief Eltwise div.
43     div = cldnn_eltwise_div,
44     /// @brief Eltwise min.
45     min = cldnn_eltwise_min,
46     /// @brief Eltwise pow.
47     pow = cldnn_eltwise_pow,
48     /// @brief Eltwise squared diff.
49     squared_diff = cldnn_eltwise_squared_diff,
50     /// @brief Eltwise mod.
51     mod = cldnn_eltwise_mod,
52     /// @brief Eltwise equal.
53     eq = cldnn_eltwise_eq,
54     /// @brief Eltwise not equal.
55     ne = cldnn_eltwise_ne,
56     /// @brief Eltwise less.
57     lt = cldnn_eltwise_lt,
58     /// @brief Eltwise less of equal.
59     le = cldnn_eltwise_le,
60     /// @brief Eltwise greater.
61     gt = cldnn_eltwise_gt,
62     /// @brief Eltwise greater or equal.
63     ge = cldnn_eltwise_ge,
64     /// @brief Eltwise and.
65     logic_and = cldnn_eltwise_and,
66     /// @brief Eltwise or.
67     logic_or = cldnn_eltwise_or,
68     /// @brief Eltwise XOR.
69     logic_xor = cldnn_eltwise_xor
70 };
71
72 /// @brief Performs elementwise operations (sum, subtract, max or product) on two input primitives
73 /// Also supports built-in Relu @ref activation available by setting it in arguments.
74 /// @notes
75 /// - both inputs have to have equal sizes in all dimensions or the input tensors are broadcastable
76 ///   to the same shape in which the size of each dimention is a max. of input sizes on this dimension)
77 /// - format of both inputs has to be the same
78 /// - when using integer types, only following eltwise modes are supported: sum, sub, prod, div
79 struct eltwise : public primitive_base<eltwise, CLDNN_PRIMITIVE_DESC(eltwise)>
80 {
81     CLDNN_DECLARE_PRIMITIVE(eltwise)
82
83     /// @brief Constructs eltwise primitive.
84     /// @param id This primitive id.
85     /// @param input Input primitive id.
86     /// @param input2 Second input primitive id with values needed for eltwise computation.
87     /// @param mode Eltwise mode.
88     /// @param with_activation Enables Relu activation.
89     /// @param activation_slp Relu activation slope.
90     eltwise(
91         const primitive_id& id,
92         const primitive_id& input,
93         const primitive_id& input2,
94         eltwise_mode mode,
95         bool with_activation = false,
96         float activation_slp = 0.0f,
97         const padding& output_padding = padding()
98     )
99         :primitive_base(id, { input, input2 }, output_padding)
100         , output_calibration_factors("")
101         , output_quantization_factor(1.0f)
102         , mode(mode)
103         , coefficients(std::vector<float>(0))
104         , with_activation(with_activation)
105         , activation_negative_slope(activation_slp)
106         , stride(std::vector<tensor>(0))
107         , _stride(tensor_vector_to_cldnn_vector(stride))
108     {
109     }
110
111     /// @brief Constructs eltwise primitive.
112     /// @param id This primitive id.
113     /// @param input Input primitive id.
114     /// @param input2 Second input primitive id with values needed for eltwise computation.
115     /// @param stride Defines shift in input buffers between adjacent calculations of output values.
116     /// @param mode Eltwise mode.
117     /// @param with_activation Enables Relu activation.
118     /// @param activation_slp Relu activation slope.
119     eltwise(
120         const primitive_id& id,
121         const primitive_id& input,
122         const primitive_id& input2,
123         std::vector<tensor> stride,
124         eltwise_mode mode,
125         bool with_activation = false,
126         float activation_slp = 0.0f,
127         const padding& output_padding = padding()
128     )
129         :primitive_base(id, { input, input2 }, output_padding)
130         , output_calibration_factors("")
131         , output_quantization_factor(1.0f)
132         , mode(mode)
133         , coefficients(std::vector<float>(0))
134         , with_activation(with_activation)
135         , activation_negative_slope(activation_slp)
136         , stride(stride)
137         , _stride(tensor_vector_to_cldnn_vector(stride))
138     {
139     }
140
141     /// @brief Constructs eltwise primitive.
142     /// @param id This primitive id.
143     /// @param inputs Input primitives ids.
144     /// @param mode Eltwise mode.
145     /// @param with_activation Enables Relu activation.
146     /// @param activation_slp Relu activation slope.
147     eltwise(
148         const primitive_id& id,
149         const std::vector<primitive_id>& inputs,
150         eltwise_mode mode,
151         bool with_activation = false,
152         float activation_slp = 0.0f,
153         const padding& output_padding = padding()
154     )
155         :primitive_base(id, inputs, output_padding)
156         , output_calibration_factors("")
157         , output_quantization_factor(1.0f)
158         , mode(mode)
159         , coefficients(std::vector<float>(0))
160         , with_activation(with_activation)
161         , activation_negative_slope(activation_slp)
162         , stride(std::vector<tensor>(0))
163         , _stride(tensor_vector_to_cldnn_vector(stride))
164     {
165     }
166
167     /// @brief Constructs eltwise primitive.
168     /// @param id This primitive id.
169     /// @param input Input primitive id.
170     /// @param input2 Second input primitive id with values needed for eltwise computation.
171     /// @param output_calibration_factors Primitive id containing output calibration factors per output feature map.
172     /// @param mode Eltwise mode.
173     /// @param with_activation Enables Relu activation.
174     /// @param activation_slp Relu activation slope.
175     eltwise(
176         const primitive_id& id,
177         const primitive_id& input,
178         const primitive_id& input2,
179         const primitive_id& output_calibration_factors,
180         eltwise_mode mode,
181         bool with_activation = false,
182         float activation_slp = 0.0f,
183         const padding& output_padding = padding()
184     )
185         :primitive_base(id, { input, input2 }, output_padding)
186         , output_calibration_factors(output_calibration_factors)
187         , output_quantization_factor(1.0f)
188         , mode(mode)
189         , coefficients(std::vector<float>(0))
190         , with_activation(with_activation)
191         , activation_negative_slope(activation_slp)
192         , stride(std::vector<tensor>(0))
193         , _stride(tensor_vector_to_cldnn_vector(stride))
194     {
195     }
196
197     /// @brief Constructs eltwise primitive.
198     /// @param id This primitive id.
199     /// @param inputs Input primitives ids.
200     /// @param output_calibration_factors Primitive id containing output calibration factors per output feature map.
201     /// @param mode Eltwise mode.
202     /// @param with_activation Enables Relu activation.
203     /// @param activation_slp Relu activation slope.
204     eltwise(
205         const primitive_id& id,
206         const std::vector<primitive_id>& inputs,
207         const primitive_id& output_calibration_factors,
208         eltwise_mode mode,
209         bool with_activation = false,
210         float activation_slp = 0.0f,
211         const padding& output_padding = padding()
212     )
213         :primitive_base(id, inputs, output_padding)
214         , output_calibration_factors(output_calibration_factors)
215         , output_quantization_factor(1.0f)
216         , mode(mode)
217         , coefficients(std::vector<float>(0))
218         , with_activation(with_activation)
219         , activation_negative_slope(activation_slp)
220         , stride(std::vector<tensor>(0))
221         , _stride(tensor_vector_to_cldnn_vector(stride))
222     {
223     }
224
225     /// @brief Constructs eltwise primitive.
226     /// @param id This primitive id.
227     /// @param input Input primitive id.
228     /// @param input2 Second input primitive id with values needed for eltwise computation.
229     /// @param o_quantization_factor Output quantization factor
230     /// @param mode Eltwise mode.
231     /// @param with_activation Enables Relu activation.
232     /// @param activation_slp Relu activation slope.
233     eltwise(
234         const primitive_id& id,
235         const primitive_id& input,
236         const primitive_id& input2,
237         const float o_quantization_factor,
238         eltwise_mode mode,
239         bool with_activation = false,
240         float activation_slp = 0.0f,
241         const padding& output_padding = padding()
242     )
243         :primitive_base(id, { input, input2 }, output_padding)
244         , output_calibration_factors("")
245         , output_quantization_factor(o_quantization_factor)
246         , mode(mode)
247         , coefficients(std::vector<float>(0))
248         , with_activation(with_activation)
249         , activation_negative_slope(activation_slp)
250         , stride(std::vector<tensor>(0))
251         , _stride(tensor_vector_to_cldnn_vector(stride))
252     {
253     }
254
255     /// @brief Constructs eltwise primitive.
256     /// @param id This primitive id.
257     /// @param inputs Input primitives ids.
258     /// @param o_quantization_factor Output quantization factor
259     /// @param mode Eltwise mode.
260     /// @param with_activation Enables Relu activation.
261     /// @param activation_slp Relu activation slope.
262     eltwise(
263         const primitive_id& id,
264         const std::vector<primitive_id>& inputs,
265         const float o_quantization_factor,
266         eltwise_mode mode,
267         bool with_activation = false,
268         float activation_slp = 0.0f,
269         const padding& output_padding = padding()
270     )
271         :primitive_base(id, inputs, output_padding)
272         , output_calibration_factors("")
273         , output_quantization_factor(o_quantization_factor)
274         , mode(mode)
275         , coefficients(std::vector<float>(0))
276         , with_activation(with_activation)
277         , activation_negative_slope(activation_slp)
278         , stride(std::vector<tensor>(0))
279         , _stride(tensor_vector_to_cldnn_vector(stride))
280     {
281     }
282
283     /// @brief Constructs eltwise primitive.
284     /// @param id This primitive id.
285     /// @param inputs Input primitives ids.
286     /// @param coefficients Blob-wise coefficient for SUM operation
287     /// @param mode Eltwise mode.
288     /// @param with_activation Enables Relu activation.
289     /// @param activation_slp Relu activation slope.
290     eltwise(
291         const primitive_id& id,
292         const std::vector<primitive_id>& inputs,
293         eltwise_mode mode,
294         const std::vector<float>& coefficients,
295         bool with_activation = false,
296         float activation_slp = 0.0f,
297         const padding& output_padding = padding()
298     )
299         :primitive_base(id, inputs, output_padding)
300         , output_calibration_factors("")
301         , output_quantization_factor(1.0f)
302         , mode(mode)
303         , coefficients(coefficients)
304         , with_activation(with_activation)
305         , activation_negative_slope(activation_slp)
306         , stride(std::vector<tensor>(0))
307         , _stride(tensor_vector_to_cldnn_vector(stride))
308     {
309         if (mode == eltwise_mode::sum && !coefficients.empty() && coefficients.size() != inputs.size())
310         {
311             throw std::invalid_argument("Invalid eltwise sum coefficients count (should be equal to 0 or input.size)");
312         }
313         if (mode != eltwise_mode::sum && !coefficients.empty())
314         {
315             throw std::invalid_argument("Only eltwise sum operation supports blob-wise coefficients");
316         }
317     }
318
319     /// @brief Constructs a copy from C API @CLDNN_PRIMITIVE_DESC{eltwise}
320     eltwise(const dto* dto)
321         :primitive_base(dto)
322         , output_calibration_factors(dto->output_calibration_factors)
323         , output_quantization_factor(dto->output_quantization_factor)
324         , mode(static_cast<eltwise_mode>(dto->mode))
325         , coefficients(float_arr_to_vector(dto->coefficients))
326         , with_activation(dto->with_activation != 0)
327         , activation_negative_slope(dto->activation_negative_slope)
328         , stride(tensor_arr_to_vector(dto->stride))
329         , _stride(tensor_vector_to_cldnn_vector(stride))
330     {
331         if (dto->input.size < 2)
332             throw std::invalid_argument("eltiwise dto should containt at least two inputs");
333         if (dto->coefficients.size != 0 && dto->coefficients.size != dto->input.size)
334             throw std::invalid_argument("Invalid eltwise coefficients count in dto (should be equal to 0 or input.size)");
335     }
336
337     /// @brief Primitive id containing output quanitization factors per output feature map.
338     primitive_id output_calibration_factors;
339     /// @brief Output quantization factor
340     float output_quantization_factor;
341     /// @param mode Eltwise mode.
342     eltwise_mode mode;
343     /// @param coefficients Blob-wise coefficient for SUM operation.
344     std::vector<float> coefficients;
345     /// @brief Enables Relu activation.
346     bool with_activation;
347     /// @brief Relu activation slope.
348     float activation_negative_slope;
349     /// @brief Defines shift in input buffers between adjacent calculations of output values.
350     std::vector<tensor> stride;
351
352 protected:
353     std::vector<cldnn_tensor> _stride;
354     std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override
355     {
356         std::vector<std::reference_wrapper<const primitive_id>> ret;
357         if(!output_calibration_factors.empty())
358             ret.push_back(output_calibration_factors);
359
360         return ret;
361     }
362
363     void update_dto(dto& dto) const override
364     {
365         dto.output_calibration_factors = output_calibration_factors.c_str();
366         dto.output_quantization_factor = output_quantization_factor;
367         dto.mode = static_cast<cldnn_eltwise_mode>(mode);
368         dto.coefficients = float_vector_to_arr(coefficients);
369         dto.with_activation = with_activation;
370         dto.activation_negative_slope = activation_negative_slope;
371         dto.stride = tensor_vector_to_arr(_stride);
372     }
373 };
374 /// @}
375 /// @}
376 /// @}
377 }