• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2018-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "arm_compute/core/Validate.h"
25 #include "arm_compute/runtime/NEON/functions/NEElementwiseOperations.h"
26 #include <src/core/NEON/kernels/NEElementwiseOperationKernel.h>
27 
28 #include "arm_compute/core/ITensor.h"
29 #include "support/MemorySupport.h"
30 
31 #include <utility>
32 
33 namespace arm_compute
34 {
35 namespace experimental
36 {
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output)37 void NEElementwiseMax::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
38 {
39     auto k = arm_compute::support::cpp14::make_unique<NEArithmeticOperationKernel>();
40     k->configure(ArithmeticOperation::MAX, input1, input2, output);
41     _kernel = std::move(k);
42 }
43 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)44 Status NEElementwiseMax::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
45 {
46     return NEArithmeticOperationKernel::validate(ArithmeticOperation::MAX, input1, input2, output);
47 }
48 
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output)49 void NEElementwiseMin::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
50 {
51     auto k = arm_compute::support::cpp14::make_unique<NEArithmeticOperationKernel>();
52     k->configure(ArithmeticOperation::MIN, input1, input2, output);
53     _kernel = std::move(k);
54 }
55 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)56 Status NEElementwiseMin::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
57 {
58     return NEArithmeticOperationKernel::validate(ArithmeticOperation::MIN, input1, input2, output);
59 }
60 
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output)61 void NEElementwiseSquaredDiff::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
62 {
63     auto k = arm_compute::support::cpp14::make_unique<NEArithmeticOperationKernel>();
64     k->configure(ArithmeticOperation::SQUARED_DIFF, input1, input2, output);
65     _kernel = std::move(k);
66 }
67 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)68 Status NEElementwiseSquaredDiff::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
69 {
70     return NEArithmeticOperationKernel::validate(ArithmeticOperation::SQUARED_DIFF, input1, input2, output);
71 }
72 
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output)73 void NEElementwiseDivision::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
74 {
75     auto k = arm_compute::support::cpp14::make_unique<NEDivisionOperationKernel>();
76     k->configure(input1, input2, output);
77     _kernel = std::move(k);
78 }
79 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)80 Status NEElementwiseDivision::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
81 {
82     return NEDivisionOperationKernel::validate(input1, input2, output);
83 }
84 
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output)85 void NEElementwisePower::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
86 {
87     auto k = arm_compute::support::cpp14::make_unique<NEPowerOperationKernel>();
88     k->configure(input1, input2, output);
89     _kernel = std::move(k);
90 }
91 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)92 Status NEElementwisePower::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
93 {
94     return NEPowerOperationKernel::validate(input1, input2, output);
95 }
96 
97 template <ComparisonOperation COP>
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output)98 void NEElementwiseComparisonStatic<COP>::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output)
99 {
100     auto k = arm_compute::support::cpp14::make_unique<NEComparisonOperationKernel>();
101     k->configure(COP, input1, input2, output);
102     _kernel = std::move(k);
103 }
104 
105 template <ComparisonOperation COP>
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)106 Status NEElementwiseComparisonStatic<COP>::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
107 {
108     return NEComparisonOperationKernel::validate(COP, input1, input2, output);
109 }
110 
configure(const ITensorInfo * input1,const ITensorInfo * input2,ITensorInfo * output,ComparisonOperation op)111 void NEElementwiseComparison::configure(const ITensorInfo *input1, const ITensorInfo *input2, ITensorInfo *output, ComparisonOperation op)
112 {
113     auto k = arm_compute::support::cpp14::make_unique<NEComparisonOperationKernel>();
114     k->configure(op, input1, input2, output);
115     _kernel = std::move(k);
116 }
117 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,ComparisonOperation op)118 Status NEElementwiseComparison::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ComparisonOperation op)
119 {
120     return NEComparisonOperationKernel::validate(op, input1, input2, output);
121 }
122 
123 // Supported Specializations
124 template class NEElementwiseComparisonStatic<ComparisonOperation::Equal>;
125 template class NEElementwiseComparisonStatic<ComparisonOperation::NotEqual>;
126 template class NEElementwiseComparisonStatic<ComparisonOperation::Greater>;
127 template class NEElementwiseComparisonStatic<ComparisonOperation::GreaterEqual>;
128 template class NEElementwiseComparisonStatic<ComparisonOperation::Less>;
129 template class NEElementwiseComparisonStatic<ComparisonOperation::LessEqual>;
130 } // namespace experimental
131 
132 struct NEElementwiseMax::Impl
133 {
134     const ITensor                                  *src_0{ nullptr };
135     const ITensor                                  *src_1{ nullptr };
136     ITensor                                        *dst{ nullptr };
137     std::unique_ptr<experimental::NEElementwiseMax> op{ nullptr };
138 };
139 
NEElementwiseMax()140 NEElementwiseMax::NEElementwiseMax()
141     : _impl(support::cpp14::make_unique<Impl>())
142 {
143 }
144 NEElementwiseMax::NEElementwiseMax(NEElementwiseMax &&) = default;
145 NEElementwiseMax &NEElementwiseMax::operator=(NEElementwiseMax &&) = default;
146 NEElementwiseMax::~NEElementwiseMax()                              = default;
147 
configure(ITensor * input1,ITensor * input2,ITensor * output,const ActivationLayerInfo & act_info)148 void NEElementwiseMax::configure(ITensor *input1, ITensor *input2, ITensor *output, const ActivationLayerInfo &act_info)
149 {
150     ARM_COMPUTE_UNUSED(act_info);
151     _impl->src_0 = input1;
152     _impl->src_1 = input2;
153     _impl->dst   = output;
154     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwiseMax>();
155     _impl->op->configure(input1->info(), input2->info(), output->info());
156 }
157 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)158 Status NEElementwiseMax::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
159 {
160     ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled());
161     return experimental::NEElementwiseMax::validate(input1, input2, output);
162 }
163 
run()164 void NEElementwiseMax::run()
165 {
166     ITensorPack pack;
167     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
168     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
169     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
170     _impl->op->run(pack);
171 }
172 
173 struct NEElementwiseMin::Impl
174 {
175     const ITensor                                  *src_0{ nullptr };
176     const ITensor                                  *src_1{ nullptr };
177     ITensor                                        *dst{ nullptr };
178     std::unique_ptr<experimental::NEElementwiseMin> op{ nullptr };
179 };
180 
NEElementwiseMin()181 NEElementwiseMin::NEElementwiseMin()
182     : _impl(support::cpp14::make_unique<Impl>())
183 {
184 }
185 NEElementwiseMin::NEElementwiseMin(NEElementwiseMin &&) = default;
186 NEElementwiseMin &NEElementwiseMin::operator=(NEElementwiseMin &&) = default;
187 NEElementwiseMin::~NEElementwiseMin()                              = default;
188 
configure(ITensor * input1,ITensor * input2,ITensor * output,const ActivationLayerInfo & act_info)189 void NEElementwiseMin::configure(ITensor *input1, ITensor *input2, ITensor *output, const ActivationLayerInfo &act_info)
190 {
191     ARM_COMPUTE_UNUSED(act_info);
192     _impl->src_0 = input1;
193     _impl->src_1 = input2;
194     _impl->dst   = output;
195     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwiseMin>();
196     _impl->op->configure(input1->info(), input2->info(), output->info());
197 }
198 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)199 Status NEElementwiseMin::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
200 {
201     ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled());
202     return experimental::NEElementwiseMin::validate(input1, input2, output);
203 }
204 
run()205 void NEElementwiseMin::run()
206 {
207     ITensorPack pack;
208     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
209     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
210     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
211     _impl->op->run(pack);
212 }
213 
214 struct NEElementwiseSquaredDiff::Impl
215 {
216     const ITensor                                          *src_0{ nullptr };
217     const ITensor                                          *src_1{ nullptr };
218     ITensor                                                *dst{ nullptr };
219     std::unique_ptr<experimental::NEElementwiseSquaredDiff> op{ nullptr };
220 };
221 
NEElementwiseSquaredDiff()222 NEElementwiseSquaredDiff::NEElementwiseSquaredDiff()
223     : _impl(support::cpp14::make_unique<Impl>())
224 {
225 }
226 NEElementwiseSquaredDiff::NEElementwiseSquaredDiff(NEElementwiseSquaredDiff &&) = default;
227 NEElementwiseSquaredDiff &NEElementwiseSquaredDiff::operator=(NEElementwiseSquaredDiff &&) = default;
228 NEElementwiseSquaredDiff::~NEElementwiseSquaredDiff()                                      = default;
229 
configure(ITensor * input1,ITensor * input2,ITensor * output,const ActivationLayerInfo & act_info)230 void NEElementwiseSquaredDiff::configure(ITensor *input1, ITensor *input2, ITensor *output, const ActivationLayerInfo &act_info)
231 {
232     ARM_COMPUTE_UNUSED(act_info);
233     _impl->src_0 = input1;
234     _impl->src_1 = input2;
235     _impl->dst   = output;
236     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwiseSquaredDiff>();
237     _impl->op->configure(input1->info(), input2->info(), output->info());
238 }
239 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)240 Status NEElementwiseSquaredDiff::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
241 {
242     ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled());
243     return experimental::NEElementwiseSquaredDiff::validate(input1, input2, output);
244 }
245 
run()246 void NEElementwiseSquaredDiff::run()
247 {
248     ITensorPack pack;
249     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
250     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
251     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
252     _impl->op->run(pack);
253 }
254 
255 struct NEElementwiseDivision::Impl
256 {
257     const ITensor                                       *src_0{ nullptr };
258     const ITensor                                       *src_1{ nullptr };
259     ITensor                                             *dst{ nullptr };
260     std::unique_ptr<experimental::NEElementwiseDivision> op{ nullptr };
261 };
262 
NEElementwiseDivision()263 NEElementwiseDivision::NEElementwiseDivision()
264     : _impl(support::cpp14::make_unique<Impl>())
265 {
266 }
267 NEElementwiseDivision::NEElementwiseDivision(NEElementwiseDivision &&) = default;
268 NEElementwiseDivision &NEElementwiseDivision::operator=(NEElementwiseDivision &&) = default;
269 NEElementwiseDivision::~NEElementwiseDivision()                                   = default;
270 
configure(ITensor * input1,ITensor * input2,ITensor * output,const ActivationLayerInfo & act_info)271 void NEElementwiseDivision::configure(ITensor *input1, ITensor *input2, ITensor *output, const ActivationLayerInfo &act_info)
272 {
273     ARM_COMPUTE_UNUSED(act_info);
274     _impl->src_0 = input1;
275     _impl->src_1 = input2;
276     _impl->dst   = output;
277     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwiseDivision>();
278     _impl->op->configure(input1->info(), input2->info(), output->info());
279 }
280 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)281 Status NEElementwiseDivision::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
282 {
283     ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled());
284     return experimental::NEElementwiseDivision::validate(input1, input2, output);
285 }
286 
run()287 void NEElementwiseDivision::run()
288 {
289     ITensorPack pack;
290     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
291     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
292     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
293     _impl->op->run(pack);
294 }
295 
296 struct NEElementwisePower::Impl
297 {
298     const ITensor                                    *src_0{ nullptr };
299     const ITensor                                    *src_1{ nullptr };
300     ITensor                                          *dst{ nullptr };
301     std::unique_ptr<experimental::NEElementwisePower> op{ nullptr };
302 };
303 
NEElementwisePower()304 NEElementwisePower::NEElementwisePower()
305     : _impl(support::cpp14::make_unique<Impl>())
306 {
307 }
308 NEElementwisePower::NEElementwisePower(NEElementwisePower &&) = default;
309 NEElementwisePower &NEElementwisePower::operator=(NEElementwisePower &&) = default;
310 NEElementwisePower::~NEElementwisePower()                                = default;
311 
configure(ITensor * input1,ITensor * input2,ITensor * output,const ActivationLayerInfo & act_info)312 void NEElementwisePower::configure(ITensor *input1, ITensor *input2, ITensor *output, const ActivationLayerInfo &act_info)
313 {
314     ARM_COMPUTE_UNUSED(act_info);
315     _impl->src_0 = input1;
316     _impl->src_1 = input2;
317     _impl->dst   = output;
318     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwisePower>();
319     _impl->op->configure(input1->info(), input2->info(), output->info());
320 }
321 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)322 Status NEElementwisePower::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
323 {
324     ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled());
325     return experimental::NEElementwisePower::validate(input1, input2, output);
326 }
327 
run()328 void NEElementwisePower::run()
329 {
330     ITensorPack pack;
331     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
332     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
333     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
334     _impl->op->run(pack);
335 }
336 
337 template <ComparisonOperation COP>
338 struct NEElementwiseComparisonStatic<COP>::Impl
339 {
340     const ITensor                                                    *src_0{ nullptr };
341     const ITensor                                                    *src_1{ nullptr };
342     ITensor                                                          *dst{ nullptr };
343     std::unique_ptr<experimental::NEElementwiseComparisonStatic<COP>> op{ nullptr };
344 };
345 
346 template <ComparisonOperation COP>
NEElementwiseComparisonStatic()347 NEElementwiseComparisonStatic<COP>::NEElementwiseComparisonStatic()
348     : _impl(support::cpp14::make_unique<Impl>())
349 {
350 }
351 template <ComparisonOperation COP>
352 NEElementwiseComparisonStatic<COP>::NEElementwiseComparisonStatic(NEElementwiseComparisonStatic &&) = default;
353 template <ComparisonOperation       COP>
354 NEElementwiseComparisonStatic<COP> &NEElementwiseComparisonStatic<COP>::operator=(NEElementwiseComparisonStatic &&) = default;
355 template <ComparisonOperation       COP>
356 NEElementwiseComparisonStatic<COP>::~NEElementwiseComparisonStatic() = default;
357 
358 template <ComparisonOperation COP>
configure(ITensor * input1,ITensor * input2,ITensor * output)359 void NEElementwiseComparisonStatic<COP>::configure(ITensor *input1, ITensor *input2, ITensor *output)
360 {
361     _impl->src_0 = input1;
362     _impl->src_1 = input2;
363     _impl->dst   = output;
364     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwiseComparisonStatic<COP>>();
365     _impl->op->configure(input1->info(), input2->info(), output->info());
366 }
367 
368 template <ComparisonOperation COP>
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output)369 Status NEElementwiseComparisonStatic<COP>::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
370 {
371     return experimental::NEElementwiseComparisonStatic<COP>::validate(input1, input2, output);
372 }
373 
374 template <ComparisonOperation COP>
run()375 void                          NEElementwiseComparisonStatic<COP>::run()
376 {
377     ITensorPack pack;
378     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
379     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
380     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
381     _impl->op->run(pack);
382 }
383 
384 struct NEElementwiseComparison::Impl
385 {
386     const ITensor                                         *src_0{ nullptr };
387     const ITensor                                         *src_1{ nullptr };
388     ITensor                                               *dst{ nullptr };
389     std::unique_ptr<experimental::NEElementwiseComparison> op{ nullptr };
390 };
391 
NEElementwiseComparison()392 NEElementwiseComparison::NEElementwiseComparison()
393     : _impl(support::cpp14::make_unique<Impl>())
394 {
395 }
396 NEElementwiseComparison::NEElementwiseComparison(NEElementwiseComparison &&) = default;
397 NEElementwiseComparison &NEElementwiseComparison::operator=(NEElementwiseComparison &&) = default;
398 NEElementwiseComparison::~NEElementwiseComparison()                                     = default;
399 
configure(ITensor * input1,ITensor * input2,ITensor * output,ComparisonOperation op)400 void NEElementwiseComparison::configure(ITensor *input1, ITensor *input2, ITensor *output, ComparisonOperation op)
401 {
402     _impl->src_0 = input1;
403     _impl->src_1 = input2;
404     _impl->dst   = output;
405     _impl->op    = arm_compute::support::cpp14::make_unique<experimental::NEElementwiseComparison>();
406     _impl->op->configure(input1->info(), input2->info(), output->info(), op);
407 }
408 
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,ComparisonOperation op)409 Status NEElementwiseComparison::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ComparisonOperation op)
410 {
411     return experimental::NEElementwiseComparison::validate(input1, input2, output, op);
412 }
413 
run()414 void NEElementwiseComparison::run()
415 {
416     ITensorPack pack;
417     pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
418     pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
419     pack.add_tensor(TensorType::ACL_DST, _impl->dst);
420     _impl->op->run(pack);
421 }
422 
423 // Supported Specializations
424 template class NEElementwiseComparisonStatic<ComparisonOperation::Equal>;
425 template class NEElementwiseComparisonStatic<ComparisonOperation::NotEqual>;
426 template class NEElementwiseComparisonStatic<ComparisonOperation::Greater>;
427 template class NEElementwiseComparisonStatic<ComparisonOperation::GreaterEqual>;
428 template class NEElementwiseComparisonStatic<ComparisonOperation::Less>;
429 template class NEElementwiseComparisonStatic<ComparisonOperation::LessEqual>;
430 } // namespace arm_compute
431