blob: 099abf6f9639caf67fb2681bc914c1783a23537b [file] [log] [blame]
Georgios Pinitas58bce682020-11-13 11:38:58 +00001/*
2 * Copyright (c) 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 "tests/validation/reference/Logical.h"
Sang-Hoon Park75eea332020-11-13 13:44:13 +000025#include "src/core/KernelTypes.h"
26#include "tests/framework/Asserts.h"
Georgios Pinitas58bce682020-11-13 11:38:58 +000027
28namespace arm_compute
29{
30namespace test
31{
32namespace validation
33{
34namespace reference
35{
36template <typename T>
Sang-Hoon Park75eea332020-11-13 13:44:13 +000037T logical_binary_op(arm_compute::kernels::LogicalOperation op, T src1, T src2)
Georgios Pinitas58bce682020-11-13 11:38:58 +000038{
39 switch(op)
40 {
Sang-Hoon Park75eea332020-11-13 13:44:13 +000041 case arm_compute::kernels::LogicalOperation::And:
Georgios Pinitas58bce682020-11-13 11:38:58 +000042 return src1 && src2;
Sang-Hoon Park75eea332020-11-13 13:44:13 +000043 case arm_compute::kernels::LogicalOperation::Or:
Georgios Pinitas58bce682020-11-13 11:38:58 +000044 return src1 || src2;
Sang-Hoon Park75eea332020-11-13 13:44:13 +000045 // The following operators are either invalid or not binary operator
46 case arm_compute::kernels::LogicalOperation::Not:
Sang-Hoon Park2dbc5862020-11-18 13:52:11 +000047 // fall through
Sang-Hoon Park75eea332020-11-13 13:44:13 +000048 case arm_compute::kernels::LogicalOperation::Unknown:
Sang-Hoon Park2dbc5862020-11-18 13:52:11 +000049 // fall through
Georgios Pinitas58bce682020-11-13 11:38:58 +000050 default:
Sang-Hoon Park75eea332020-11-13 13:44:13 +000051 ARM_COMPUTE_ASSERT(true);
Georgios Pinitas58bce682020-11-13 11:38:58 +000052 }
Sang-Hoon Park75eea332020-11-13 13:44:13 +000053 return T{};
Georgios Pinitas58bce682020-11-13 11:38:58 +000054}
55
56template <size_t dim>
57struct BroadcastUnroll
58{
59 template <typename T>
Sang-Hoon Park75eea332020-11-13 13:44:13 +000060 static void unroll(arm_compute::kernels::LogicalOperation op, const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, SimpleTensor<T> &dst,
Georgios Pinitas58bce682020-11-13 11:38:58 +000061 Coordinates &id_src1, Coordinates &id_src2, Coordinates &id_dst)
62 {
63 const bool src1_is_broadcast = (src1.shape()[dim - 1] != dst.shape()[dim - 1]);
64 const bool src2_is_broadcast = (src2.shape()[dim - 1] != dst.shape()[dim - 1]);
65
66 id_src1.set(dim - 1, 0);
67 id_src2.set(dim - 1, 0);
68 id_dst.set(dim - 1, 0);
69#if defined(_OPENMP)
70 #pragma omp parallel for
71#endif /* _OPENMP */
72 for(size_t i = 0; i < dst.shape()[dim - 1]; ++i)
73 {
74 BroadcastUnroll < dim - 1 >::unroll(op, src1, src2, dst, id_src1, id_src2, id_dst);
75
76 id_src1[dim - 1] += !src1_is_broadcast;
77 id_src2[dim - 1] += !src2_is_broadcast;
78 ++id_dst[dim - 1];
79 }
80 }
81};
82
83template <>
84struct BroadcastUnroll<0>
85{
86 template <typename T>
Sang-Hoon Park75eea332020-11-13 13:44:13 +000087 static void unroll(arm_compute::kernels::LogicalOperation op, const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, SimpleTensor<T> &dst,
Georgios Pinitas58bce682020-11-13 11:38:58 +000088 Coordinates &id_src1, Coordinates &id_src2, Coordinates &id_dst)
89 {
Sang-Hoon Park75eea332020-11-13 13:44:13 +000090 dst[coord2index(dst.shape(), id_dst)] = logical_binary_op(op, src1[coord2index(src1.shape(), id_src1)], src2[coord2index(src2.shape(), id_src2)]);
Georgios Pinitas58bce682020-11-13 11:38:58 +000091 }
92};
93
94template <typename T>
95SimpleTensor<T> logical_or(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
96{
97 Coordinates id_src1{};
98 Coordinates id_src2{};
99 Coordinates id_dst{};
100 SimpleTensor<T> dst{ TensorShape::broadcast_shape(src1.shape(), src2.shape()), src1.data_type() };
101
Sang-Hoon Park75eea332020-11-13 13:44:13 +0000102 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(arm_compute::kernels::LogicalOperation::Or, src1, src2, dst, id_src1, id_src2, id_dst);
Georgios Pinitas58bce682020-11-13 11:38:58 +0000103
104 return dst;
105}
106
107template <typename T>
108SimpleTensor<T> logical_and(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
109{
110 Coordinates id_src1{};
111 Coordinates id_src2{};
112 Coordinates id_dst{};
113 SimpleTensor<T> dst{ TensorShape::broadcast_shape(src1.shape(), src2.shape()), src1.data_type() };
114
Sang-Hoon Park75eea332020-11-13 13:44:13 +0000115 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(arm_compute::kernels::LogicalOperation::And, src1, src2, dst, id_src1, id_src2, id_dst);
Georgios Pinitas58bce682020-11-13 11:38:58 +0000116
117 return dst;
118}
119
120template <typename T>
121SimpleTensor<T> logical_not(const SimpleTensor<T> &src)
122{
123 SimpleTensor<T> dst(src.shape(), src.data_type());
124#if defined(_OPENMP)
125 #pragma omp parallel for
126#endif /* _OPENMP */
127 for(int i = 0; i < src.num_elements(); ++i)
128 {
129 dst[i] = !src[i];
130 }
131
132 return dst;
133}
134
135template SimpleTensor<uint8_t> logical_or(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2);
136template SimpleTensor<uint8_t> logical_and(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2);
137template SimpleTensor<uint8_t> logical_not(const SimpleTensor<uint8_t> &src1);
138} // namespace reference
139} // namespace validation
140} // namespace test
Sang-Hoon Park75eea332020-11-13 13:44:13 +0000141} // namespace arm_compute